Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a "build dev" command #1357

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

flavorjones
Copy link
Member

@flavorjones flavorjones commented Jan 15, 2025

Context

The problem I'm trying to solve with this PR is: During the development process, how can a developer iterate quickly on their container?

The primary obstacles to using Kamal to build development images in this way are:

  • build push uses the config to determine the build context, and the default is to make a pristine build from a clean git clone. There's no command option override that configuration for a single invocation.
  • build push will push to the registry every time! For this use case, it's more likely the developer will simply want to push to the local docker image store.

A secondary obstacle is the danger of accidentally using a development image (built from the dirty working directory) in production! If we're going to support development images, we should probably tag them explicitly to avoid confusion.

Alternatives considered

It's possible, but not trivial, to build the container in a manner that addresses this use case by running docker buildx from the commandline. However, for containers with build steps that require secrets to be injected, this can quickly become very complicated.

Proposed solution

I've broken this feature out into two commits.

First, I introduce some flexibility into the kamal build push command with an --output option which allows Kamal users to specify where they would like the build result to be exported. The default value is "registry" to reflect the current behavior of build push.

Any value provided to this option will be passed to the docker buildx build command as a --output=type=<VALUE> flag. For example, the following command will push to the local docker image store:

kamal build push --output=docker

Second, I introduce a new command, build dev which is similar to build push but:

  • always uses the local working directory as the build context
  • exports the build result to the local docker image store
  • tags the build result with a -dirty suffix

The command also supports the --output option.

Other notes

Documentation PR is basecamp/kamal-site#158 (or will be once I update it).

@flavorjones flavorjones deleted the flavorjones-kamal-build-local branch January 15, 2025 20:37
@flavorjones flavorjones restored the flavorjones-kamal-build-local branch January 15, 2025 20:38
@flavorjones flavorjones reopened this Jan 15, 2025
@nickhammond
Copy link
Contributor

@flavorjones Does this introduce a different behavior than setting your build context to the current directory with context: .?

https://kamal-deploy.org/docs/configuration/builders/#build-context

@flavorjones
Copy link
Member Author

flavorjones commented Jan 15, 2025

@nickhammond I'm not sure I understand the question? The idea behind this is to build a one-off container that doesn't get pushed anywhere by running a different command -- without having to write a new config.

Part of the behavior is to build with the current directory as context, sure. The different behaviors are described in the description above.

Does that answer your question?

@nickhammond
Copy link
Contributor

nickhammond commented Jan 16, 2025

@flavorjones Is the use case to warm the build cache? Or just to verify that your image is building successfully without dealing with the login and push process?

It's nice to have the standalone build process but dev made me think it was something you'd use in your development environment, similar to say if you develop locally utilizing containers(https://github.com/rails/docked) or bin/dev.

What about kamal build local?

@flavorjones
Copy link
Member Author

@nickhammond The use case here is that I want to iterate on the contents of my Dockerfile.

In particular, I was running into an issue with packages installed on the base image, so I wanted to quickly run through the process of:

  1. make change to Dockerfile
  2. build image
  3. run test in the image using docker run

It's possible to build the image with docker build, but in particular if I've got secrets used during the build process, it's troublesome to either inject them or work around their absence.

I got some feedback on this PR from my colleagues at 37signals that it could probably be merged into build push with a --local flag or something similar. I'll be revising this taking that feedback into account.

@nickhammond
Copy link
Contributor

@flavorjones Great! It'll be really handy to have that when getting an app going. It has definitely been clunky to maintain a docker build script outside of kamal for testing because of env clear/secrets as you mentioned.

@flavorjones flavorjones force-pushed the flavorjones-kamal-build-local branch 2 times, most recently from 13a47d0 to 528aa3e Compare January 20, 2025 21:36
@flavorjones
Copy link
Member Author

I've rewritten this PR to decouple the build result export from the dirty working directory features. See the description for a longer explanation.

@flavorjones flavorjones force-pushed the flavorjones-kamal-build-local branch 4 times, most recently from 2f13b3a to 74f4eb2 Compare January 20, 2025 21:57
@flavorjones flavorjones marked this pull request as draft January 20, 2025 22:11
which controls where the build result is exported.

The default value is "registry" to reflect the current behavior of
`build push`.

Any value provided to this option will be passed to the `buildx build`
command as a `--output=type=<VALUE>` flag.

For example, the following command will push to the local docker image
store:

    kamal build push --output=docker

squash
@flavorjones flavorjones force-pushed the flavorjones-kamal-build-local branch from 74f4eb2 to 93644af Compare January 20, 2025 23:37
@flavorjones flavorjones marked this pull request as ready for review January 20, 2025 23:42
which will build a "dirty" image using the working directory.

This command is different from `build push` in two important ways:

- the image tags will have a suffix of `-dirty`
- the export action is "docker", pushing to the local docker image store

The command also supports the `--output` option just added to `build
push` to override that default.

This command is intended to allow developers to quickly iterate on a
docker image built from their local working directory while avoiding
any confusion with a pristine image built from a git clone, and
keeping those images on the local dev system by default.
@flavorjones flavorjones force-pushed the flavorjones-kamal-build-local branch from 93644af to 2127f17 Compare January 20, 2025 23:52
@flavorjones flavorjones requested a review from djmb January 21, 2025 00:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants