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
FROMinstruction specifies the base image to use for the subsequent instructions. Every Dockerfile must begin with aFROMinstruction. - 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
WORKDIRinstruction 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
COPYinstruction 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
/appdirectory inside the image.
-
RUN
- The
RUNinstruction 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.txtwithout using the cache to reduce image size.
-
CMD
- The
CMDinstruction specifies the default command to run when a container is started. UnlikeRUN, which runs at build time,CMDruns at container runtime. - Example:
CMD ["python", "app.py"] - The
Explanation: This runs
python app.pywhen the container starts.Important Note: If a Docker container is started with a custom command (e.g.,
docker run my-image echo "Hello"), theCMDinstruction will be overridden.
-
ENTRYPOINT
- The
ENTRYPOINTinstruction is similar toCMDbut 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.pyscript, but any additional arguments provided during container start will be passed toapp.py.
-
EXPOSE
- The
EXPOSEinstruction 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-por--publishwhen running the container. - Example:
EXPOSE 80 - The
- Explanation: This indicates that the application listens on port 80.
-
ENV
- The
ENVinstruction sets environment variables in the container. - Example:
ENV FLASK_ENV=development - The
-
Explanation: This sets the environment variable
FLASK_ENVtodevelopmentinside the container.
-
ADD vs COPY
-
ADDandCOPYare both used to copy files into the image. However,ADDcan also handle URLs and unpack compressed files, whileCOPYis simpler and preferred for straightforward copying. - Example:
ADD source.tar.gz /app -
-
Explanation: This would copy and automatically extract
source.tar.gzinto/app.
-
VOLUME
- The
VOLUMEinstruction 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
USERinstruction 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
ARGinstruction 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
.gitignorefiles, a.dockerignorefile 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
RUNcommands 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)