Dockerfile 参考

概述

Dockerfile 是一个文本文件,包含了构建 Docker 镜像所需的所有命令。Docker 通过读取 Dockerfile 中的指令自动构建镜像。本文档详细介绍了 Dockerfile 的格式和支持的指令。

基本结构

Dockerfile 由一系列指令和参数组成。每条指令都必须大写,后面跟随相应的参数。

# 注释
FROM ubuntu:20.04
LABEL maintainer="[email protected]"
RUN apt-get update && apt-get install -y nginx
COPY . /app
WORKDIR /app
CMD ["nginx", "-g", "daemon off;"]

基础指令

FROM

指定基础镜像,是 Dockerfile 中必须存在的第一条指令。

语法

FROM 指令支持以下几种格式:

FROM <image>
FROM <image>:<tag>
FROM <image>@<digest>

WORKDIR

设置工作目录,影响后续的 RUN、CMD、ENTRYPOINT、COPY 和 ADD 指令。

语法

WORKDIR /path/to/workdir

COPY

从构建上下文复制文件或目录到容器中。

语法

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]

ADD

类似 COPY,但支持 URL 和自动解压 tar 文件。建议优先使用 COPY,除非需要 ADD 的特殊功能。

语法

ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]

RUN

在当前镜像之上执行命令并创建新的镜像层。每个 RUN 指令都会创建一个新的镜像层。

语法

RUN 指令支持 shell 格式和 exec 格式:

# Shell 格式
RUN command

# Exec 格式
RUN ["executable", "param1", "param2"]

CMD

指定容器启动时要运行的命令。一个 Dockerfile 中只能有一个 CMD 指令。如果指定了多个,只有最后一个会生效。

语法

CMD 指令支持三种格式:

# Exec 格式(推荐)
CMD ["executable","param1","param2"]

# 作为 ENTRYPOINT 的默认参数
CMD ["param1","param2"]

# Shell 格式
CMD command param1 param2

ENTRYPOINT

配置容器启动时运行的可执行文件。ENTRYPOINT 的主要用途是将容器作为可执行程序使用。

语法

# Exec 格式(推荐)
ENTRYPOINT ["executable", "param1", "param2"]

# Shell 格式
ENTRYPOINT command param1 param2

环境和参数

ENV

设置环境变量,这些变量在构建过程中和容器运行时都可用。

语法

ENV <key>=<value> ...
ENV <key> <value>

ARG

定义构建参数,这些参数只在构建过程中可用,容器运行时不可用。

语法

ARG <name>[=<default value>]

元数据

LABEL

为镜像添加元数据,比如维护者信息、版本信息等。

语法

LABEL <key>=<value> <key>=<value> <key>=<value> ...

最佳实践

使用多阶段构建

使用多阶段构建可以显著减小最终镜像的大小。在编译阶段使用包含编译工具的镜像,在运行阶段只复制编译后的文件。

FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o main

FROM alpine:latest
COPY --from=builder /app/main /main
CMD ["/main"]

合并 RUN 指令

合并多个 RUN 指令可以减少镜像层数,从而减小镜像大小。使用 && 连接多个命令,并在最后清理缓存。

RUN apt-get update &&     apt-get install -y         package1         package2 &&     rm -rf /var/lib/apt/lists/*

使用 .dockerignore

使用 .dockerignore 文件排除不需要的文件,可以加快构建速度并减小构建上下文的大小。

node_modules
npm-debug.log
Dockerfile
.dockerignore
.git
.gitignore

选择合适的基础镜像

使用官方镜像,优先选择 alpine 版本以减小镜像大小。确保使用具体的标签而不是 latest。

FROM node:18-alpine

完整示例

Node.js 应用示例

# 使用 Node.js Alpine 作为基础镜像
FROM node:18-alpine

# 设置工作目录
WORKDIR /app

# 复制 package.json 和 package-lock.json
COPY package*.json ./

# 安装依赖
RUN npm ci --only=production

# 复制源代码
COPY . .

# 暴露端口
EXPOSE 3000

# 启动应用
CMD ["npm", "start"]

Go 应用多阶段构建示例

# 构建阶段
FROM golang:1.21-alpine AS builder

WORKDIR /app

# 复制 Go 模块文件
COPY go.* ./
RUN go mod download

# 复制源代码
COPY . .

# 构建应用
RUN CGO_ENABLED=0 GOOS=linux go build -o main

# 运行阶段
FROM alpine:latest

RUN apk --no-cache add ca-certificates

WORKDIR /root/

# 从构建阶段复制二进制文件
COPY --from=builder /app/main .

# 运行应用
CMD ["./main"]