第二章:Docker镜像管理——镜像的获取与查看、搜索与下载、构建、导出导入、删除与清理
镜像管理,说白了就是Docker世界的「物资管理」。你想想看,没有镜像,容器就是空中楼阁。我刚开始接触Docker那会儿,最头疼的就是镜像越积越多,硬盘报警,还搞不清哪个镜像有用哪个是垃圾。这一章,我就把镜像管理的全套功夫给你捋一遍。
2.1 镜像的获取与查看
先说说怎么拿到镜像。最直接的方式,就是从仓库拉取。我个人习惯用官方仓库,稳定可靠。
# 拉取一个镜像
docker pull nginx:latest
# 拉取指定版本
docker pull nginx:1.21-alpine
拉下来之后,怎么看?用 docker images 或者 docker image ls。我一般用后者,语义更清晰。
docker image ls
输出结果会显示仓库名、标签、镜像ID、创建时间和大小。这里有个坑——镜像ID是唯一的,但仓库名和标签可以重复。我曾经在项目里遇到过,同事拉了两个不同版本的镜像,标签都写成了latest,结果搞混了。所以,生产环境一定要用具体版本号,别偷懒用latest。
docker image inspect。它会返回一个JSON,包含层信息、环境变量、入口点等。我排查问题时经常用这招。
2.2 镜像的搜索与下载
不知道用什么镜像?先搜一下。Docker Hub上镜像海量,但质量参差不齐。
# 搜索镜像
docker search nginx
# 搜索时过滤,只看官方镜像
docker search --filter "is-official=true" nginx
搜索结果会显示名称、描述、星数、是否官方等。我个人建议:优先选官方镜像,其次选星数高、更新活跃的社区镜像。为什么?官方镜像经过安全审核,漏洞少。我曾经图省事用了一个不知名镜像,结果里面藏了挖矿脚本,教训深刻。
下载就是 docker pull。注意,它会分层下载,每一层都有哈希校验。如果网络不好,可以配置镜像加速器。我在国内项目里,一般用阿里云或中科大的加速器。
# 配置镜像加速(以Linux为例)
# 编辑 /etc/docker/daemon.json
{
"registry-mirrors": ["https://your-mirror.mirror.aliyuncs.com"]
}
# 重启docker
systemctl restart docker
2.3 镜像的构建——Dockerfile基础
这才是镜像管理的核心。Dockerfile,就是镜像的「配方」。我见过很多新手,把Dockerfile写得又臭又长,一个镜像几个G。其实,好的Dockerfile讲究「精炼」和「分层」。
先看一个最简单的例子:
# 基础镜像
FROM node:18-alpine
# 设置工作目录
WORKDIR /app
# 复制依赖文件
COPY package.json package-lock.json ./
# 安装依赖
RUN npm install --production
# 复制源码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动命令
CMD ["node", "server.js"]
这里有几个关键点:
- FROM:基础镜像,尽量选alpine版本,体积小。我有个项目,从ubuntu换到alpine,镜像从1.2G缩到300M。
- WORKDIR:设置工作目录,避免路径混乱。
- COPY:复制文件。注意顺序——把不常变动的文件放前面,利用Docker的缓存机制。我习惯先复制package.json,再复制源码,这样依赖没变时,npm install那层缓存就能复用。
- RUN:执行命令。每个RUN会生成一个新层,所以尽量合并命令。比如
RUN apt-get update && apt-get install -y xxx && rm -rf /var/lib/apt/lists/*,这样只生成一层。 - CMD 和 ENTRYPOINT:定义容器启动时的行为。CMD可以被覆盖,ENTRYPOINT不行。我一般用ENTRYPOINT指定可执行文件,CMD传默认参数。
2.4 镜像的导出与导入
有时候,你需要把镜像从一台机器搬到另一台,但没网。这时候,导出导入就派上用场了。
# 导出镜像为tar文件
docker save -o nginx.tar nginx:latest
# 或者用重定向
docker save nginx:latest > nginx.tar
# 导入镜像
docker load -i nginx.tar
docker save 保存的是完整镜像,包括所有层和元数据。而 docker export 导出的是容器的文件系统,不包含元数据。我一般用save/load,因为能保留镜像的标签和历史。
docker save nginx:latest | gzip > nginx.tar.gz,导入时 gunzip -c nginx.tar.gz | docker load。
2.5 镜像的删除与清理
镜像用久了,磁盘空间会告急。删除镜像很简单:
# 删除单个镜像
docker rmi nginx:latest
# 删除多个
docker rmi nginx:latest redis:latest
# 强制删除(镜像被容器引用时)
docker rmi -f nginx:latest
但真正头疼的是清理。Docker会留下很多「悬空镜像」——没有标签、没有被任何容器引用的镜像。它们占着空间,却毫无用处。
# 查看悬空镜像
docker image ls -f "dangling=true"
# 清理所有悬空镜像
docker image prune
# 清理所有未使用的镜像(包括被容器引用但容器已停止的)
docker image prune -a
我一般每周跑一次 docker image prune -a,配合 docker container prune 和 docker volume prune,能释放大量空间。有一次,我清理后发现磁盘从85%降到了30%,效果立竿见影。
0 3 * * * docker image prune -a -f。注意加 -f 跳过确认。
2.6 镜像管理的最佳实践
最后,分享几个我多年积累的经验:
- 标签管理:别只用latest。我习惯用
项目名-版本号-构建日期的格式,比如myapp-v1.2.3-20250101,方便回溯。 - 定期清理:镜像不是越多越好。我见过有人机器上存了上百个镜像,90%都没用。每周清理一次,养成习惯。
- 安全扫描:拉下来的镜像,最好扫一下漏洞。可以用
docker scan或第三方工具。我有个项目,就是因为没扫,上线后被爆出高危漏洞,紧急回滚。 - 私有仓库:公司内部用,建议搭一个私有仓库(Harbor或Registry)。安全可控,还能做镜像复制。
嗯,镜像管理这块,说白了就是「拿来、造好、存好、清掉」四个步骤。每一步都有门道,但掌握了这些,你就能在Docker世界里游刃有余。下一章,我们聊聊容器管理,那才是真正跑起来的东西。