45

From the docker build docs, you can specify a --target flag with the name of the stage to build it. Also, the same is specified in the multi-stage build docs.

When you build your image, you don’t necessarily need to build the entire Dockerfile including every stage. You can specify a target build stage. The following command assumes you are using the previous Dockerfile but stops at the stage named builder:

$ docker build --target builder -t alexellis2/href-counter:latest .

I have a single Dockerfile to build my project. It has multiple stages:

# development
FROM node:carbon as development
...

# e2e tests
FROM node:carbon as puppeteer
...
COPY --chown=puppeteer:puppeteer --from=development /app /home/puppeteer
...

# prod build
FROM node:carbon as build
...

# prod image behind webserver
FROM nginx as prod
...
COPY --from=build /app/build /usr/share/nginx/html
...

When I try to build for prod stage with:

docker build -t my-app --target prod .

I see the logs that it is building all the stages, causing the build to take very long time.

I want it to build just the target I specify (and its stage "dependency"), so that it builds the build stage and then the prod stage.

What am I doing wrong or what am I missing?

Note: I am also aware that maybe I have wrong expectations about what the multi-stage build does, but the documentation makes it sounds as if you can build the target you want instead of the whole file so I'll assume that's the case.

Community
  • 1
  • 1
Christopher Francisco
  • 15,672
  • 28
  • 94
  • 206

4 Answers4

61

As of Docker 18.09 you can use BuildKit. One of the benefits is skipping unused stages, so all you should need to do is build with DOCKER_BUILDKIT=1 docker build -t my-app --target prod .

Reference

Kaka Ruto
  • 4,581
  • 1
  • 31
  • 39
mikeweather
  • 611
  • 1
  • 5
  • 4
  • 4
    @MarcellodeSales, @mikeweather -- it looks like this still uses the cache if the stage has already been built. `=> CACHED [prod 4/4]` is there a way to force only the last stage (prod) to not use the cache but allow the first stages to use the cache? – sdc Jun 14 '19 at 04:10
27

In docker build docs it says When building a Dockerfile with multiple build stages, --target can be used to specify an intermediate build stage by name as a final stage for the resulting image. Commands after the target stage will be skipped.

This means, that when you specify --target option, you only specifying the last target which will be built so all before that will be included in the build process. To build multiple environments you probably need to have two Dockerfiles.

ansidev
  • 361
  • 1
  • 3
  • 17
ttomalak
  • 1,936
  • 13
  • 19
  • 8
    This is BEFORE 18.06 (experimental) and 18.09 (release) of BuildKit... Explained at https://docs.docker.com/develop/develop-images/build_enhancements/ – Marcello DeSales Apr 17 '19 at 21:29
  • @MarcellodeSales what changes in those versions? The answer still looks correct — is it? – Maximilian Feb 05 '21 at 05:37
  • I'm using 19.03.13-ce and I see the opposite version. I want to build all stages (since my final stage is a test), but it's only building the stage I specified as target. – falsePockets Mar 16 '21 at 00:33
0

In addition to all other answers, if one wants to make sure that the current target stage is force re-built even if it has already been cached without rebuilding the previous dependent stages, once can use the docker build --no-cache-filter flag.

An example, given you have a multi-stage Dockerfile with a 'test' stage, would be:

docker build --no-cache-filter test --target test --tag your-image-name:version .
0

Today BuildKit is the default builder, so you don't need to take any further actions. If your Docker is latest version, then the default behaviour of this command:

docker build --target builder -t alexellis2/href-counter:latest .

is exactly what you expected. Unused build stages are skipped.

From the BuildKit`s page:

BuildKit is the default builder for users on Docker Desktop and Docker Engine v23.0 and later.

Dimitar Atanasov
  • 141
  • 1
  • 15