Docker 镜像与 Dockerfile 基础指南:从编写到管理

Docker 镜像与 Dockerfile 基础指南:从编写到管理

一份系统、实用的 Docker 镜像操作手册,涵盖 Dockerfile 编写规范与镜像全生命周期指令。

前言

Docker 容器化已成为现代应用交付的事实标准,而镜像则是容器的"源代码"。无论是构建自定义镜像,还是从仓库拉取、推送、管理现有镜像,掌握核心指令和编写技巧都是每一位开发者和运维工程师的必备技能。

本文基于实际工作中最常用的场景,分为两大章节:

  1. 如何编写高效的 Dockerfile:从基础指令到最佳实践,附带完整示例。
  2. 常用 Docker 镜像管理指令:覆盖构建、下载、推送、查看、删除、标记、导入导出等全流程。

读完本文,你将能够独立编写生产级 Dockerfile,并熟练使用 CLI 管理镜像生命周期。


第一部分:编写高效的 Dockerfile

1.1 什么是 Dockerfile?

Dockerfile 是一个纯文本文件,定义了一系列指令,告诉 Docker 如何从基础镜像开始,逐层叠加构建出你的应用镜像。每条指令通常对应镜像中的一层,利用层缓存可以大幅加速重建过程。

1.2 核心指令速查表

指令 作用 示例
FROM 指定基础镜像(必为第一条非注释指令) FROM node:18-alpine
WORKDIR 设置工作目录(自动创建) WORKDIR /app
COPY 将主机文件/目录复制到镜像中 COPY package.json .
ADD 类似 COPY,额外支持自动解压 tar 和 URL 下载 ADD app.tar.gz /app
RUN 在构建时执行命令(安装软件、生成文件) RUN npm install
ENV 设置环境变量(运行时也存在) ENV NODE_ENV=production
ARG 构建时变量(docker build --build-arg 传值) ARG VERSION=latest
EXPOSE 声明容器监听的端口(仅文档作用) EXPOSE 8080
CMD 容器启动时执行的命令(可被 docker run 覆盖) CMD ["node", "app.js"]
ENTRYPOINT 容器启动时执行的命令(更不易被覆盖) ENTRYPOINT ["./entrypoint.sh"]
USER 切换执行用户(提升安全性) USER node
VOLUME 声明匿名卷(用于持久化数据) VOLUME ["/data"]

📌 CMD 与 ENTRYPOINT 的区别

  • ENTRYPOINT 定义固定主进程,CMD 提供默认参数,两者可配合使用。
  • 示例:ENTRYPOINT ["nginx"] + CMD ["-g", "daemon off;"]
  • docker run 时若指定额外参数,会覆盖 CMD 而不会覆盖 ENTRYPOINT

1.3 编写 Dockerfile 的最佳实践

① 选择合适的基础镜像
  • 优先使用官方镜像,并指定具体版本标签(避免 :latest)。
  • Alpine 变体(如 python:3.11-alpine)体积极小,适合生产环境。
② 利用构建缓存

将不易变化的指令放在前面。例如,先 COPY package.json,再 RUN npm install,之后才 COPY . .。这样代码变动不会导致依赖重新安装。

③ 合并 RUN 命令,减少层数
dockerfile 复制代码
RUN apt-get update && apt-get install -y curl \
    && rm -rf /var/lib/apt/lists/*

使用 && 连接,并在最后清理临时文件。

④ 多阶段构建

大幅减小最终镜像体积:

dockerfile 复制代码
# 构建阶段
FROM golang:1.19 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp

# 运行阶段
FROM alpine:latest
COPY --from=builder /app/myapp /usr/local/bin/
CMD ["myapp"]
⑤ 设置 .dockerignore

忽略无关文件(.gitnode_modules__pycache__*.log 等),加快构建速度并减小上下文。

⑥ 避免以 root 运行
dockerfile 复制代码
RUN addgroup -g 1001 -S appgroup && adduser -u 1001 -S appuser -G appgroup
USER appuser
⑦ 声明健康检查
dockerfile 复制代码
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:3000/ || exit 1

1.4 完整示例:Python Flask 应用

项目结构

复制代码
myapp/
├── Dockerfile
├── .dockerignore
├── requirements.txt
└── app.py

Dockerfile 内容

dockerfile 复制代码
FROM python:3.11-slim AS builder

WORKDIR /app

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

COPY . .

ENV FLASK_APP=app.py
ENV FLASK_ENV=production

EXPOSE 5000

RUN adduser --disabled-password --gecos '' appuser && chown -R appuser /app
USER appuser

CMD ["flask", "run", "--host=0.0.0.0"]

.dockerignore

bash 复制代码
__pycache__
*.pyc
.git
.env
.venv

构建并运行

bash 复制代码
docker build -t my-flask-app .
docker run -p 5000:5000 my-flask-app

1.5 调试与优化技巧

  • 查看镜像层:docker history <镜像名>

  • 分析镜像体积:使用 dive 工具

  • 启用 BuildKit:export DOCKER_BUILDKIT=1,支持并行构建和缓存挂载

    dockerfile 复制代码
    RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt

第二部分:常用 Docker 镜像管理指令

本节涵盖从拉取、构建到推送、删除的全生命周期指令。所有命令均以 docker 为前缀。

2.1 构建镜像 -- docker build

从 Dockerfile 构建镜像。

bash 复制代码
docker build [OPTIONS] PATH
常用选项 说明
-t, --tag 指定镜像名称:标签
-f, --file 指定 Dockerfile 路径
--build-arg 传递构建变量
--no-cache 禁用缓存
--platform 目标平台,如 linux/amd64

示例

bash 复制代码
docker build -t myapp:1.0 .
docker build -t myapp:dev -f Dockerfile.dev .
docker build --build-arg VERSION=1.2.3 -t myapp .

2.2 下载镜像 -- docker pull

从仓库(默认 Docker Hub)拉取镜像。

bash 复制代码
docker pull [OPTIONS] NAME[:TAG|@DIGEST]

示例

bash 复制代码
docker pull ubuntu
docker pull node:18-alpine
docker pull --all-tags nginx          # 拉取所有标签(慎用)
docker pull ubuntu@sha256:dfd64e...   # 按摘要拉取

2.3 推送镜像 -- docker push

将本地镜像推送到远程仓库(需先 docker login)。

bash 复制代码
docker push [OPTIONS] NAME[:TAG]

前置步骤

bash 复制代码
# 登录 Docker Hub
docker login -u username

# 打标签(假设本地镜像 myapp:1.0)
docker tag myapp:1.0 username/myapp:1.0

# 推送
docker push username/myapp:1.0

2.4 查看镜像列表 -- docker images / docker image ls

列出本地所有镜像。

bash 复制代码
docker images [OPTIONS] [REPOSITORY[:TAG]]

常用选项

  • -a:显示所有(包括中间层)
  • -q:只显示镜像 ID
  • --filter:过滤,如 "dangling=true"(虚悬镜像)

示例

bash 复制代码
docker images
docker images -q
docker images --filter "reference=*ubuntu*"

2.5 查看镜像详情 -- docker inspect

获取 JSON 格式的元数据(环境变量、层、架构等)。

bash 复制代码
docker inspect [OPTIONS] NAME|ID

示例

bash 复制代码
docker inspect ubuntu:latest
docker inspect --format='{{.Architecture}}' myapp:1.0

2.6 查看镜像历史 -- docker history

显示每一层的构建命令和大小。

bash 复制代码
docker history [OPTIONS] IMAGE

示例

bash 复制代码
docker history myapp:1.0
docker history --no-trunc nginx   # 完整显示命令

2.7 删除镜像 -- docker rmi / docker image rm

删除本地一个或多个镜像。

bash 复制代码
docker rmi [OPTIONS] IMAGE [IMAGE...]

常用选项

  • -f:强制删除(即使有容器依赖)
  • --no-prune:不删除未加标签的父镜像

示例

bash 复制代码
docker rmi myapp:1.0
docker rmi $(docker images -f "dangling=true" -q)   # 删除所有虚悬镜像
docker rmi -f myapp

2.8 标记镜像 -- docker tag

为镜像添加新标签(指向同一镜像 ID)。

bash 复制代码
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

示例

bash 复制代码
docker tag myapp:1.0 myapp:stable
docker tag myapp:1.0 myregistry.example.com/myapp:1.0

2.9 登录/登出仓库 -- docker login / docker logout

bash 复制代码
docker login [SERVER] [OPTIONS]
docker logout [SERVER]

安全传密码

bash 复制代码
echo "mypassword" | docker login -u alice --password-stdin

在 Docker Hub 搜索公开镜像。

bash 复制代码
docker search [OPTIONS] TERM

示例

bash 复制代码
docker search nginx --filter "is-official=true"
docker search mysql --filter stars=1000 --limit 5

2.11 保存与加载镜像文件 -- docker save / docker load

用于离线迁移或备份。

bash 复制代码
# 保存为一个 tar 文件
docker save -o myapp.tar myapp:1.0
docker save -o multi.tar nginx alpine   # 多个镜像

# 加载 tar 文件为镜像
docker load -i myapp.tar
docker load < myapp.tar

补充docker export / docker import 作用于容器,会丢失镜像层历史,不推荐常规使用。

2.12 快速参考表(镜像管理篇)

操作 指令
构建 docker build -t name:tag .
拉取 docker pull name:tag
推送 docker push repo/name:tag
列出镜像 docker images
查看详情 docker inspect name
查看历史 docker history name
删除 docker rmi name
打标签 docker tag src dst
登录仓库 docker login
搜索 docker search term
保存为文件 docker save -o file.tar name
从文件加载 docker load -i file.tar

总结

从编写 Dockerfile 到管理镜像,每一步都有其规范和技巧。回顾要点:

  • Dockerfile 编写:选择精简基础镜像、合并 RUN 命令、利用多阶段构建、避免 root 运行、添加健康检查。
  • 镜像管理指令 :掌握 buildpullpushtagrmisave/load 等,合理利用过滤和格式化输出。
  • 日常优化 :善用 .dockerignore、构建缓存、BuildKit 特性,定期清理虚悬镜像。

本文涵盖的内容足以支撑日常开发与运维中的绝大多数需求。随着使用深入,你还可以进一步学习多架构构建(docker buildx)、镜像签名(docker trust)以及容器编排中的镜像管理策略。

希望这份指南能成为你工作中的实用手册。如果有任何疑问或补充,欢迎留言交流! 该博客通过总结AI对话过程生成

相关推荐
用户329104422504111 小时前
基于 Claude Code 实现 CI/CD 完整流程
前端·后端
星栈11 小时前
别让 API 跳去登录页:我在 Axum 里做了认证失败双通道
前端·后端·开源
Cache技术分享11 小时前
416. 现代 Java I/O 最佳实践 - 高效、简洁、安全地处理文本与数据
前端·后端
倚栏听风雨11 小时前
EdgeValue 详细分析
后端
用户7138742290011 小时前
OAuth 2.0 中的state参数:从规范到实践的深度解析
后端
倚栏听风雨11 小时前
StateGraph 详细分析
后端
用户7138742290011 小时前
Cookie 深度技术指南:从原理到安全实践
后端
倚栏听风雨11 小时前
AsyncCommandAction 详细分析
后端
倚栏听风雨11 小时前
Edge 详细分析
后端