DOCKERFILE(5)
π DOCKERFILE(5) π
Docker User Manuals πΈ this one is the Dockerfile page, bestie
π NAME π
Dockerfile - automate the steps of creating a Docker image β¨
π¦ INTRODUCTION π¦
okay so the Dockerfile is a config file that automates the steps of creating a Docker image π₯ it's kinda like a Makefile, if you've ever touched one. Docker reads instructions out of the Dockerfile so it can do all the steps you'd otherwise do by hand to make an image. to build an image, you just create a file called Dockerfile π
The Dockerfile describes every step taken to assemble the image. once your Dockerfile exists, you call the docker build command and pass it the path of the directory that contains your Dockerfile as the argument π«Ά
π SYNOPSIS π
INSTRUCTION arguments
For example:
FROM image
π DESCRIPTION π
A Dockerfile is a file that automates the steps of creating a Docker image β¨ and it's similar to a Makefile, so if that clicked for you, you're already ahead π
π USAGE π
docker build .
- Runs the steps and commits them, building a final image. ποΈ The path to the source repository tells the build where to find its context. The build is run by the Docker daemon, not the CLI, so the whole context has to be transferred to the daemon. The Docker CLI shows "Sending build context to Docker daemon" once that context is sent over.
docker build -t repository/tag .
- Specifies a repository and tag to save the new image under, if the build succeeds. π― The Docker daemon runs the steps one-by-one, committing the result to a new image when needed, and then finally outputs the ID of the new image. The Docker daemon automatically cleans up the context it was given π§Ή
Docker reuses intermediate images whenever possible π which significantly accelerates the docker build process. literally faster builds, slay π
π§ FORMAT π§
FROM image
FROM image:tag
FROM image@digest
- The
FROMinstruction sets the base image for subsequent instructions. π± A valid Dockerfile must haveFROMas its first instruction. The image can be any valid image, and it's super easy to start by pulling one from the public repositories. FROMmust be the first non-comment instruction in the Dockerfile. πFROMcan show up multiple times in a single Dockerfile so you can make multiple images π¦ Make a note of the last image ID output by the commit before each newFROMcommand.- If no tag is given to
FROM, Docker applies thelatesttag. If the tag you used doesn't exist, an error is returned π - If no digest is given to
FROM, Docker applies thelatesttag. If the tag you used doesn't exist, an error is returned π
π MAINTAINER π
MAINTAINERsets the Author field for the generated images. It's useful for giving users an email or URL for support π
π RUN π
RUN has two forms, and they're both giving different energy β¨
# the command is run in a shell - /bin/sh -c
RUN <command>
# Executable form
RUN ["executable", "param1", "param2"]
- The
RUNinstruction executes any commands in a new layer on top of the current image and commits the results. π¦ The committed image is used for the next step in the Dockerfile. - Layering
RUNinstructions and generating commits matches the core concepts of Docker π§ commits are cheap, and containers can be created from any point in the history of an image. It's kinda like source control. The exec form makes it possible to avoid shell string munging, and it also makes it possible toRUNcommands using a base image that does not contain/bin/shπ«Ά
Heads up bestie: the exec form is parsed as a JSON array, so you must use double-quotes (") around words, not single-quotes (') β οΈ
π¬ CMD π¬
CMD has three forms, each one iconic in its own way π
# Executable form
CMD ["executable", "param1", "param2"]`
# Provide default arguments to ENTRYPOINT
CMD ["param1", "param2"]`
# the command is run in a shell - /bin/sh -c
CMD command param1 param2
- There should be only one
CMDin a Dockerfile. If you list more than one, only the lastCMDtakes effect π - The main purpose of a
CMDis to provide defaults for an executing container. π These defaults may include an executable, or they can omit the executable. If they omit the executable, anENTRYPOINTmust be specified. - When used in the shell or exec formats, the
CMDinstruction sets the command to be executed when running the image π― - If you use the shell form of
CMD, the<command>executes in/bin/sh -c
Same warning as before, babe: the exec form is parsed as a JSON array, which means you must use double-quotes (") around words, not single-quotes (') π
FROM ubuntu
CMD echo "This is a test." | wc -
- If you run a command without a shell, you must express the command as a JSON array and give the full path to the executable. This array form is the preferred form of
CMDπ All additional parameters must be individually expressed as strings in the array:
FROM ubuntu
CMD ["/usr/bin/wc","--help"]
- To make the container run the same executable every time, use
ENTRYPOINTin combination withCMD⨠- If the user specifies arguments to
docker run, those specified commands override the default inCMDπ - Do not confuse
RUNwithCMD!! πRUNruns a command and commits the result.CMDexecutes nothing at build time, but specifies the intended command for the image π§
π·οΈ LABEL π·οΈ
LABEL has a couple of looks:
LABEL <key>=<value> [<key>=<value> ...]
or
LABEL <key>[ <value>]
LABEL <key>[ <value>]
...
- The
LABELinstruction adds metadata to an image. π A label is a key-value pair. To specify a label without a value, just use an empty string. To include spaces within a label value, use quotes and backslashes the same way you would in command-line parsing π
LABEL com.example.vendor="ACME Incorporated"
LABEL com.example.vendor "ACME Incorporated"
LABEL com.example.vendor.is-beta ""
LABEL com.example.vendor.is-beta=
LABEL com.example.vendor.is-beta=""
- An image can have more than one label. To specify multiple labels, separate each key-value pair by a space π
- Labels are additive, including
LABELs inFROMimages. As the system encounters and then applies a new label, new keys override any previous labels with identical keys π - To display an image's labels, use the
docker inspectcommand π
π STOPSIGNAL π
STOPSIGNAL <signal>
- The
STOPSIGNALinstruction sets the system call signal that will be sent to the container to exit. πͺ This signal can be a signal name in the formatSIG, for instanceSIGKILL, or an unsigned number that matches a position in the kernel's syscall table, for instance9. The default isSIGTERMif not defined β¨ - The image's default stopsignal can be overridden per container π― using the
--stop-signalflag ondocker-run(1)anddocker-create(1).
πͺ EXPOSE πͺ
EXPOSE <port> [<port>...]
- The
EXPOSEinstruction informs Docker that the container listens on the specified network ports at runtime. π‘ Docker uses this info to interconnect containers using links, and to set up port redirection on the host system π
πΏ ENV πΏ
ENV <key> <value>
- The
ENVinstruction sets the environment variable to the value<value>. π± This value is passed to all futureRUN,ENTRYPOINT, andCMDinstructions. It's functionally equivalent to prefixing the command with<key>=<value>π§ - Environment variables set with
ENVpersist when a container is run from the resulting image πΎ Usedocker inspectto inspect these values, and change them usingdocker run --env <key>=<value>.
Bestie, heads up: setting "ENV DEBIAN_FRONTEND=noninteractive" may cause unintended consequences, because it will persist when the container is run interactively, as with the following command π¬
docker run -t -i image bash
π¦ ADD π¦
ADD has two forms π
ADD <src> <dest>
# Required for paths with whitespace
ADD ["<src>",... "<dest>"]
- The
ADDinstruction copies new files, directories, or remote file URLs to the filesystem of the container at path<dest>π Multiple<src>resources may be specified, but if they are files or directories then they must be relative to the source directory that is being built (the context of the build) π - The
<dest>is the absolute path, or a path relative toWORKDIR, into which the source is copied inside the target container π― - If the
<src>argument is a local file in a recognized compression format (tar, gzip, bzip2, etc) then it is unpacked at the specified<dest>in the container's filesystem π - Only local compressed files will be unpacked. The URL download and archive unpacking features cannot be used together π ββοΈ
- All new directories are created with mode
0755and with the uid and gid of0π
okay so an ENTRYPOINT lets you set up your container like a little executable π§β¨ once you add one, the whole container acts like it's only that program, bestie π
The ENTRYPOINT instruction adds a command that does not get overwritten when you pass arguments to docker run. This is NOT how CMD works π so arguments you pass in can go straight to the entrypoint. For example, docker run <image> -d hands the -d argument to the ENTRYPOINT π¦
You can set parameters two ways: in the ENTRYPOINT JSON array (the preferred exec form from above), or with a CMD statement. Parameters inside the ENTRYPOINT are safe and won't get overwritten by docker run arguments π«Ά but parameters set through CMD will get overwritten by docker run arguments. Plot twist π
If you give the ENTRYPOINT a plain string, it runs inside /bin/sh -c, just like a CMD instruction:
FROM ubuntu
ENTRYPOINT wc -l -
So this image always takes stdin as input (that's what - means) and prints the number of lines (that's what -l means) β¨ To make that optional but still the default, use a CMD instead:
FROM ubuntu
CMD ["-l", "-"]
ENTRYPOINT ["/usr/bin/wc"]
VOLUME
VOLUME ["/data"]
The VOLUME instruction makes a mount point with the name you give it πΈ and marks it as holding externally-mounted volumes, either from the native host or from other containers.
USER
USER daemon
This sets the username or UID used to run the commands that come after it π
The USER instruction can also optionally set the group or GID. These examples are all valid:
USER [user | user:group | uid | uid:gid | user:gid | uid:group ]
Until the USER instruction shows up, everything runs as root π You can use USER as many times as you want in a Dockerfile, and it only affects the commands after it.
WORKDIR
WORKDIR /path/to/workdir
WORKDIR sets the working directory for the RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it π You can use it multiple times in one Dockerfile. Relative paths are defined relative to the path of the previous WORKDIR instruction. For example:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
In that example, the output of pwd is a/b/c β¨ so yeah, it stacks up, periodt π
ARG
ARG [=]
ARG defines a variable that users can pass in at build-time to the builder with the docker build command, using the --build-arg <varname>=<value> flag π If a user passes a build argument that wasn't defined in the Dockerfile, the build spits out a warning:
[Warning] One or more build-args [foo] were not consumed
The Dockerfile author can define one variable by writing ARG once, or a bunch of them by writing ARG more than once. For example, a valid Dockerfile:
FROM busybox
ARG user1
ARG buildno
...
A Dockerfile author can also give an ARG a default value:
FROM busybox
ARG user1=someuser
ARG buildno=1
...
If an ARG has a default and no value gets passed in at build-time, the builder uses the default π«Ά
An ARG variable comes into effect from the line where it's defined in the Dockerfile. It does NOT come into effect from wherever the argument gets used on the command line or elsewhere π Take this Dockerfile:
1 FROM busybox
2 USER ${user:-some_user}
3 ARG user
4 USER $user
...
A user builds it by calling:
$ docker build --build-arg user=what_user Dockerfile
The USER on line 2 evaluates to some_user, because the user variable isn't defined until the next line, line 3. The USER on line 4 evaluates to what_user, because user is defined by then and the what_user value was passed on the command line π
Before its ARG instruction defines it, any use of a variable gives you an empty string.
Warning: It is not recommended to use build-time variables for passing secrets like github keys, user credentials etc. Build-time variable values are visible to any user of the image with the docker history command. ππ
You can use an ARG or an ENV instruction to specify variables that are available to the RUN instruction. Environment variables set with ENV always override an ARG instruction with the same name π Here's a Dockerfile with both an ENV and an ARG instruction:
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 ENV CONT_IMG_VER=v1.0.0
4 RUN echo $CONT_IMG_VER
Then, say this image gets built with this command:
$ docker build --build-arg CONT_IMG_VER=v2.0.1 Dockerfile
In this case, the RUN instruction uses v1.0.0 instead of the v2.0.1 ARG value the user passed in. This is similar to a shell script, where a locally scoped variable overrides variables passed as arguments or inherited from the environment, starting from the point where it's defined π§
Using the example above but with a different ENV specification, you can create more useful interactions between ARG and ENV instructions:
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 ENV CONT_IMG_VER=${CONT_IMG_VER:-v1.0.0}
4 RUN echo $CONT_IMG_VER
Unlike ARG, ENV values are always persisted in the built image β¨ Consider a docker build without the --build-arg flag:
$ docker build Dockerfile
With this Dockerfile, CONT_IMG_VER is still persisted in the image, but its value is v1.0.0 because that's the default set on line 3 by the ENV instruction π
The variable expansion trick in this example lets you pass arguments from the command line and persist them in the final image by leveraging the ENV instruction π Variable expansion is only supported for a limited set of Dockerfile instructions. β¨#environment-replacementβ©
Docker has a set of predefined ARG variables you can use without a matching ARG instruction in the Dockerfile π
HTTP_PROXYhttp_proxyHTTPS_PROXYhttps_proxyFTP_PROXYftp_proxyNO_PROXYno_proxyALL_PROXYall_proxy
To use these, pass them on the command line with the --build-arg flag, for example:
$ docker build --build-arg HTTPS_PROXY=https://my-proxy.example.com .
ONBUILD
ONBUILD [INSTRUCTION]
ONBUILD adds a trigger instruction to an image π¦ The trigger doesn't run right away. It runs later, when the image gets used as the base for another build. Docker runs the trigger in the context of that downstream build, as if the trigger existed right after the FROM instruction in the downstream Dockerfile.
You can register any build instruction as a trigger π Triggers are super useful if you're defining an image to use as a base for building other images, like an application build environment or a daemon customized with user-specific configuration.
Imagine an image meant to be a reusable python application builder. It has to add application source code into a particular directory, and it might need a build script called after that. You can't just call ADD and RUN right now, because you don't have access to the application source code yet, and it's different for every application build π
Giving application developers a boilerplate Dockerfile to copy-paste into their app is inefficient, error-prone, and hard to update, because it gets mixed up with application-specific code π The fix? Use ONBUILD to register instructions in advance, so they run later, during the next build stage π
HISTORY
- May 2014: Compiled by Zac Dover (zdover at redhat dot com) based on docker.com Dockerfile documentation.
- Feb 2015: updated by Brian Goff (cpuguy83@gmail.com) for readability.
- Sept 2015: updated by Sally O'Malley (somalley@redhat.com).
- Oct 2016: updated by Addam Hardy (addam.hardy@gmail.com).
That's the whole page, bestie π«Άβ¨ It came from the Docker Community, last updated May 2014, and it's DOCKERFILE(5) forever ππ
π¦ where this page comes from
- fedora 43: docker-cli 28.4.0-1.fc43 Β· Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND MIT
- fedora 43: docker-cli 29.6.2-1.fc43
- fedora 43: docker-cli 29.8.2-2.fc43
- fedora 43: docker-cli 29.9.2-2.fc43 Β· Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND MIT
- fedora 44: docker-cli 29.3.0-1.fc44 Β· Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND MIT
- fedora 44: docker-cli 29.8.2-2.fc44
- fedora 44: docker-cli 29.9.2-2.fc44 Β· Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND MIT
- ubuntu jammy: docker.io 29.1.3-0ubuntu3~22.04.2 Β· Apache-2.0
- ubuntu noble: docker.io 29.1.3-0ubuntu3~24.04.2 Β· Apache-2.0
- ubuntu questing: docker-ce-cli 5:29.5.3-1~ubuntu.25.10~questing
- ubuntu questing: docker.io 28.2.2-0ubuntu1
- ubuntu questing: docker.io 29.1.3-0ubuntu3~25.10.1
- ubuntu resolute: docker.io 29.1.3-0ubuntu4 Β· Apache-2.0
- ubuntu resolute: docker.io 29.1.3-0ubuntu4.1 Β· Apache-2.0
- ubuntu stonking: docker.io 29.7.2-0ubuntu1 Β· Apache-2.0
- π girlified by anthropic/claude-haiku-5.5 on : a language model's rewrite of the original, under its terms