Dockerfile 是一个用于构建 Docker 镜像的文本文件,它包含了一系列指令,用于定义镜像的基础环境、安装软件、配置应用等操作。通过 Dockerfile,你可以自动化构建出一致且可重复的镜像。
一、Dockerfile 基础结构
一个典型的 Dockerfile 包含以下部分:
dockerfile
# 基础镜像
FROM ubuntu:22.04
# 维护者信息(可选)
LABEL maintainer="your@email.com"
# 环境变量(可选)
ENV APP_HOME /app
ENV PORT 8080
# 安装依赖
RUN apt-get update && apt-get install -y \
python3 \
python3-pip \
&& rm -rf /var/lib/apt/lists/*
# 创建工作目录
WORKDIR $APP_HOME
# 复制文件到镜像
COPY requirements.txt .
RUN pip3 install --no-cache-dir -r requirements.txt
COPY . .
# 暴露端口
EXPOSE $PORT
# 容器启动命令
CMD ["python3", "app.py"]
二、常用指令详解
1. FROM
指定基础镜像,必须是第一条非注释指令。
dockerfile
FROM python:3.9-slim # 使用官方 Python 3.9 轻量级镜像
2. RUN
在镜像构建过程中执行命令,常用于安装软件。
dockerfile
RUN apt-get update && apt-get install -y curl # Ubuntu/Debian
RUN yum install -y curl # CentOS/RHEL
3. COPY 和 ADD
复制文件或目录到镜像中。
dockerfile
COPY src/ /app/src/ # 复制本地 src 目录到镜像的 /app/src
ADD package.json /app/ # 支持远程 URL 和自动解压 tar 文件
4. WORKDIR
设置工作目录(相当于 cd 命令),后续指令将在此目录执行。
dockerfile
WORKDIR /app
RUN touch test.txt # 在 /app 目录下创建 test.txt
5. ENV
设置环境变量,可在后续指令或运行时使用。
dockerfile
ENV DB_HOST=localhost \
DB_PORT=5432
6. EXPOSE
声明容器运行时监听的端口,但不实际映射端口。
dockerfile
EXPOSE 8080 # 声明容器监听 8080 端口
7. CMD 和 ENTRYPOINT
定义容器启动时执行的命令:
-
CMD :提供默认命令,可被
docker run的参数覆盖。dockerfileCMD ["python3", "app.py"] # 推荐写法(数组形式) -
ENTRYPOINT :配置容器启动时的可执行程序,参数不会被覆盖。
dockerfileENTRYPOINT ["python3", "app.py"] # 固定执行 app.py CMD ["--host", "0.0.0.0"] # 作为默认参数
三、构建镜像
使用 docker build 命令构建镜像:
bash
docker build -t my-app:1.0 . # -t 指定镜像标签,. 表示使用当前目录的 Dockerfile
四、最佳实践
1. 分层构建
将不常变更的操作放在前面,利用镜像缓存加速构建。
dockerfile
COPY requirements.txt . # 先复制依赖文件
RUN pip install -r requirements.txt # 安装依赖(缓存此层)
COPY . . # 最后复制应用代码(频繁变更)
2. 最小化镜像大小
-
使用轻量级基础镜像(如
alpine或slim)。 -
清理临时文件:
dockerfileRUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
3. 安全最佳实践
- 避免使用
root用户运行应用。 - 定期更新基础镜像和依赖。
4. 多阶段构建
适合编译型语言(如 Go、Java),减小最终镜像体积。
dockerfile
# 构建阶段
FROM golang:1.20 as builder
WORKDIR /app
COPY . .
RUN go build -o myapp
# 运行阶段
FROM alpine:3.17
COPY --from=builder /app/myapp /usr/bin/
CMD ["myapp"]
五、示例:构建 Node.js 应用镜像
dockerfile
# 使用 Node.js 官方轻量级镜像
FROM node:18-alpine
# 设置工作目录
WORKDIR /app
# 复制 package.json 和 package-lock.json
COPY package*.json ./
# 安装依赖
RUN npm ci --production
# 复制应用代码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动应用
CMD ["node", "server.js"]
六、常见问题
- 缓存失效 :当
COPY或ADD命令的源文件发生变化时,后续层的缓存都会失效。 - 权限问题:容器内文件权限可能与主机不一致,需显式设置。
- 镜像膨胀 :避免在同一
RUN指令中执行无关操作,减少层数。
通过合理编写 Dockerfile,可以构建出高效、安全且易于维护的容器镜像。