Cheatsheet - Dockerfile
A Dockerfile is a text file that contains all the commands a user could call on the command line to assemble an image. It acts as a blueprint for building Docker images.
1. FROM
- Purpose: Defines the base image for your new image. Every Dockerfile must start with
FROM. - Syntax:
FROM <image>[:<tag>] - Example:
- Ubuntu:
FROM ubuntu:22.04 - Node LTS version:
FROM node:lts-slim
- Ubuntu:
- Tip: Use a specific tag (e.g.,
22.04) instead oflatestfor consistent builds.
2. LABEL
- Purpose: Adds metadata to an image. This can include information like maintainer, version, or description.
- Syntax:
LABEL <key>=<value> [<key>=<value>...] - Example:
LABEL maintainer="John Doe <[email protected]>" version="1.0" description="My Awesome App" - Tip: Useful for documentation and organizing images.
3. RUN
- Purpose: Executes commands in a new layer on top of the current image and commits the results. Used for installing packages, creating directories, etc.
- Syntax:
RUN <command>(shell form, default:/bin/sh -con Linux)RUN ["executable", "param1", "param2"](exec form, preferred for clarity and avoiding shell string processing)
- Example (shell form):
RUN apt-get update && apt-get install -y git build-essential - Example (exec form):
RUN ["/bin/bash", "-c", "echo Hello && echo World"] - Tip: Chain multiple
RUNcommands with&&and use\for readability to reduce image layers.
4. WORKDIR
- Purpose: Sets the working directory for any
RUN,CMD,ENTRYPOINT,COPY, andADDinstructions that follow it. - Syntax:
WORKDIR /path/to/workdir - Example:
WORKDIR /app COPY . . # Copies content to /app in the image - Tip: Use
WORKDIRto keep your Dockerfile clean and avoid absolute paths in subsequent commands.
5. COPY
- Purpose: Copies new files or directories from the host machine (
<src>) to the filesystem of the container at path<dest>. - Syntax:
COPY <src>... <dest> - Example:
COPY ./src /app/src COPY requirements.txt /app/ - Tip: Preferred over
ADDfor copying local files as it's more transparent.
6. ADD
- Purpose: Similar to
COPYbut has additional features:- Can extract tar files from
<src>(local or remote URL). - Can accept a URL for
<src>.
- Can extract tar files from
- Syntax:
ADD <src>... <dest> - Example (local tar):
ADD app.tar.gz /app/ - Example (remote URL):
ADD http://example.com/latest.zip /app/ - Tip: Use
COPYunless you specifically need the tar extraction or URL download features ofADD.
7. EXPOSE
- Purpose: Informs Docker that the container listens on the specified network ports at runtime. This is purely for documentation and doesn't actually publish the port.
- Syntax:
EXPOSE <port> [<port>...] - Example:
EXPOSE 80 443 - Tip: To actually publish ports, use the
-por--publishflag withdocker run.
8. ENV
- Purpose: Sets environment variables. These variables persist when a container is run and can be accessed by applications inside the container.
- Syntax:
ENV <key>=<value> [<key>=<value>...] - Example:
ENV NODE_ENV=production PORT=3000 - Tip: Can be overridden with
docker run -e <key>=<value>.
9. ARG
- Purpose: Defines a variable that users can pass at build-time to the builder using
docker build --build-arg <varname>=<value>. - Syntax:
ARG <name>[=<default value>] - Example:
ARG BUILD_VERSION=1.0 RUN echo "Building version: $BUILD_VERSION" - Tip:
ARGvariables are not available after the image is built, unlikeENV.
10. VOLUME
- Purpose: Creates a mount point with the specified name and marks it as holding externally mounted volumes from the native host or other containers.
- Syntax:
VOLUME ["/data"]orVOLUME /data - Example:
VOLUME /var/log/app - Tip: Use volumes to persist data generated by and used by Docker containers, especially for database files or logs.
11. USER
- Purpose: Sets the user name or UID to use when running the image and for any
RUN,CMD, andENTRYPOINTinstructions that follow it. - Syntax:
USER <user>[:<group>] - Example:
USER appuser - Tip: Running containers as a non-root user is a security best practice.
12. HEALTHCHECK
- Purpose: Tells Docker how to test a container to check if it is still working.
- Syntax:
HEALTHCHECK [OPTIONS] CMD command - Example:
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD curl -f http://localhost/ || exit 1 - Tip: Essential for robust container orchestration (e.g., Kubernetes) to determine container readiness.
13. ENTRYPOINT
- Purpose: Configures a container that will run as an executable. It defines the command that will always be executed when the container starts.
- Syntax:
ENTRYPOINT ["executable", "param1", "param2"](exec form, preferred)ENTRYPOINT command param1 param2(shell form)
- Example (exec form):
ENTRYPOINT ["/usr/bin/supervisord", "-n"] - Tip: Often used in conjunction with
CMDto provide default arguments to theENTRYPOINT.
14. CMD
-
Purpose: Provides defaults for an executing container. There can only be one
CMDinstruction in a Dockerfile. -
Syntax:
CMD ["executable","param1","param2"](exec form, as the main command)CMD ["param1","param2"](as default arguments toENTRYPOINT)CMD command param1 param2(shell form)
-
Example (with ENTRYPOINT):
ENTRYPOINT ["nginx"] CMD ["-g", "daemon off;"] # Default arguments for nginx -
Example (without ENTRYPOINT):
CMD ["python", "app.py"] -
Tip: When
ENTRYPOINTis defined,CMDprovides the default arguments for it. IfENTRYPOINTis not defined,CMDprovides the default command to execute. Thedocker runcommand line arguments will overrideCMD.
CMD vs ENTRYPOINT
Both CMD and ENTRYPOINT instructions define what command gets executed when running a container. There are few rules that describe their co-operation.
- Dockerfile should specify at least one of
CMDorENTRYPOINTcommands. ENTRYPOINTshould be defined when using the container as an executable.CMDshould be used as a way of defining default arguments for anENTRYPOINTcommand or for executing an ad-hoc command in a container.CMDwill be overridden when running the container with alternative arguments.
Dockerfile Best Practices:
- Order matters: Place instructions that change less frequently at the top to leverage Docker's build cache.
- Minimize layers: Combine
RUNcommands where possible using&&and\for efficiency. - Remove unnecessary files: Clean up temporary files, caches (
apt-get clean,rm -rf /var/lib/apt/lists/*) to keep image size small. - Use
.dockerignore: Exclude files and directories not needed in the image (like.git,node_modules,*.log). - Run as non-root: Create a dedicated user and group for your application for security.
- Specific tags: Always use specific version tags for base images instead of
latest.
Example: Containerize a Node app
Use this Dockerfile template:
# node
FROM node:12-slim
# the path inside the container
WORKDIR /usr/src/app
# copy the package.json and package-lock.json, and install dependencies
COPY package*.json ./
RUN npm install
# copy all the source code
COPY . .
# port
EXPOSE 8080
# run the command inside the container
CMD [ "node", "app.js" ]
And add a .dockerignore file:
Dockerfile
.dockerignore
node_modules
npm-debug.log
What is || : &&
|| : && creates a conditional execution flow:
- The command before
||is executed. - If it succeeds, the
|| :part is skipped, and the command after&&is executed. - If it fails, the
|| :part is executed (doing nothing), and then the command after && is executed regardless.
This pattern is often used to ensure that subsequent commands in a RUN instruction are always executed, even if a previous command fails. This is useful for tasks like cleaning up or setting up configurations that should happen regardless of earlier failures.
RUN apt-get update || : && apt-get install -y --no-install-recommends some-package