Introduction
Dockerfiles form the foundation of custom images in the Docker ecosystem. In article chapter, we will delve deeper into the anatomy of a Dockerfile and explore common instructions used for creating custom images.
Anatomy of a Dockerfile
A typical Dockerfile consists of the following components:
-
Base image
This is the starting point for building your custom image. You can choose from a wide array of official or community-created images available on Docker Hub. -
Instructions
These are the commands that modify the base image to create a new, custom image. -
Comments
Lines beginning with a#
symbol are treated as comments.
Common Dockerfile Instructions
Here is a closer look at some of the most frequently used instructions in Dockerfiles:
FROM
Specifies the base image to start with. This instruction is mandatory and must be the first instruction in the Dockerfile.
FROM ubuntu:18.04
RUN
Executes a command and commits the result. Multiple RUN
instructions create separate layers in the image. To minimize layers, combine commands using &&
.
RUN apt-get update && \
apt-get install -y nginx
CMD
Sets the default command to run when the container starts. If multiple CMD
instructions are present, only the last one takes effect.
CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT
Defines the entry point for the container, allowing it to be run as an executable. It can be overridden using the --entrypoint
flag when starting the container.
ENTRYPOINT ["python", "app.py"]
COPY
Copies files from the host system to the image. It is recommended to use COPY
instead of ADD
unless you need advanced features like URL support or extracting archives.
COPY . /app
ADD
Adds files to the image, with support for URLs and extracting archives. Use it sparingly, and prefer COPY
for simple file transfers.
ADD https://example.com/file.tar.gz /app
ENV
Sets environment variables within the image. They can be accessed by processes running inside the container.
ENV APP_PORT=8080
EXPOSE
Informs Docker that the container listens on specific network ports. This instruction does not actually publish the ports but serves as documentation.
EXPOSE 80
WORKDIR
Sets the working directory for subsequent instructions. If the specified directory does not exist, it is created.
WORKDIR /app
USER
Sets the user for subsequent instructions. This is useful for running non-root processes inside the container.
USER www-data
VOLUME
Creates a mount point for external storage. This instruction is used to persist data generated by the container.
VOLUME /var/lib/mysql
Building Custom Images
Creating custom images using Dockerfiles allows developers to streamline the process of setting up environments, configuring applications, and deploying software. In this chapter, I will discuss the build process.
To build a custom image from a Dockerfile, use the docker build
command followed by the build context (usually the current directory):
$ docker build -t your-image-name:tag .
The -t
flag assigns a name and optional tag to the new image. The build context contains the Dockerfile and any additional files needed during the build process. The build context is important because it is where Docker looks for the files referenced in the Dockerfile.
The build process consists of the following steps:
- Docker reads the Dockerfile and processes each instruction in sequence.
- Each instruction creates a new layer in the image. Layers are cached to speed up subsequent builds.
- The final layer represents the new custom image, which can be used to create containers.
For example, consider the following Dockerfile for a simple Node.js application:
# Set the base image
FROM node:14
# Set the working directory
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the application code
COPY . .
# Expose the application port
EXPOSE 3000
# Run the application
CMD ["npm", "start"]
When building this image, Docker will perform the following actions:
- Pull the
node:14
base image from Docker Hub. - Set the working directory to
/app
. - Copy the
package.json
andpackage-lock.json
files into the image. - Run
npm install
to install the application dependencies. - Copy the remaining application code into the image.
- Expose port 3000.
- Set the default command to run the application with
npm start
.
Once the image is built, you can create and run containers using the docker run
command:
$ docker run -d -p 3000:3000 your-image-name:tag