Appearance
Dockerfile
1. Dockerfile 指令
让我们深入理解每个重要的 Dockerfile 指令:
1.1. FROM
作用:指定基础镜像,所有 Dockerfile 都必须以
FROM开头。语法:
FROM [--platform=<platform>] <image>[:<tag>|@<digest>] [AS <name>]示例:
DockerfileFROM ubuntu:20.04
Note:可选的
AS用于构建多阶段镜像。
1.2. WORKDIR
作用:设置工作目录,影响
RUN、CMD等指令的相对路径。语法:
WORKDIR <path>示例:
DockerfileWORKDIR /app
1.3. COPY
作用:将文件从构建环境复制到镜像内。
语法:
COPY [OPTIONS] <src> ... <dest>选项 最低 Dockerfile 版本 --from--chown--chmod1.2 --link1.4 --parents1.7-labs --exclude1.7-labs 示例:
DockerfileCOPY . /app/DockerfileCOPY file1.txt file2.txt /usr/src/things/
1.4. ADD
作用:功能类似
COPY,但支持额外功能(如自动解压tar文件)。语法:
ADD [OPTIONS] <src> ... <dest>选项 最低 Dockerfile 版本 --keep-git-dir1.1 --checksum1.6 --chown--chmod1.2 --link1.4 --exclude1.7-labs 示例:
DockerfileADD app.tar.gz /app/
一般推荐使用 COPY,除非需要解压功能。
1.5. RUN
作用:在镜像内执行命令,并创建镜像层。
语法:
RUN [OPTIONS] <command> ...。选项 最低 Dockerfile 版本 --mount1.2 --network1.3 --security1.1.2-labs 示例:
Dockerfile# 建议使用 `&&` 连接命令以减少镜像层 RUN apt-get update && \ apt-get install -y curlDockerfileRUN <<EOF apt-get update apt-get install -y curl EOF
1.6. ENV
作用:设置环境变量,这些变量在构建时和容器运行时都可用。
语法:
ENV <key>=<value> [<key>=<value>...]示例:
DockerfileENV MY_NAME="John Doe" ENV MY_DOG=Rex\ The\ Dog ENV MY_CAT=fluffy
1.7. ARG
作用:定义构建参数,在构建时可以传递值(可用
--build-arg覆盖)。语法:
ARG <name>[=<default value>] [<name>[=<default value>]...]示例:
DockerfileARG VERSION=1.0 RUN echo "Version: $VERSION"
| 特性 | ARG | ENV |
|---|---|---|
| 生效范围 | 仅在构建期间使用 | 构建期间和运行时均可用 |
| 默认值是否保留 | 不保留(不会写入镜像) | 保留,写入镜像元数据 |
| 使用方式 | 通过 --build-arg 传递 | Dockerfile 或运行时使用 |
1.8. EXPOSE
作用:声明容器要监听的端口(仅声明,不会实际绑定)。
语法:
EXPOSE <port> [<port>/<protocol>...]示例:
DockerfileEXPOSE 8080 EXPOSE 80/udp
1.9. VOLUME
作用:声明挂载点,提示用户需要挂载的目录。
语法:
VOLUME ["<path>"]示例:
DockerfileVOLUME ["/data"]
1.10. LABEL
作用:为镜像添加元数据。
语法:
LABEL <key>=<value> [<key>=<value>...]示例:
DockerfileLABEL "com.example.vendor"="ACME Incorporated" LABEL com.example.label-with-value="foo" LABEL version="1.0" LABEL description="This text illustrates \ that label-values can span multiple lines."
Note:有些旧的 Dockerfile 使用
MAINTAINER指令来指定作者信息。MAINTAINER指令是 Dockerfile 中的一个旧指令,从 Docker 1.13.0 版本开始,MAINTAINER指令已经被弃用,并被LABEL指令取代。
1.11. USER
作用:指定运行容器的用户。
语法:
USER <user>[:<group>]示例:
DockerfileUSER nonroot
1.12. CMD
作用:指定容器启动时运行的默认命令(可以被覆盖)。
语法:
CMD ["executable", "param1", "param2"](推荐)CMD command param1 param2(Shell 格式)
示例:
DockerfileCMD ["nginx", "-g", "daemon off;"]
1.13. ENTRYPOINT
作用:定义容器启动时的主进程,不易被覆盖。
语法:
ENTRYPOINT ["executable", "param1", "param2"](推荐)ENTRYPOINT command param1 param2(Shell 格式)
示例:
DockerfileENTRYPOINT ["python3", "app.py"]
Note:与
CMD指令的区别
CMD可以被docker run的命令覆盖,而ENTRYPOINT更像是不可替代的主进程(如果docker run使用--entrypoint,则会覆盖ENTRYPOINT。)。此外
CMD还可作为ENTRYPOINT的参数:DockerfileENTRYPOINT ["python3"] CMD ["app.py"]
通常会用 ENTRYPOINT 固定一个主命令,但允许用户通过 CMD 或 docker run 覆盖参数。示例:
Dockerfile
FROM python:3.10
# 固定的主命令
ENTRYPOINT ["python", "-m"]
# 可覆盖的模块或参数
CMD ["http.server", "8080"]运行时:
默认行为:
Dockerfiledocker run <image>运行:
Dockerfilepython -m http.server 8080覆盖
CMD参数:Dockerfiledocker run <image> json.tool运行:
Dockerfilepython -m json.tool
1.14. SHELL
作用:修改默认的 Shell。
语法:
SHELL ["executable", "param1", "param2"]示例:
DockerfileSHELL ["/bin/bash", "-c"]
1.15. HEALTHCHECK
作用:定义容器健康检查命令。
语法:
HEALTHCHECK [OPTIONS] CMD <command>示例:
DockerfileHEALTHCHECK --interval=30s --timeout=5s CMD curl -f http://localhost || exit 1
1.16. ONBUILD
作用:为子镜像设置触发指令。
语法:
ONBUILD <instruction>示例:
DockerfileONBUILD COPY . /app
1.17. STOPSIGNAL
作用:指定停止容器时发送的信号。
语法:
STOPSIGNAL <signal>示例:
DockerfileSTOPSIGNAL SIGKILL
1.18. 注释
作用:添加注释。
语法:以
#开头。示例:
Dockerfile# This is a comment
2. 构建优化技巧
使用多阶段构建来减小镜像体积:
Dockerfile# 构建阶段 FROM node:14 AS builder WORKDIR /app COPY . . RUN npm install && npm run build # 生产阶段 FROM nginx:alpine COPY --from=builder /app/build /usr/share/nginx/html合并
RUN指令来减少层数:Dockerfile# 好的做法 RUN apt-get update && \ apt-get install -y python3 && \ rm -rf /var/lib/apt/lists/* # 避免这样做 RUN apt-get update RUN apt-get install -y python3 RUN rm -rf /var/lib/apt/lists/*使用
.dockerignore文件排除不需要的文件:ignorenode_modules npm-debug.log Dockerfile .git .env
3. Dockerfile 示例
以下是一些经典的 Dockerfile 示例,涵盖了从简单的基础镜像创建到复杂的多阶段构建。每个示例都展示了 Dockerfile 的不同功能及其最佳实践。
3.1. Nginx 静态网站
构建一个简单的基于 nginx 的静态网站镜像:
Dockerfile
# 使用官方 Nginx 镜像
FROM nginx:alpine
# 复制静态文件到默认的 Nginx 目录
COPY ./static /usr/share/nginx/html
# 暴露端口
EXPOSE 80
# 默认启动命令
CMD ["nginx", "-g", "daemon off;"]说明:
- 使用
COPY指令将本地文件复制到镜像中; CMD保持 Nginx 前台运行;
3.2. Python 应用
运行一个基于 Flask 的 Python 应用:
Dockerfile
# 使用 Python 官方镜像,或使用 python:slim(如:python:3.10-slim)基础镜像减少镜像体积
FROM python:3.10
# 设置工作目录
WORKDIR /app
# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY . .
# 暴露 Flask 默认端口
EXPOSE 5000
# 启动应用
CMD ["python", "app.py"]说明:
- 使用
pip install --no-cache-dir减少镜像体积; requirements.txt的分离复制提升缓存利用率;
3.3. Node.js 应用
适用于基于 Node.js 的 Web 应用:
Dockerfile
# 使用 Node.js 官方镜像
FROM node:18
# 设置工作目录
WORKDIR /app
# 复制 package.json 并安装依赖
COPY package*.json ./
RUN npm install
# 复制应用代码
COPY . .
# 暴露应用端口
EXPOSE 3000
# 启动应用
CMD ["npm", "start"]说明:
- 遵循最佳实践,将依赖文件单独复制并安装,避免不必要的重新构建;
- 使用
WORKDIR简化路径操作;
3.4. 多阶段构建
适用于需要构建和运行分离的场景,如前端应用:
Dockerfile
# 构建阶段
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 运行阶段
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]说明:
- 第一阶段(
builder)用于编译构建代码; - 第二阶段(运行时)仅包含编译后的文件,减小镜像体积;
3.5. 构建小型 Go 应用
适用于编译并运行 Go 应用:
Dockerfile
# 构建阶段
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
# 编译 Go 应用
RUN go build -o main .
# 运行阶段
FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]说明:
- 使用多阶段构建将编译和运行分离;
- 使用
alpine作为基础镜像,进一步缩小镜像大小;
3.6. 带健康检查的应用
为应用添加健康检查:
Dockerfile
FROM python:3.10
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
HEALTHCHECK --interval=30s --timeout=5s --retries=3 CMD curl -f http://localhost:5000/health || exit 1
CMD ["python", "app.py"]说明:
HEALTHCHECK定期检查应用健康状态;- 如果健康检查失败,Docker 会将容器标记为
unhealthy;
3.7. 使用环境变量的应用
支持运行时配置:
Dockerfile
FROM python:3.10
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
# 设置默认环境变量
ENV APP_ENV=production
CMD ["python", "app.py"]说明:
ENV设置默认值,可以在运行容器时通过-e参数覆盖;
3.8. 使用 ARG 和 ENV
结合 ARG 和 ENV 用于构建参数和运行时环境:
Dockerfile
FROM node:18
# 构建参数(仅构建时可用)
ARG BUILD_ENV=development
# 环境变量(运行时可用)
ENV NODE_ENV=$BUILD_ENV
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]说明:
构建时可以使用
--build-arg传递BUILD_ENV的值:Bashdocker build --build-arg BUILD_ENV=production .