Docker 镜像与 Dockerfile 基础指南:从编写到管理
一份系统、实用的 Docker 镜像操作手册,涵盖 Dockerfile 编写规范与镜像全生命周期指令。
前言
Docker 容器化已成为现代应用交付的事实标准,而镜像则是容器的"源代码"。无论是构建自定义镜像,还是从仓库拉取、推送、管理现有镜像,掌握核心指令和编写技巧都是每一位开发者和运维工程师的必备技能。
本文基于实际工作中最常用的场景,分为两大章节:
- 如何编写高效的 Dockerfile:从基础指令到最佳实践,附带完整示例。
- 常用 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
忽略无关文件(.git、node_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,支持并行构建和缓存挂载dockerfileRUN --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
2.10 搜索镜像 -- docker search
在 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 运行、添加健康检查。
- 镜像管理指令 :掌握
build、pull、push、tag、rmi、save/load等,合理利用过滤和格式化输出。 - 日常优化 :善用
.dockerignore、构建缓存、BuildKit 特性,定期清理虚悬镜像。
本文涵盖的内容足以支撑日常开发与运维中的绝大多数需求。随着使用深入,你还可以进一步学习多架构构建(docker buildx)、镜像签名(docker trust)以及容器编排中的镜像管理策略。
希望这份指南能成为你工作中的实用手册。如果有任何疑问或补充,欢迎留言交流! 该博客通过总结AI对话过程生成