Reputation: 653
I have a Dockerfile that currently uses the node:10.21.0-buster-slim
as its base. That works well for running in production since I get a nice small image (I'd rather not use Alpine since I've had issues with this code on Alpine previously and I'm already stuck running a MySQL image based on buster-slim in production). However, for development, it would obviously be nice to have an image with more tools for diagnosing issues that crop up (presumably based on either debian:buster
or buildpack-deps:buster
).
Is there some way I can run the same steps with two different base images without having to duplicate the Dockerfile contents? I assume the answer is yes with some multi-stage build magic, but I haven't figured out how that's supposed to work. In my dream world there are also a few minor differences between the dev and prod build steps (e.g. the --only=production
argument to npm install
, but I'm willing to sacrifice that if I have to to avoid maintaining two nearly identical Dockerfiles.
Upvotes: 3
Views: 1840
Reputation: 5337
Multi-stage build magic is one way to do it:
ARG TARGET="prod"
FROM node:10.21.0-buster-slim as prod
# do stuff
FROM debian:buster as dev
# do other stuff, like apt-get install nodejs
FROM ${TARGET}
# anything in common here
Build the image with DOCKER_BUILDKIT=1 docker build --build-arg 'TARGET=dev' [...]
to get the development-specific stuff. Build image with DOCKER_BUILDKIT=1 docker build [...]
to get the existing "prod" stuff. Switch out the value in the first ARG
line to change the default behavior if the --build-arg
flag is omitted.
Using the DOCKER_BUILDKIT=1
environment flag is important; if you leave it out, builds will always do all three stages. This becomes a much bigger problem the more phases you have and the more conditional stuff you do. When you include it, the build executes the last stage in the file, and only the previous stages that are necessary to complete the multi-stage build. Meaning, for TARGET=prod
, the dev
stage never executes, and vice versa.
Upvotes: 3