Dockerfile
A Dockerfile is a text file that contains a set of instructions to automate the creation of Docker images. It defines how an image should be built, including its base image, dependencies, configurations, and runtime commands.
The default filename for a dockerfile is Dockerfile without a file extension. But you can specify custom Dockerfile filename using:
docker build --file <something>.Dockerfile .Example of a Dockerfile:
FROM ubuntu:latest
RUN apt-get update && apt-get install -y curl
COPY app/ /app/
WORKDIR /app
ENV APP_ENV=prod
CMD ["python3", "app.py"]Each command in a Dockerfile, that modifies the filesystem, will result in a new layer. However, not all Dockerfile commands alter the filesystem.
Commands that create layers
These commands alter the filesystem and therefore create new layers:
RUN– Executes a command inside the container and commits the changes.COPY– Copies files from the host to the container image.ADD– Similar toCOPY, but also supports fetching files from URLs and automatically extracting compressed archives.
Commands that don't create layers
These commands modify metadata but do not change the filesystem, so they don't create new layers:
ENV– Sets environment variables.WORKDIR– Sets the working directory for subsequent instructions.CMD– Sets the default command, that runs when a container starts, for the container.- You can specify this in shell or exec form:
CMD ["executable","param1","param2"](exec form)CMD ["param1","param2"](exec form, as default parameters toENTRYPOINT)CMD command param1 param2(shell form)
- There can only be one
CMDinstruction in a Dockerfile. If you list more than one, only the last one takes effect.
- You can specify this in shell or exec form:
ENTRYPOINT– Defines the main command, that always runs when a container starts, for the container. UnlikeCMD, which can be easily overridden,ENTRYPOINTis meant to be fixed, ensuring that the container behaves like a dedicated executable.- You can however override it, using
--entrypointflag ofdocker run.
- You can however override it, using
EXPOSE– Declares which ports the container listens on (but doesn't actually open them). You must explicitly publish them when running the container usingdocker runcommand with option-por-P.LABEL– Adds metadata to the image. This metadata consists of key-value pairs that provide useful information about the image, such as its author, description, version, license, and more.USER– SSets the default user for all subsequent instructions.VOLUME– Declares a mount point for persistent external storage, allowing data to survive container restarts and be shared across multiple containers.
For a full list of Dockerfile commands, refer to the Official Documentation.
Shell and Exec form
The RUN, CMD, and ENTRYPOINT instructions all have two possible forms:
Exec Form (JSON array syntax)
INSTRUCTION ["executable","param1","param2"]Exec form uses a JSON array syntax, which means each element must be wrapped within double-quotes (""). Each element in the array represents a command, flag, or argument.
Exec form doesn't automatically invoke a command shell. This means that normal shell processing, such as variable substitution, doesn't happen. For example, RUN [ "echo", "$HOME" ] won't handle variable substitution for $HOME.
Additionally, in exec form, you must escape backslashes. This is particularly relevant on Windows where the backslash is the path separator:
RUN ["c:\\windows\\system32\\tasklist.exe"]Shell Form (regular command syntax)
INSTRUCTION command param1 param2Unlike the exec form, instructions using the shell form always use a command shell. The shell form doesn't use the JSON array format, instead it's a regular string.
The shell form string lets you escape newlines using the backslash escape character.
RUN source $HOME/.bashrc && \
echo $HOMEHere Docs
You can also use heredocs with the shell form to break up supported commands.
RUN <<EOF
source $HOME/.bashrc && \
echo $HOME
EOFTBD (Here Docs - https://docs.docker.com/reference/dockerfile/#here-documents)
.dockerignore file
A .dockerignore file is used to exclude files and directories during the image build process. It works similarly to .gitignore, improving build speed and reducing image size by excluding unnecessary files.
For example, if you don't want to copy node_modules and .env into the container, you can define .dockerignore file as follows:
node_modules/
.env