Docker: In Dockerfile, copy files temporarily, but not for final image

Building an image works as follows.

... The docker build command will use whatever directory contains the Dockerfile as the build context (including all of its subdirectories). The build context will be sent to the Docker daemon before building the image, which means if you use / as the source repository, the entire contents of your hard drive will get sent to the daemon ...

See https://docs.docker.com/reference/builder/

I see no way to achieve what you want. There are two options:

  1. Having all the build dependencies inside the image and build your JAR file inside the container. That bloats your image.

  2. I would recommend to build your JAR separately and just ADD the executable and config files when they are build. That means all build dependencies must be available on your development environment, but your image is as small as it can be.


There is an experimental build flag --squash to summarize everything into one layer.

For example, docker build --squash -t <tag> .

The documentation https://docs.docker.com/engine/reference/commandline/image_build/#options.

The Github discussion https://github.com/moby/moby/issues/332.

How to enable experimental features in the daemon? https://github.com/docker/docker-ce/blob/master/components/cli/experimental/README.md


Another workaround would be to use a web server to pull in the data.

  1. Start a web server, serving your temporarily needed files. You may use

    python3 -m http.server 8000 --bind 127.0.0.1 &
    

    to serve the current directory, see https://docs.python.org/3/library/http.server.html#http-server-cli

  2. In your Dockerfile get the file, perform actions, delete the files in a single RUN

    RUN wget http://localhost:8000/big.tar && tar xf big.tar && ... && rm big.tar
    
  3. Build image with --network host to be able to access localhost


Docker introduced so called "multi stage builds". With them, you can avoid having unnecessary files in your image. Your Dockerfile would look like this:

FROM ubuntu AS build
COPY . /src
# run your build

FROM ubuntu
RUN mkdir -p /dist/
COPY --from=build /src/my.object /dist/

The principle is simple. In the first FROM you name your build. In the second FROM you can use the COPY --from=-parameter to copy files from your first build to your second. The second build is the one which results in an usable image later.

If you want to test the results of your build instead the resulting image, you can use docker build --target build myimage:build .. The resulting image only includes the first FROM in your Dockerfile.

Try to use the same base image für your "build" and the final image. Different base images might result in strange bugs or even segfaults.

For more information: https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds

Tags:

Docker