未记录事实核验 · 状态:维护中

记录仅说明核验时间与维护状态,不保证适用于所有环境;使用前请留意正文中的版本、适用条件与风险提示。

warning 适用范围与待维护事项

本文适用于已安装 Docker、具备基本命令行能力的学习者;删除与清理练习应在可丢弃环境完成,勿直接用于共享或生产主机。阿里云“免费”政策、Docker Hub规模判断、推荐仓库标签及加速端点均未核实,不作为采购或生产选型依据。推送示例需预先拥有本地 my-etl-app:v1.0、仓库及相应权限;离线迁移需核对目标平台。生产部署应核对镜像来源、维护状态与摘要,清理卷前须备份并确认用途。

Docker 镜像管理

abstract 本章要点

  • 理解镜像的命名规则和标签体系
  • 在 Docker Hub / 阿里云仓库找到合适的镜像
  • 掌握镜像拉取、查看、删除的常用命令
  • 了解如何推送镜像到仓库

镜像是什么(复习)

镜像(Image)是容器的"安装包"——一个只读的文件系统快照,包含了运行应用所需的一切:代码、运行时、库、配置文件。

镜像和容器的关系:

  • 镜像是模板(静态的,不会变)
  • 容器是镜像跑起来的实例(动态的,可以启停)
  • 同一个镜像可以同时运行多个容器

镜像命名规则

Docker 镜像的完整命名格式:

[注册表地址/][命名空间/]镜像名[:标签][@摘要]

官方镜像(Docker Hub)

mysql:8.0
  │       │
  │       └─ 标签(版本),省略则默认 latest
  └─ 镜像名(官方镜像只有名称,没有用户名前缀)

python:3.11-slim
nginx:alpine
postgres:16

社区/用户镜像(Docker Hub)

bitnami/kafka:3.6
  │       │     │
  │       │     └─ 标签
  │       └─ 镜像名
  └─ 用户名/组织名

confluentinc/cp-kafka:7.5.0
jupyter/pyspark-notebook:latest

私有仓库镜像

registry.aliyuncs.com/my-namespace/my-app:v1.0
    │                      │            │     │
    │                      │            │     └─ 标签
    │                      │            └─ 镜像名
    │                      └─ 命名空间(相当于用户名)
    └─ 注册表地址(私有仓库域名)

标签(Tag)的含义

标签用来区分同一镜像的不同版本,强烈建议不要使用 latest。

标签示例 含义
mysql:8.0 MySQL 8.0 版本
python:3.11-slim Python 3.11,slim 表示精简版(体积小)
nginx:alpine 基于 Alpine Linux 的 nginx,体积极小
postgres:16-bullseye PostgreSQL 16,基于 Debian Bullseye
mysql:latest 发布者维护的 latest 标签,不保证是最新版本(不推荐在生产中使用)

warning 不要在生产环境使用 latest 标签

latest 是发布者维护的标签,不保证指向最新版本,且其指向可能变化并引入不兼容的更新。数据工程中建议记录具体版本号,如 mysql:8.0.36;版本标签也可能被重新指向,要固定镜像内容应使用并记录镜像摘要(digest),同时核对目标平台。


Docker Hub 找镜像

Docker Hub 是最大的公开镜像仓库,数据工程师常用的官方镜像都在这里。

命令行搜索

# 搜索 MySQL 相关镜像
docker search mysql

# 输出示例:
# NAME                    DESCRIPTION                   STARS   OFFICIAL
# mysql                   MySQL is a widely used...     15000   [OK]
# bitnami/mysql           Bitnami container image...    1200
# mysql/mysql-server      Optimized MySQL Server...     1000

# 只显示官方镜像
docker search --filter is-official=true python

# 限制显示条数
docker search --limit 5 kafka

网页搜索

推荐直接在 hub.docker.com 搜索,可以看到:

  • 镜像的文档和使用说明
  • 所有可用的标签(Tags)列表
  • 下载量(评估镜像流行度)
  • 是否为官方镜像

数据工程师常用镜像速查

工具 镜像名 推荐标签
MySQL mysql 8.0、8.4
PostgreSQL postgres 16、15
Redis redis 7-alpine
Kafka bitnami/kafka 3.7、latest
Spark bitnami/spark 3.5、latest
Flink flink 1.19、1.18
Hadoop apache/hadoop 3
Jupyter jupyter/pyspark-notebook latest
Python python 3.11-slim、3.12-slim
Airflow apache/airflow 2.9.0
Zookeeper zookeeper 3.8、3.9

核心镜像命令

docker pull 拉取镜像

# 拉取默认 latest 标签(不保证是最新版本,不推荐用于生产)
docker pull mysql

# 拉取指定版本(推荐)
docker pull mysql:8.0

# 拉取指定版本(默认输出拉取进度)
docker pull postgres:16

# 从指定仓库拉取(使用国内镜像加速)
docker pull docker.mirrors.ustc.edu.cn/library/mysql:8.0

# 拉取多架构镜像中的特定平台版本
docker pull --platform linux/amd64 mysql:8.0

拉取过程中可以看到分层下载的进度:

8.0: Pulling from library/mysql
72a69066d2fe: Pull complete    # 每一行是镜像的一个层(layer)
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
...
Digest: sha256:xxxxxxxx         # 镜像的唯一标识
Status: Downloaded newer image for mysql:8.0

docker images 查看本地镜像

# 列出所有本地镜像
docker images

# 输出示例:
# REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
# mysql        8.0       a3b6608898d6   2 weeks ago    596MB
# postgres     16        ced297a2c3a1   3 weeks ago    431MB
# redis        7-alpine  a5f5d8ba5b9c   4 weeks ago    41.1MB

# 只显示镜像 ID(常用于批量操作)
docker images -q

# 按名称过滤
docker images mysql

# 显示所有镜像(包含中间层镜像)
docker images -a

# 自定义显示格式
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"

docker rmi 删除镜像

# 删除指定镜像(用名称:标签)
docker rmi mysql:8.0

# 删除指定镜像(用 IMAGE ID)
docker rmi a3b6608898d6

# 强制删除:可处理部分引用冲突,但不能强制删除运行中容器所用的镜像;不要绕过依赖检查
docker rmi -f mysql:8.0

# 删除所有本地镜像(谨慎使用!)
docker rmi $(docker images -q)

# 删除未被容器引用的悬空镜像(通常没有标签;不等于清理全部构建缓存)
docker image prune

# 删除所有未使用的镜像(不只是悬空的)
docker image prune -a

warning 删除镜像前确认

如果有容器(包括已停止的容器)在使用某个镜像,直接 rmi 会报错。先用 docker ps -a 检查容器,docker rm 删除容器后再删镜像。

docker inspect 查看镜像详情

# 查看镜像的详细元数据(JSON 格式)
docker inspect mysql:8.0

# 只查看特定字段(如暴露的端口)
docker inspect --format '{{.Config.ExposedPorts}}' mysql:8.0

# 查看镜像的构建历史(每一层做了什么)
docker history mysql:8.0

镜像仓库操作

登录 Docker Hub

# 登录 Docker Hub(需要有账号)
docker login
# 按当前客户端提示完成登录;可能使用浏览器设备码流程

# 凭据保存方式取决于配置:可能使用外部凭据存储;未配置时可能以非加密的编码形式保存在 ~/.docker/config.json,勿共享该文件
# 退出登录
docker logout

推送镜像到 Docker Hub

# 1. 先给镜像打上你的用户名前缀标签
docker tag my-etl-app:v1.0 yourusername/my-etl-app:v1.0

# 2. 推送到 Docker Hub
docker push yourusername/my-etl-app:v1.0

阿里云容器镜像服务(私有仓库)

阿里云提供了免费的私有镜像仓库,适合存放公司内部的镜像。

# 1. 登录阿里云镜像仓库(替换为你的仓库地址)
docker login --username=your_aliyun_account \
  registry.cn-hangzhou.aliyuncs.com

# 2. 给镜像打标签(替换为你的命名空间和仓库名)
docker tag my-etl-app:v1.0 \
  registry.cn-hangzhou.aliyuncs.com/your-namespace/my-etl-app:v1.0

# 3. 推送镜像
docker push registry.cn-hangzhou.aliyuncs.com/your-namespace/my-etl-app:v1.0

# 4. 从阿里云拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/your-namespace/my-etl-app:v1.0

导入导出镜像(离线场景)

在无法访问外网的服务器上,可以先在有网的机器上下载镜像,然后传输到目标服务器。

# 将镜像保存为 tar 文件
docker save mysql:8.0 -o mysql_8.0.tar

# 将多个镜像打包成一个文件
docker save mysql:8.0 redis:7-alpine -o data_services.tar

# 在目标服务器上加载镜像
docker load -i mysql_8.0.tar

# 加载后验证
docker images

tip 镜像压缩传输

镜像 tar 文件通常很大,传输前可以压缩:

# 保存并压缩
docker save mysql:8.0 | gzip > mysql_8.0.tar.gz

# 加载压缩文件
docker load -i mysql_8.0.tar.gz

管理本地镜像的最佳实践

定期清理

# 查看 Docker 磁盘使用情况
docker system df

# 输出示例:
# TYPE            TOTAL   ACTIVE  SIZE      RECLAIMABLE
# Images          12      5       8.234GB   5.123GB (62%)
# Containers      8       3       234MB     123MB (52%)
# Local Volumes   5       3       2.1GB     450MB (21%)
# Build Cache     0       0       0B        0B

# 高风险清理:删除停止的容器、未使用的网络和镜像,并按当前 Docker 版本规则清理未使用卷;可能丢失卷内数据,执行前确认清理范围并备份
docker system prune -a --volumes

镜像版本策略

环境 建议策略
本地开发 可用 latest 做临时试验;标签变化不代表本地镜像自动更新,需重新拉取
测试环境 使用次版本号,如 mysql:8.0
生产环境 记录完整版本号,如 mysql:8.0.36,并使用摘要固定镜像内容;通过受控流程更新安全补丁


info 前置知识


掌握检查

  • [ ] 能用 docker pull mysql:8.0 拉取指定版本镜像,而不是 docker pull mysql(避免用 latest 在生产上)
  • [ ] 能用 docker images 列出本地镜像,知道 REPOSITORY、TAG、IMAGE ID、SIZE 各列的含义
  • [ ] 知道 docker image prune 和 docker rmi 的区别:前者默认清理未被容器引用的悬空镜像,后者删除指定镜像;docker image prune -a 会扩大到所有未被容器引用的镜像
  • [ ] 能用 docker history 镜像名 查看镜像的每一层构建历史,了解镜像是如何一层层叠加的
  • [ ] 知道在无公网环境的生产服务器上,用 docker save + scp + docker load 的方式传输镜像

实践练习

基础题:搜索并拉取 Redis 官方镜像(redis:7-alpine,选 alpine 版本体积更小),用 docker images 查看大小,用 docker history 查看构建层数,然后用 docker tag 给它加一个自定义标签。

进阶题:用 docker system df 查看当前 Docker 磁盘占用,然后清理所有不再使用的镜像和悬空镜像,再次查看磁盘占用对比变化。


下一步

学会了镜像管理,下一步是学如何用镜像启动容器并进行操作:

tip 数据工程师的镜像使用习惯

建议建立一个文本文件(如 docker-images.txt),记录你项目中用到的所有镜像及其版本。这样换机器或给新同事配置环境时,可以快速批量拉取所需镜像:

# 批量拉取镜像
cat docker-images.txt | xargs -I{} docker pull {}