The Dockerfile
is at the heart of Docker image creation. It is a text file that contains a series of instructions on how to build a Docker image, similar to a recipe. Each instruction in a Dockerfile
creates a layer in the final image, which makes Docker images lightweight, efficient, and reusable.
Key Dockerfile Instructions
-
FROM
- The
FROM
instruction specifies the base image to use for the subsequent instructions. Every Dockerfile must begin with aFROM
instruction. - Example:
FROM python:3.9-slim
- The
- Explanation: This starts from a minimal Python 3.9 image. The base image can be anything—from a Linux distribution to an application runtime.
-
WORKDIR
- The
WORKDIR
instruction sets the working directory inside the container. All subsequent instructions operate relative to this path. - Example:
WORKDIR /app
- The
-
Explanation: All commands will now be run inside
/app
.
-
COPY
- The
COPY
instruction copies files and directories from your local filesystem into the Docker image. - Example:
COPY . /app
- The
-
Explanation: This copies all files from the current directory (where the Dockerfile is located) to the
/app
directory inside the image.
-
RUN
- The
RUN
instruction executes a command in the shell inside the container. It is typically used to install dependencies, update packages, or run scripts. - Example:
RUN pip install --no-cache-dir -r requirements.txt
- The
-
Explanation: This command installs Python dependencies listed in
requirements.txt
without using the cache to reduce image size.
-
CMD
- The
CMD
instruction specifies the default command to run when a container is started. UnlikeRUN
, which runs at build time,CMD
runs at container runtime. - Example:
CMD ["python", "app.py"]
- The
Explanation: This runs
python app.py
when the container starts.Important Note: If a Docker container is started with a custom command (e.g.,
docker run my-image echo "Hello"
), theCMD
instruction will be overridden.
-
ENTRYPOINT
- The
ENTRYPOINT
instruction is similar toCMD
but with a key difference: it defines the command that always runs when the container starts. UnlikeCMD
, it is not easily overridden. - Example:
ENTRYPOINT ["python", "app.py"]
- The
-
Explanation: This runs the
app.py
script, but any additional arguments provided during container start will be passed toapp.py
.
-
EXPOSE
- The
EXPOSE
instruction informs Docker that the container listens on a specified network port at runtime. It doesn’t publish the port to the host; that’s done using-p
or--publish
when running the container. - Example:
EXPOSE 80
- The
- Explanation: This indicates that the application listens on port 80.
-
ENV
- The
ENV
instruction sets environment variables in the container. - Example:
ENV FLASK_ENV=development
- The
-
Explanation: This sets the environment variable
FLASK_ENV
todevelopment
inside the container.
-
ADD vs COPY
-
ADD
andCOPY
are both used to copy files into the image. However,ADD
can also handle URLs and unpack compressed files, whileCOPY
is simpler and preferred for straightforward copying. - Example:
ADD source.tar.gz /app
-
-
Explanation: This would copy and automatically extract
source.tar.gz
into/app
.
-
VOLUME
- The
VOLUME
instruction creates a mount point with the specified path and marks it as holding externally mounted volumes. It’s used to persist data or share data between containers. - Example:
VOLUME /data
- The
- **Explanation:** This will mount the `/data` directory to a Docker-managed volume.
-
USER
- The
USER
instruction sets the user and group to run subsequent instructions and the CMD/ENTRYPOINT as. - Example:
USER appuser
- The
- **Explanation:** This ensures all following commands are run as `appuser` instead of the root user, enhancing security.
-
ARG
- The
ARG
instruction defines a variable that users can pass at build time to the Dockerfile withdocker build --build-arg
. - Example:
ARG version=latest
- The
- **Explanation:** This allows setting a `version` variable that can be used in the Dockerfile, which can be overridden by passing `--build-arg version=1.0`.
Building Efficient Dockerfiles
-
Use .dockerignore:
- Just like
.gitignore
files, a.dockerignore
file prevents unnecessary files and directories from being included in the Docker image. This helps keep the image size small. - Example:
__pycache__ *.pyc .git .env
- Just like
-
Order Instructions for Caching:
- Docker caches each layer (instruction) during the build process. By ordering instructions that don’t change often (e.g., installing system packages) before those that do (e.g., copying code), you can speed up the build process.
-
Minimize Layers:
- Each instruction in the Dockerfile creates a layer. Where possible, combine multiple
RUN
commands using&&
to reduce the number of layers. - Example:
RUN apt-get update && apt-get install -y \ package1 \ package2 \ && rm -rf /var/lib/apt/lists/*
- Each instruction in the Dockerfile creates a layer. Where possible, combine multiple
-
Leverage Multi-Stage Builds:
- For applications that need to be built (e.g., compiled), you can use multi-stage builds to keep the final image small by discarding build dependencies.
- Example:
# Build stage FROM golang:alpine AS builder WORKDIR /app COPY . . RUN go build -o myapp # Run stage FROM alpine COPY --from=builder /app/myapp /myapp CMD ["/myapp"]
Example: Dockerfile for a Python Web Application
# Use an official Python runtime as a parent image
FROM python:3.9-slim
# Set the working directory in the container
WORKDIR /usr/src/app
# Copy the current directory contents into the container at /usr/src/app
COPY . .
# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
# Make port 80 available to the world outside this container
EXPOSE 80
# Define environment variable
ENV FLASK_ENV=production
# Run app.py when the container launches
CMD ["python", "app.py"]
✌🏾
Top comments (0)