📘 第03课:镜像管理

基础 深入理解Docker镜像的分层结构,掌握搜索、拉取、构建、推送

🔍 什么是Docker镜像?

Docker镜像是一个只读的模板,包含创建容器所需的文件系统层和配置信息。镜像是容器的"蓝图"——同一个镜像可以创建无数个容器实例。

镜像与容器的关系: ┌─────────────────────────┐ │ Docker Image │ ┌───────────────────────┐ │ ┌───────────────────┐ │ │ Container 1 │ │ │ Layer 3: App │ │────►│ + 可写层(Writable) │ │ ├───────────────────┤ │ └───────────────────────┘ │ │ Layer 2: Deps │ │────►┌───────────────────────┐ │ ├───────────────────┤ │ │ Container 2 │ │ │ Layer 1: Base OS │ │────►│ + 可写层(Writable) │ │ └───────────────────┘ │ └───────────────────────┘ │ (只读,不可修改) │ └─────────────────────────┘ 镜像 = 多个只读层叠加(UnionFS) 容器 = 镜像 + 可写层(Container Layer)

📐 镜像命名规范

Docker镜像名称由三部分组成:

[registry/]repository[:tag]

# 示例解析:
docker.io/library/nginx:1.25-alpine
│         │       │    │
│         │       │    └── Tag(版本标签,默认latest)
│         │       └────── Repository(仓库名)
│         └────────────── Namespace(命名空间/用户)
└──────────────────────── Registry(注册服务器)

# 常见写法:
nginx                    # = docker.io/library/nginx:latest
nginx:1.25               # 指定版本
nginx:alpine             # Alpine版
myregistry.com/myapp:v1  # 私有仓库
username/myapp:latest     # Docker Hub个人仓库

🔎 搜索镜像

# 在Docker Hub搜索镜像 ✅
docker search nginx
NAME                   DESCRIPTION                    STARS   OFFICIAL
nginx                  Official build of Nginx.       19000   [OK]
nginx/nginx-ingress    NGINX Ingress Controller       350

# 过滤星级 ≥ 50 的镜像
docker search --filter stars=50 nginx

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

# 限制结果数量
docker search --limit 5 nginx
💡 如何选择镜像?
  1. 优先选官方镜像(OFFICIAL = [OK])
  2. 关注STARS数量(社区认可度)
  3. 优先选Alpine版(体积小,安全攻击面小)
  4. 检查最近更新时间(在Docker Hub网页查看)

⬇️ 拉取镜像

# 拉取最新版本 ✅
docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete
a9edb18cadd1: Pull complete
589b7251471a: Pull complete

# 拉取指定版本 ✅
docker pull nginx:1.25-alpine

# 拉取所有标签(不推荐)
docker pull --all-tags nginx

# 从指定平台拉取
docker pull --platform linux/arm64 nginx

# 使用镜像加速器拉取
docker pull mirror.ccs.tencentyun.com/library/nginx:latest

镜像拉取过程详解

docker pull nginx 的分层拉取: 检查本地 → 已有层跳过 → ✓ 已存在 缺失层下载 → ⬇ 下载中... Layer 1 (基础层): a2abf6c4d29d ✓ Pull complete (32MB) Layer 2 (依赖层): a9edb18cadd1 ✓ Pull complete (25MB) Layer 3 (应用层): 589b7251471a ✓ Pull complete (4MB) Layer 4 (配置层): f5b0c2dca9e1 ✓ Pull complete (1KB) Layer 5 (入口层): d3a0e2f9b1c4 ✓ Pull complete (3KB) 分层设计的优势: - 多个镜像可共享相同的底层 → 节省磁盘空间 - 拉取时跳过已有层 → 节省带宽 - 推送时只传差异层 → 节省时间

📋 列出镜像

# 列出本地所有镜像 ✅
docker images
REPOSITORY   TAG        IMAGE ID       CREATED        SIZE
nginx        latest     605c77e624dd   2 weeks ago    187MB
ubuntu       22.04      58db3edaf2be   3 weeks ago    77.8MB
redis        7-alpine   3c5b4a53de57   4 weeks ago    32.4MB

# 只显示镜像ID
docker images -q

# 过滤显示
docker images nginx
docker images --filter "dangling=true"    # 悬空镜像(无标签)
docker images --filter "since=ubuntu"      # 在某镜像之后构建的
docker images --format "{{.Repository}}:{{.Tag}}"  # 自定义格式

🔬 镜像详细信息

# 查看镜像详情 ✅
docker inspect nginx

# 查看特定字段
docker inspect nginx --format='{{.Config.Env}}'
docker inspect nginx --format='{{.Config.ExposedPorts}}'
docker inspect nginx --format='{{.RootFS.Layers}}'

# 查看镜像构建历史 ✅
docker history nginx
IMAGE          CREATED       CREATED BY                                SIZE
605c77e624dd   2 weeks ago   /bin/sh -c #(nop)  CMD ["nginx" "-g"...  0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  STOPSIGNAL SIGQUIT    0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  EXPOSE 80             0B
<missing>      2 weeks ago   /bin/sh -c #(nop) COPY entrypoint.sh...  1.2kB

# 查看镜像层信息 ✅
docker image inspect nginx --format='{{json .RootFS.Layers}}'

🏷️ 镜像标签

# 为镜像打标签 ✅
docker tag nginx:latest myregistry.com/myapp/nginx:v1.0

# 同一镜像可以有多个标签
docker tag nginx:latest myapp/nginx:stable
docker tag nginx:latest myapp/nginx:1.25

# 验证:同一IMAGE ID,不同标签
docker images | grep nginx
myregistry.com/myapp/nginx   v1.0     605c77e624dd   2 weeks ago   187MB
myapp/nginx                  stable   605c77e624dd   2 weeks ago   187MB
myapp/nginx                  1.25     605c77e624dd   2 weeks ago   187MB

📤 推送镜像

# 登录Docker Hub
docker login

# 登录私有仓库
docker login myregistry.com

# 推送镜像 ✅
docker push myregistry.com/myapp/nginx:v1.0

# 推送所有标签
docker push --all-tags myregistry.com/myapp/nginx

🗑️ 删除镜像

# 删除镜像(需无容器使用)
docker rmi nginx:1.25-alpine

# 强制删除
docker rmi -f nginx:1.25-alpine

# 删除所有悬空镜像 ✅
docker image prune

# 删除所有未使用镜像
docker image prune -a

# 删除所有镜像(危险!)
docker rmi $(docker images -q)

💾 导出与导入镜像

# 导出为tar文件 ✅
docker save -o nginx.tar nginx:latest

# 导出多个镜像
docker save -o images.tar nginx:latest redis:7-alpine ubuntu:22.04

# 压缩导出
docker save nginx:latest | gzip > nginx.tar.gz

# 从tar文件导入 ✅
docker load -i nginx.tar

# 从压缩文件导入
gunzip -c nginx.tar.gz | docker load
ℹ️ docker save vs docker export

📊 镜像大小对比

基础镜像大小包管理器适用场景
alpine~7MBapk微服务、CLI工具(首选)
distroless~2MB安全敏感场景(无shell)
slim (Debian)~80MBapt需要glibc兼容性
ubuntu~77MBapt通用开发环境
debian~124MBapt稳定性优先
centos/rhel~200MByum/dnf企业兼容性
node:alpine~180MBapkNode.js运行时
python:slim~150MBaptPython运行时

🌐 常用官方镜像选择指南

# Web服务器
nginx:alpine              # 首选,轻量快速
httpd:alpine              # Apache
caddy:alpine              # 自动HTTPS

# 应用运行时
node:20-alpine            # Node.js
python:3.12-slim          # Python
openjdk:21-jdk-slim       # Java
golang:1.22-alpine        # Go

# 数据库
postgres:16-alpine        # PostgreSQL
mysql:8.0                 # MySQL(无alpine版)
redis:7-alpine            # Redis
mongo:7                   # MongoDB

❓ 常见问题

❓ 什么是悬空镜像(dangling image)? 悬空镜像是指没有标签的镜像(:),通常在构建新版本镜像后产生——旧镜像失去了原来的标签。用docker image prune清理,安全无副作用。
❓ pull镜像超时怎么办? ①配置镜像加速器(见第01课)②重试:docker pull支持断点续传 ③使用代理:HTTP_PROXY=http://proxy:port docker pull nginx ④下载离线镜像包用docker load导入。
❓ 镜像和容器到底什么区别? 镜像 = 只读模板(类),容器 = 运行实例(对象)。同一个镜像可以创建多个容器。类比面向对象:镜像是Class,容器是Object。
❓ 如何查看镜像里有什么文件? 方法一:docker run --rm -it nginx ls / 方法二:docker export <container> | tar -tvf - 方法三:dive工具可以交互式浏览每层内容。

🏆 第03课成就

下一课:深入学习容器生命周期管理——从创建到销毁的完整旅程!