FORMA

镜像与 Dockerfile

镜像(Image)是 Docker 容器的只读模板,熟悉镜像操作是使用 Docker 的起点;而 Dockerfile 则是描述「如何构建一个镜像」的文本文件,两者是一体两面。基础概念与安装见 Docker 基础概念、安装与命令速查

一、镜像基础操作

在 Docker Hub(默认公共仓库)中搜索镜像。

bash
docker search nginx
  • 输出包括镜像名称、描述、星级(受欢迎程度)、是否官方(OFFICIAL)等。
  • 常用选项:--limit N 限制搜索结果条数。

2. 拉取镜像(docker pull

从仓库下载镜像到本地。

bash
docker pull nginx               # 拉取最新版(标签 latest)
docker pull nginx:1.25          # 拉取指定版本标签
docker pull alpine:3.18         # 拉取 Alpine Linux 3.18 版本
  • 如果不指定标签,默认使用 :latest(不推荐在生产环境依赖隐式 latest,版本升级可能悄悄引入不兼容变更)。
  • 支持私有仓库:docker pull myregistry.com/myimage:v1
  • 支持多架构镜像(manifest list):同一个 tag 在不同 CPU 架构(amd64 / arm64)下会自动拉取匹配的那一份,可用 docker buildx imagetools inspect <image> 查看包含哪些架构。

3. 查看本地镜像(docker images

列出已下载的镜像。

bash
docker images
# 或
docker image ls

输出示例:

text
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        latest    abc123def456   2 days ago    142MB
alpine       3.18      789ghi012jkl   3 weeks ago   7.05MB
  • -a 显示所有镜像(包含中间层)。
  • -q 只显示镜像 ID,常配合脚本批量操作,如 docker rmi $(docker images -q)

查看某个镜像的分层历史与构建指令:

bash
docker history nginx

查看镜像详细元数据(环境变量、入口命令、暴露端口等):

bash
docker inspect nginx

4. 删除镜像(docker rmi

bash
docker rmi nginx:1.25           # 删除指定仓库:标签
docker rmi abc123def456          # 通过镜像 ID 删除
docker rmi -f <image-id>         # 强制删除(即使有容器正在使用,通常不建议)
docker image prune               # 删除所有悬空镜像(dangling images,无标签且无容器使用)
docker image prune -a            # 删除所有未使用的镜像(更激进)
  • 如果镜像被容器(包括停止的容器)引用,需要先删除相关容器或使用 -f 强制删除。

5. 打标签(docker tag

为本地镜像创建一个新的别名(标签),通常用于准备推送到自定义仓库。

bash
docker tag nginx:latest myrepo/nginx:v1
  • 格式:docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
  • 示例中,将本地 nginx:latest 赋予一个新标签 myrepo/nginx:v1(仓库 myrepo,镜像名 nginx,标签 v1)。
  • 注意:tag 并不复制镜像数据,只是新增一个指向同一份镜像层的引用,因此几乎不占用额外磁盘空间。

6. 推送镜像到仓库(docker push

将本地镜像上传到远程仓库(需先登录:docker login)。

bash
docker push myrepo/nginx:v1
  • 推送前需确保镜像标签包含仓库地址(如 myrepo/registry.example.com/myrepo/)。
  • 若推送 Docker Hub,仓库名默认为 Docker Hub 用户名或组织名。
  • 推送私有仓库需指定完整域名:docker push registry.example.com/myapp:v1

7. 镜像存储位置

Docker 镜像默认存储在 /var/lib/docker(Linux)。一般不需要手动操作,使用 docker 命令管理即可。

镜像操作总结表

操作命令
搜索镜像docker search <name>
拉取镜像docker pull <image>:<tag>
查看镜像docker imagesdocker image ls
查看构建历史docker history <image>
删除镜像docker rmi <image>
清理悬空镜像docker image prune
打标签docker tag <source> <target>
推送镜像docker push <image>

掌握这些命令,就能基本管理 Docker 镜像的生命周期。

二、Dockerfile 基础

Dockerfile 是一个文本文件,包含一系列指令,用于自动化构建 Docker 镜像。通过 Dockerfile,你可以定义应用的环境、依赖、启动命令等,确保应用在任何支持 Docker 的平台上一致运行。每条指令通常会在镜像上新增一层,层与层之间可以复用缓存。

1. 常用指令

指令说明示例
FROM指定基础镜像(必须是第一条指令,多阶段构建可出现多次)FROM node:18-alpine
WORKDIR设置工作目录(如果目录不存在则创建)WORKDIR /app
COPY将构建上下文中的文件/目录复制到镜像中COPY package.json .
ADD类似 COPY,但支持自动解压 tar 包和拉取 URL(一般优先用 COPY,行为更可预测)ADD app.tar.gz /app
RUN在构建镜像时执行命令(通常用于安装依赖)RUN npm install
CMD容器启动时执行的默认命令(可被 docker run 后面的参数覆盖)CMD ["node", "app.js"]
ENTRYPOINT容器启动时的入口命令(更灵活,不易被覆盖)ENTRYPOINT ["npm", "start"]
EXPOSE声明容器运行时监听的端口(仅文档作用,不会自动映射,需配合 -pEXPOSE 3000
ENV设置环境变量(在构建阶段和容器运行时均可用)ENV NODE_ENV=production
ARG定义构建时变量(仅在构建阶段有效,docker build --build-arg 传入)ARG VERSION=1.0
VOLUME声明匿名数据卷挂载点,防止该目录写入可写层VOLUME /data
USER指定后续指令及容器运行时使用的用户,避免以 root 运行USER node
LABEL为镜像添加元数据(作者、版本等键值对)LABEL maintainer="a@b.com"
HEALTHCHECK定义容器健康检查命令,供 docker ps / 编排系统探测HEALTHCHECK CMD curl -f http://localhost/ || exit 1

CMD 与 ENTRYPOINT 的区别

  • CMD 的默认参数可以被 docker run 后面的命令整体覆盖。
  • ENTRYPOINT 通常用于定义可执行文件,CMD 提供默认参数,两者可组合使用,如 ENTRYPOINT ["node"] + CMD ["app.js"]docker run image other.js 会变成 node other.js

2. 示例:Node.js 应用的 Dockerfile

dockerfile
# 使用轻量的 Alpine 基础镜像
FROM node:18-alpine

# 设置工作目录
WORKDIR /app

# 复制 package.json 和 package-lock.json(先复制依赖文件,利用缓存)
COPY package*.json ./

# 安装生产依赖(不安装 devDependencies)
RUN npm ci --only=production

# 复制其余源代码
COPY . .

# 声明容器监听的端口(文档作用)
EXPOSE 3000

# 建议以非 root 用户运行
USER node

# 容器启动时运行应用
CMD ["node", "server.js"]

3. 构建镜像

在 Dockerfile 所在目录执行:

bash
# 构建镜像,指定名称和标签(. 表示当前目录作为构建上下文)
docker build -t myapp:v1 .

# 使用非默认名称的 Dockerfile(如 Dockerfile.dev)
docker build -f Dockerfile.dev -t myapp:dev .

常用构建选项

  • -t, --tag:设置镜像名称和标签(可省略标签,默认为 latest)。
  • -f, --file:指定 Dockerfile 路径。
  • --no-cache:不使用缓存,强制重新构建所有步骤。
  • --build-arg:传递构建时变量,例如 --build-arg VERSION=1.2(配合 ARG 使用)。
  • --platform:指定目标架构,如 --platform linux/amd64,linux/arm64(配合 docker buildx 构建多架构镜像)。

4. 常见优化技巧

(1)使用 .dockerignore 文件

类似 .gitignore,忽略不需要的文件(如 node_modules.git、日志文件等),加快构建速度并减小镜像体积、避免敏感文件被带入镜像。

示例 .dockerignore

text
node_modules
.git
*.log
Dockerfile
.dockerignore

(2)多阶段构建(Multi-stage Builds)

在一个 Dockerfile 中使用多个 FROM 语句,将构建环境和运行环境分离,极大减小最终镜像体积——构建工具(编译器、devDependencies)只存在于中间阶段,不会进入最终镜像。

示例(Node.js + 构建前端静态文件):

dockerfile
# 第一阶段:构建
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# 第二阶段:运行(只复制构建产物)
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

(3)选择轻量基础镜像

  • 官方镜像通常提供 -alpine(基于 Alpine Linux)版本,体积极小,适合生产环境。例如 node:18-alpinepython:3.12-alpine
  • 还可以考虑 distroless(Google 提供,不含 shell 和包管理器,攻击面更小)用于最终运行阶段。
  • 避免使用 latest 标签(不够明确,可能随更新变化),生产环境建议锁定具体版本号,甚至锁定 digest(image@sha256:...)以保证可复现构建。

(4)合并 RUN 命令,减少层数

dockerfile
# 不推荐:多个 RUN 命令产生多个层,且中间产物也会被保留
RUN apt update
RUN apt install -y curl
RUN rm -rf /var/lib/apt/lists/*

# 推荐:合并成一条命令(使用 &&),清理动作在同一层内完成才能真正释放空间
RUN apt update && apt install -y curl && rm -rf /var/lib/apt/lists/*

(5)利用构建缓存

  • 将容易变化的指令放在 Dockerfile 末尾(如 COPY . .)。
  • 先用 COPY 复制依赖文件并执行安装,再复制源代码,这样只要依赖文件不变,就会使用缓存,跳过耗时的依赖安装步骤。
  • 使用 BuildKit(Docker 新版默认开启)的 --mount=type=cache 可以在多次构建之间持久化依赖缓存目录,进一步加速:
    dockerfile
    RUN --mount=type=cache,target=/root/.npm npm ci
    

(6)减小镜像体积的其他手段

  • docker image prune 定期清理悬空镜像;用 docker history <image> 排查哪一层体积异常大。
  • 尽量在一层内下载、解压、删除临时文件,避免临时文件残留在某一层里(即使后续层删除了它,之前层的体积依旧会被保留)。
  • 生产镜像不要安装调试工具(vimcurl 等),必要时用 docker exec 结合临时的 debug 容器(如 docker run --pid=container:<id> ... nicolaka/netshoot)排障。

5. 总结

  • Dockerfile 是构建镜像的蓝图,通过一系列指令定义环境和启动行为。
  • 常用指令包括 FROMWORKDIRCOPYRUNCMDENTRYPOINTHEALTHCHECK 等。
  • 使用 .dockerignore、多阶段构建、轻量基础镜像、合并 RUN、善用构建缓存等优化手段,可大幅减小镜像体积,提高构建效率。
  • 构建命令:docker build -t 名称:标签 .

掌握镜像操作与 Dockerfile 编写,即可将应用容器化,实现环境一致性和快速部署;下一步可学习 容器、数据与网络Docker Compose

参考文献

资料说明
Docker 文档官方
Dockerfile 参考指令完整列表
多阶段构建官方指南
运维导读学习路径

相关文章