shiplift icon indicating copy to clipboard operation
shiplift copied to clipboard

Image building should respect .dockerignore

Open NAlexPear opened this issue 5 years ago • 4 comments

In contrast to the docker build command provided by the Docker CLI, the build method on the Images struct does not respect .dockerignore files. This is an issue especially for Rust crate build contexts that often have a target directory of a few GB or more, and are very slow to make it through the tarbell::dir steps of shiplift's build process.

A couple of suggested approaches that could solve the problem:

  1. Respect .dockerignore files by default: this would technically be a breaking change, but would better align with the Docker CLI equivalent command
  2. Add an option to BuildOptions enabling .dockerignore support: this seems surprising if it's not enabled by default, but this change wouldn't be a breaking change, at least
  3. Allow users to provide their own tarballs to a build command: rather than dealing with the file system directly, users could use their own tarball-ing scheme and submit that archive directly to a separate build command (build_from_archive, perhaps?)

If any of those :point_up: sound like good options, I'd be happy to whip up a PR.

NAlexPear avatar Oct 23 '19 17:10 NAlexPear

You're right. I think 1 sounds like a good default. I don't think there would be many cases to ignore a docker ignore if a docker ignore is present so I'd say you could skip 2. 3 sounds very reasonable but likely a rare case. I don't think I've ever hand built a tar ball and gave that to docker to run.

I believe there's a few off the shelf gitignore parsing crates that you may be able to leverage to managing a docker ignore. I believe it follows the same syntax.

softprops avatar Oct 23 '19 22:10 softprops

Sounds good, let me tackle option 1 tonight. It won't be quite as simple as dropping in an existing gitignore crate, since .dockerignore syntax is based on golang's filepath.Match, and .gitignore is its own thing, but I need to support that syntax anyway in my own project.

Speaking of option three: my use case is a command-line tool that templates Dockerfiles and spins up containers for users, so it's pretty convenient to be able to generate my own tarball without writing a Dockerfile (and .dockerignore, soon) to the file system. This use case could also be addressed more generally by the ability to provide the contents of a Dockerfile instead of a path to an existing file, like one is able to do with the CLI by providing the contents over STDIN (e.g. echo "FROM rust" | docker build -f - .). I've implemented the former in my fork of shiplift, but wasn't sure if that was worthy of its own feature request or inclusion in shiplift itself.

NAlexPear avatar Oct 23 '19 23:10 NAlexPear

Was just looking at the docker image build implementation to figure out how it works. Here's the code that handles tarballing and dockerignore, maybe it's a useful reference if anyone wants to implement this: https://github.com/docker/cli/blob/04dad42c3c82733c3c82b1f859829d62d8608128/cli/command/image/build.go#L293

cswinter avatar Apr 18 '21 02:04 cswinter

Random semi-related thought, tarballing the entire context dir seems quite wasteful and requires thoughtfulness around where to put the Dockerfile, does anyone know a good reason why it wouldn't be possible to parse the Dockerfile and include just files that are referenced by ADD or COPY commands?

cswinter avatar Apr 18 '21 02:04 cswinter