I am trying to optimize my Docker image and I need to run specific commands only if a certain build argument is provided. For example, I want to install debugging tools only in my development environment but skip them for production to keep the image size small. Since Dockerfile syntax doesn't seem to support a standard "if" statement, what is the best practice for handling conditional steps during the build process without creating multiple separate Dockerfiles?
3 answers
While Docker doesn't have an IF keyword, you can achieve this by using a combination of ARG and shell-level conditional logic within a RUN instruction. You define a build argument at the top, and then use standard bash syntax to check its value. For instance: ARG ENV=prod followed by RUN if [ "$ENV" = "dev" ]; then apt-get install -y vim; fi. This keeps your Dockerfile clean and allows you to pass the variable during build time using the --build-arg flag.
It is also worth looking into Multi-stage builds, which is a more "Docker-native" way to handle different environments by separating the build stages and only copying what is necessary into the final production image
Are you planning to use these conditions for installing packages, or are you trying to conditionally copy configuration files into the image? I ask because if you are dealing with files, it is often much easier to manage this through your CI/CD pipeline or by using different .dockerignore files rather than bloating the RUN command with complex shell scripts.
You can't use shell logic on COPY or ADD. For files, use the "Multi-stage" build approach where you name your stages and only include the files you need in the final alias.
Sandra is correct. You can't wrap a COPY in a bash if. A great workaround is to use a build script that renames the correct config file to a generic name like config.actual before the docker build command starts. That way, the Dockerfile always finds the file it's looking for regardless of the environment.
Kevin, I am actually trying to do both. I have a specific nginx.conf for staging and another for production. If I use the shell method Deborah suggested, can I also conditionally execute the COPY command, or does that approach only work for RUN instructions? I'm worried that the COPY instruction might fail if the file doesn't exist for a specific environment.