Dockerfile 完全指南:从入门到精通

发布于:2025-07-23 ⋅ 阅读:(15) ⋅ 点赞:(0)

Dockerfile 完全指南:从入门到精通

一、什么是 Dockerfile?

Dockerfile 是一个文本文件,包含了一系列构建 Docker 镜像的指令。通过 Dockerfile,开发者可以将应用程序的构建过程标准化、自动化,确保在任何环境中都能生成一致的镜像。

使用 Dockerfile 构建镜像的核心优势:

  • 可重复性:相同的 Dockerfile 在任何环境下都能生成相同的镜像

  • 可维护性:以代码形式管理镜像构建过程,便于版本控制

  • 可扩展性:便于团队协作和持续集成 / 持续部署 (CI/CD) 流程集成

二、Dockerfile 基本结构

一个完整的 Dockerfile 通常包含以下几个部分(按常规顺序排列):

  1. 基础镜像指令:指定构建的基础镜像

  2. 维护者信息:可选,说明镜像的维护者

  3. 环境配置:设置环境变量、工作目录等

  4. 文件操作:复制文件到镜像中

  5. 命令执行:运行命令安装依赖或配置应用

  6. 暴露端口:声明容器运行时监听的端口

  7. 启动命令:指定容器启动时执行的命令

三、常用 Dockerfile 指令详解

1. FROM:指定基础镜像

\# 格式:FROM <镜像名>:<标签>


FROM ubuntu:22.04

FROM python:3.11-slim


FROM alpine:latest

注意

  • 每个 Dockerfile 必须以FROM指令开始(除了 ARG 指令)

  • 推荐使用官方镜像作为基础镜像,确保安全性和稳定性

  • 优先选择轻量级基础镜像(如 alpine 版本)减小镜像体积

2. WORKDIR:设置工作目录

\# 格式:WORKDIR <目录路径>


WORKDIR /app


WORKDIR /usr/local/src

特点

  • 如果目录不存在,Docker 会自动创建

  • 后续指令(如 RUN、CMD 等)都会在该目录下执行

  • 可以多次使用 WORKDIR 切换目录

3. COPY 与 ADD:复制文件

\# COPY:复制本地文件到镜像


COPY package.json /app/


COPY . /app


\# ADD:功能更丰富,支持URL和自动解压


ADD https://example.com/file.tar.gz /tmp/

ADD local.tar.gz /app/

最佳实践

  • 优先使用COPY,因为它更直观、功能明确

  • 需要自动解压或下载远程文件时才使用ADD

4. RUN:执行命令

\# shell格式


RUN apt-get update && apt-get install -y \\


&#x20;   package1 \\


&#x20;   package2 \\


&#x20;   && rm -rf /var/lib/apt/lists/\*


\# exec格式


RUN \["npm", "install"]

注意

  • 每条 RUN 指令都会创建一个新的镜像层

  • 合并多个命令为一条 RUN 指令,减少镜像层数

  • 清理缓存和临时文件,减小镜像体积

5. ENV:设置环境变量

\# 设置单个环境变量


ENV NODE\_ENV production


\# 设置多个环境变量


ENV APP\_PORT=3000 \\


&#x20;   DB\_HOST=localhost

优势

  • 容器运行时可以直接使用这些环境变量

  • 后续指令(如 RUN、CMD 等)也可以使用

  • 可以通过docker run -e覆盖环境变量

6. EXPOSE:声明端口

EXPOSE 80

EXPOSE 443 8080

说明

  • 只是声明容器打算使用的端口,不会自动映射到主机

  • 帮助使用者了解容器运行时需要映射哪些端口

  • 实际端口映射需要在docker run时使用-p参数

7. CMD 与 ENTRYPOINT:容器启动命令

\# CMD:设置容器启动命令,可被docker run后的命令覆盖


CMD \["node", "app.js"]


CMD npm start


\# ENTRYPOINT:设置容器入口点,docker run后的命令作为参数


ENTRYPOINT \["python", "-m", "http.server"]


\# 此时运行docker run -p 8000:8000 image 8000 等价于 python -m http.server 8000

区别与使用场景

  • CMD适合设置默认命令,允许用户在运行时覆盖

  • ENTRYPOINT适合设置固定的程序入口,用户只能传递参数

  • 可以组合使用:ENTRYPOINT 指定固定部分,CMD 指定默认参数

8. ARG:构建参数

\# 定义构建参数


ARG VERSION=1.0.0

\# 使用构建参数


RUN wget https://example.com/app-\${VERSION}.tar.gz

特点

  • 仅在构建过程中有效,不会保留到容器中

  • 可以通过docker build --build-arg覆盖默认值

  • 可以在 FROM 指令前使用 ARG,用于指定基础镜像标签

9. VOLUME:定义数据卷

VOLUME \["/data"]


VOLUME /var/log /var/lib/mysql

作用

  • 声明容器中的持久化存储目录

  • 运行容器时会自动创建这些目录并挂载卷

  • 防止重要数据因容器删除而丢失

四、构建镜像命令

使用docker build命令从 Dockerfile 构建镜像:

\# 基本用法


docker build -t myapp:1.0 .


\# 指定Dockerfile路径


docker build -t myapp:1.0 -f ./docker/Dockerfile .


\# 使用构建参数


docker build -t myapp:1.0 --build-arg VERSION=2.0.0 .


\# 不使用缓存构建


docker build -t myapp:1.0 --no-cache .

其中.表示构建上下文(Docker daemon 可以访问的文件目录)。

五、Dockerfile 优化技巧

1. 减小镜像体积

  • 使用多阶段构建分离构建环境和运行环境

  • 清理包管理器缓存(如apt-get cleanyum clean all

  • 合并 RUN 指令,减少镜像层数

  • 使用.dockerignore文件排除不需要的文件

2. 优化构建速度

  • 合理排序指令,将频繁变动的指令放在后面

  • 利用 Docker 的构建缓存机制

  • 使用更小的基础镜像(如 alpine 版本)

3. 提高安全性

  • 使用非 root 用户运行容器

  • 避免在 Dockerfile 中包含敏感信息

  • 定期更新基础镜像,修复安全漏洞

六、多阶段构建详解

多阶段构建是减小镜像体积的有效方法,尤其适合编译型语言:

\# 第一阶段:构建阶段


FROM golang:1.20 AS builder


WORKDIR /app


COPY . .


RUN go build -o myapp main.go

\# 第二阶段:运行阶段


FROM alpine:latest


WORKDIR /app


COPY --from=builder /app/myapp .


EXPOSE 8080

CMD \["./myapp"]

优势

  • 最终镜像只包含运行所需的文件,不包含构建工具和源代码

  • 大幅减小镜像体积(通常可以减小 70% 以上)

  • 提高安全性,减少攻击面

七、常见应用的 Dockerfile 示例

1. Node.js 应用

FROM node:18-alpine


WORKDIR /app


\# 先复制依赖文件,利用缓存


COPY package\*.json ./


RUN npm install --production


\# 复制应用代码


COPY . .


ENV NODE\_ENV=production


EXPOSE 3000

CMD \["node", "server.js"]

2. Python 应用

FROM python:3.11-slim


WORKDIR /app


COPY requirements.txt .


RUN pip install --no-cache-dir -r requirements.txt

COPY . .


EXPOSE 5000

CMD \["python", "app.py"]

3. Java 应用(多阶段构建)

\# 构建阶段


FROM maven:3.8-openjdk-17 AS builder


WORKDIR /app


COPY pom.xml .


COPY src ./src


RUN mvn package -DskipTests

\# 运行阶段


FROM openjdk:17-jdk-slim


WORKDIR /app


COPY --from=builder /app/target/\*.jar app.jar


EXPOSE 8080


CMD \["java", "-jar", "app.jar"]

八、Dockerfile 最佳实践总结

  1. 保持镜像精简:只包含运行所需的文件和依赖

  2. 使用.dockerignore文件:排除不必要的文件和目录

  3. 合并 RUN 指令:减少镜像层数,每个 RUN 尽量完成一个完整功能

  4. 正确排序指令:将频繁变动的文件放在后面,充分利用缓存

  5. 不要以 root 用户运行:创建并使用非特权用户

  6. 避免在 Dockerfile 中存储敏感信息:使用环境变量或秘密管理工具

  7. 为镜像添加标签:使用有意义的标签,避免使用 latest 标签

  8. 使用多阶段构建:分离构建和运行环境

  9. 测试 Dockerfile:确保构建过程可重复、镜像可正常运行

  10. 添加注释:解释复杂指令的用途,提高可维护性

通过遵循这些最佳实践,你可以创建出更小、更安全、更易于维护的 Docker 镜像,从而提高容器化应用的效率和可靠性。


网站公告

今日签到

点亮在社区的每一天
去签到