镜像与 Dockerfile
镜像(Image)是 Docker 容器的只读模板,熟悉镜像操作是使用 Docker 的起点;而 Dockerfile 则是描述「如何构建一个镜像」的文本文件,两者是一体两面。基础概念与安装见 Docker 基础概念、安装与命令速查。
一、镜像基础操作
1. 搜索镜像(docker search)
在 Docker Hub(默认公共仓库)中搜索镜像。
docker search nginx
- 输出包括镜像名称、描述、星级(受欢迎程度)、是否官方(
OFFICIAL)等。 - 常用选项:
--limit N限制搜索结果条数。
2. 拉取镜像(docker pull)
从仓库下载镜像到本地。
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)
列出已下载的镜像。
docker images
# 或
docker image ls
输出示例:
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)。
查看某个镜像的分层历史与构建指令:
docker history nginx
查看镜像详细元数据(环境变量、入口命令、暴露端口等):
docker inspect nginx
4. 删除镜像(docker rmi)
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)
为本地镜像创建一个新的别名(标签),通常用于准备推送到自定义仓库。
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)。
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 images 或 docker 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 | 声明容器运行时监听的端口(仅文档作用,不会自动映射,需配合 -p) | EXPOSE 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
# 使用轻量的 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 所在目录执行:
# 构建镜像,指定名称和标签(. 表示当前目录作为构建上下文)
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:
node_modules
.git
*.log
Dockerfile
.dockerignore
(2)多阶段构建(Multi-stage Builds)
在一个 Dockerfile 中使用多个 FROM 语句,将构建环境和运行环境分离,极大减小最终镜像体积——构建工具(编译器、devDependencies)只存在于中间阶段,不会进入最终镜像。
示例(Node.js + 构建前端静态文件):
# 第一阶段:构建
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-alpine、python:3.12-alpine。 - 还可以考虑
distroless(Google 提供,不含 shell 和包管理器,攻击面更小)用于最终运行阶段。 - 避免使用
latest标签(不够明确,可能随更新变化),生产环境建议锁定具体版本号,甚至锁定 digest(image@sha256:...)以保证可复现构建。
(4)合并 RUN 命令,减少层数
# 不推荐:多个 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可以在多次构建之间持久化依赖缓存目录,进一步加速:dockerfileRUN --mount=type=cache,target=/root/.npm npm ci
(6)减小镜像体积的其他手段
- 用
docker image prune定期清理悬空镜像;用docker history <image>排查哪一层体积异常大。 - 尽量在一层内下载、解压、删除临时文件,避免临时文件残留在某一层里(即使后续层删除了它,之前层的体积依旧会被保留)。
- 生产镜像不要安装调试工具(
vim、curl等),必要时用docker exec结合临时的 debug 容器(如docker run --pid=container:<id> ... nicolaka/netshoot)排障。
5. 总结
- Dockerfile 是构建镜像的蓝图,通过一系列指令定义环境和启动行为。
- 常用指令包括
FROM、WORKDIR、COPY、RUN、CMD、ENTRYPOINT、HEALTHCHECK等。 - 使用
.dockerignore、多阶段构建、轻量基础镜像、合并RUN、善用构建缓存等优化手段,可大幅减小镜像体积,提高构建效率。 - 构建命令:
docker build -t 名称:标签 .。
掌握镜像操作与 Dockerfile 编写,即可将应用容器化,实现环境一致性和快速部署;下一步可学习 容器、数据与网络 与 Docker Compose。
参考文献
| 资料 | 说明 |
|---|---|
| Docker 文档 | 官方 |
| Dockerfile 参考 | 指令完整列表 |
| 多阶段构建 | 官方指南 |
| 运维导读 | 学习路径 |
相关文章
Docker Compose 编排
Docker Compose 是定义和运行多容器 Docker 应用的工具,通过一个 compose.yml 文件即可管理 Web、数据库、缓存等多个服务。本文覆盖安装、完整字段说明、多服务示例、常用指令与常见排错。
Docker 基础概念、安装与命令速查
Docker 是一个开源的容器化平台,能将应用程序及其所有依赖打包成轻量级、可移植的容器。本文介绍核心概念、底层原理、跨平台安装配置,并附完整的命令速查表,是学习 Docker 的第一篇。
容器、数据与网络
容器是镜像的运行实例,掌握容器的创建、管理、日志查看,配合数据卷持久化与自定义网络通信,是使用 Docker 的日常核心,也是生产部署前必须掌握的三大基础能力。
运维与协作导读
本目录覆盖日常开发运维中的 Git 版本控制、Docker 容器化与 Nginx 服务网关,与 工程化 · Git、部署相关 等章节互补,提供完整的十阶段学习路径。
后端入门概览
本目录覆盖 JavaScript/TypeScript 服务端运行时与框架、数据存储,以及 Rust 系统编程入门,提供从零到部署的完整学习路径。前置建议:JavaScript 基础、工程化 · 环境变量。
Bun 基础与核心命令
Bun 是用 Zig 编写的 JavaScript 运行时,内置包管理(bun install)、打包(bun build)、测试(bun test)等,并持续兼容 Node.js API。本文介绍核心特点、安装方式,以及日常最常用的命令与包管理功能。见 运行时对比。
Series
docker
2 / 4