Skip to content

Comments

feat: add support for using CLI container clients#8661

Merged
reedham-aws merged 16 commits intoaws:feat-buildkitfrom
reedham-aws:buildkit-tests
Feb 20, 2026
Merged

feat: add support for using CLI container clients#8661
reedham-aws merged 16 commits intoaws:feat-buildkitfrom
reedham-aws:buildkit-tests

Conversation

@reedham-aws
Copy link
Contributor

Which issue(s) does this change fix?

#3972, #8656, #3852

Why is this change necessary?

Currently, the docker-py SDK does not support BuildKit: docker/docker-py#2230. This means that in order for sam build to use BuildKit, we must use the Docker (or Finch) CLI.

How does it address the issue?

This change adds a BuildClient class that acts as a parent to either the SDKBuildClient or the CLIBuildClient. If a user passes a sam build argument of --use-buildkit, the CLIBuildClient is used with either docker buildx build or finch build ... (Finch uses buildkit by default).

What side effects does this change have?

For existing builds, there shouldn't be any. Using the CLI is entirely opt in, and the SDK build is doing the same thing as before with only a thin layer in between. There could be a difference between the SDK build and the CLI build for different applications (especially for things like cross platform builds, which buildkit is for). There also isn't any change to the detection of which build engine to use, so it shouldn't change where Docker/Finch is used.

Mandatory Checklist

PRs will only be reviewed after checklist is complete

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@reedham-aws reedham-aws requested a review from a team as a code owner February 16, 2026 17:27
@github-actions github-actions bot added area/local/start-api sam local start-api command area/build sam build command area/local/invoke sam local invoke command area/local/start-invoke pr/internal labels Feb 16, 2026
@reedham-aws reedham-aws added area/docker area/finch and removed area/local/start-api sam local start-api command area/local/invoke sam local invoke command area/local/start-invoke labels Feb 16, 2026
This change also refactors a lot of docker specific things to be "container_client" rather than "docker_client".
In addition, moving from instantiating the image build client in build context to lazily doing it in the app builder.
@reedham-aws reedham-aws requested a review from tobixlea February 17, 2026 22:40
result = subprocess.run(
["docker", "buildx", "version"],
capture_output=True,
check=True,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If docker buildx version fails, it raises CalledProcessError before the returncode != 0 check is ever reached. This should use check=False or wrap in a try/except for CalledProcessError.

The Finch path has the same issue.

Copy link
Contributor Author

@reedham-aws reedham-aws Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this to be check=False. I originally had let it fall through to the if result.returncode != 0, but then ruff didn't like the lack of explicit check. After that I forgot about the original intention 🙃.

process.wait()

if process.returncode != 0:
yield {"error": f"Build failed with exit code {process.returncode}"}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not raise an exception. The caller function expects docker.errors.BuildError on build failure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good callout. I changed this to raise the error instead of stream like this. What I did above was capture the stdout and save it in a list called build_log, then pass that as the build_log for the docker.errors.BuildError, which has the following definition:

class BuildError(DockerException):
    def __init__(self, reason, build_log):
        super().__init__(reason)
        self.msg = reason
        self.build_log = build_log

I think this should be fine, although I guess if the logs are long enough memory usage could balloon. Let me know if you think that is an issue.

@reedham-aws reedham-aws requested a review from bnusunny February 19, 2026 00:59
@reedham-aws reedham-aws merged commit dff542b into aws:feat-buildkit Feb 20, 2026
40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants