Docker镜像基础

一、镜像获取

1.1 从仓库拉取

1.1.1 docker pull命令

基本语法

docker pull [OPTIONS] NAME[:TAG|@DIGEST]

OPTIONS:
  -a, --all-tags      拉取所有标签的镜像
      --platform      指定平台(如linux/amd64)
  -q, --quiet         安静模式,不显示详细信息

使用示例

# 拉取最新版本(latest标签)
docker pull nginx

# 拉取指定版本
docker pull nginx:1.21

# 拉取指定摘要(精确版本)
docker pull nginx@sha256:7a86f8a2e...

# 拉取所有标签
docker pull -a nginx

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

# 安静模式
docker pull -q nginx:1.21

1.1.2 拉取过程详解

分层下载

docker pull nginx:latest

输出:
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete     # 第1层
aeb1c7d5e8d2: Pull complete     # 第2层
ad7f5c8ed6b1: Pull complete     # 第3层
4d67e1fc5d6a: Pull complete     # 第4层
8e4d8e5c4b8a: Pull complete     # 第5层
Digest: sha256:7a86f8a2e...     # 镜像摘要
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

东巴文理解

镜像拉取 = 分层下载拼图
就像:下载拼图块,然后拼成完整图片

下载过程:
├─ 检查本地是否已有该层
├─ 如果有,跳过下载(共享层)
├─ 如果没有,下载该层
└─ 所有层下载完成后,组合成完整镜像

优势:
├─ 节省带宽(共享层不重复下载)
├─ 节省存储(共享层只存一份)
└─ 加速拉取(已有层直接使用)

1.1.3 镜像摘要

什么是摘要

摘要(Digest):
├─ 镜像内容的SHA256哈希值
├─ 唯一标识镜像内容
├─ 内容不变,摘要不变
└─ 确保镜像完整性

格式:
算法:哈希值
示例:sha256:7a86f8a2e1d4c5b6a7f8e9d0c1b2a3f4e5d6c7b8a9f0e1d2c3b4a5f6e7d8c9b0

使用摘要拉取

# 查看镜像摘要
docker images --digests

# 输出示例
REPOSITORY   TAG       DIGEST                                                                    IMAGE ID       SIZE
nginx        latest    sha256:7a86f8a2e1d4c5b6a7f8e9d0c1b2a3f4e5d6c7b8a9f0e1d2c3b4a5f6e7d8c9b0   7a86f8a2e1d4   142MB

# 使用摘要拉取(精确版本)
docker pull nginx@sha256:7a86f8a2e1d4c5b6a7f8e9d0c1b2a3f4e5d6c7b8a9f0e1d2c3b4a5f6e7d8c9b0

1.2 从Dockerfile构建

1.2.1 docker build命令

基本语法

docker build [OPTIONS] PATH | URL | -

OPTIONS:
  -t, --tag        镜像名称和标签
  -f, --file       指定Dockerfile路径
      --build-arg  构建参数
      --no-cache   不使用缓存
      --platform   指定平台
  -q, --quiet      安静模式

使用示例

# 基本构建
docker build -t myapp:v1.0 .

# 指定Dockerfile
docker build -t myapp:v1.0 -f Dockerfile.prod .

# 构建参数
docker build -t myapp:v1.0 --build-arg VERSION=1.0 .

# 不使用缓存
docker build -t myapp:v1.0 --no-cache .

# 从URL构建
docker build -t myapp https://github.com/user/repo.git

# 从标准输入构建
cat Dockerfile | docker build -t myapp -

1.2.2 构建过程详解

示例Dockerfile

FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

构建输出

docker build -t myapp:v1.0 .

输出:
Sending build context to Docker daemon  45.2MB
Step 1/7 : FROM node:18-alpine
18-alpine: Pulling from library/node
a2abf6c4d29d: Pull complete
...
Status: Downloaded newer image for node:18-alpine
 ---> a1b2c3d4e5f6

Step 2/7 : WORKDIR /app
 ---> Running in b2c3d4e5f6a7
Removing intermediate container b2c3d4e5f6a7
 ---> c3d4e5f6a7b8

Step 3/7 : COPY package*.json ./
 ---> d4e5f6a7b8c9

Step 4/7 : RUN npm install
 ---> Running in e5f6a7b8c9d0
npm notice created a lockfile as package-lock.json
...
Removing intermediate container e5f6a7b8c9d0
 ---> f6a7b8c9d0e1

Step 5/7 : COPY . .
 ---> a7b8c9d0e1f2

Step 6/7 : EXPOSE 3000
 ---> Running in b8c9d0e1f2a3
Removing intermediate container b8c9d0e1f2a3
 ---> c9d0e1f2a3b4

Step 7/7 : CMD ["npm", "start"]
 ---> Running in d0e1f2a3b4c5
Removing intermediate container d0e1f2a3b4c5
 ---> e1f2a3b4c5d6
Successfully built e1f2a3b4c5d6
Successfully tagged myapp:v1.0

构建缓存

Docker会缓存每一步的结果:
├─ 如果指令和上下文没变,使用缓存
├─ 如果某一步变化,后续步骤重新构建
└─ --no-cache禁用所有缓存

缓存优势:
├─ 加速构建
├─ 节省资源
└─ 提高效率

注意事项:
├─ COPY/RUN指令容易失效
├─ 将变化少的指令放前面
└─ 将变化多的指令放后面

1.3 从容器创建

1.3.1 docker commit命令

基本语法

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

OPTIONS:
  -a, --author     作者信息
  -c, --change     应用Dockerfile指令
  -m, --message    提交信息

使用示例

# 运行容器
docker run -it --name mycontainer ubuntu bash

# 在容器中修改
apt-get update
apt-get install -y nginx

# 提交为新镜像
docker commit -a "author@example.com" -m "Install nginx" mycontainer myubuntu:nginx

# 查看新镜像
docker images myubuntu

注意

不推荐使用commit构建镜像:
❌ 不可重复(手动操作)
❌ 不透明(不知道做了什么)
❌ 难以维护(无法版本控制)
❌ 体积大(包含所有修改)

推荐使用Dockerfile:
✅ 可重复构建
✅ 透明可读
✅ 版本控制
✅ 优化体积

二、镜像查看

2.1 列出镜像

2.1.1 docker images命令

基本语法

docker images [OPTIONS] [REPOSITORY[:TAG]]

OPTIONS:
  -a, --all         显示所有镜像(包括中间层镜像)
      --digests     显示摘要
  -f, --filter      过滤条件
      --format      格式化输出
  -q, --quiet       只显示ID

使用示例

# 列出所有镜像
docker images

# 输出示例
REPOSITORY          TAG       IMAGE ID       CREATED        SIZE
nginx               latest    7a86f8a2e1d4   2 weeks ago    142MB
nginx               1.21      a1b2c3d4e5f6   3 weeks ago    138MB
mysql               8.0       b2c3d4e5f6a7   4 weeks ago    556MB
myapp               v1.0      c3d4e5f6a7b8   1 day ago      200MB

# 显示摘要
docker images --digests

# 只显示ID
docker images -q

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

# 过滤镜像
docker images --filter "dangling=true"  # 悬空镜像
docker images --filter "reference=nginx"  # 名称匹配

# 格式化输出
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
docker images --format "{{.ID}}: {{.Repository}}:{{.Tag}}"

2.1.2 镜像过滤

过滤条件

# 悬空镜像(无标签)
docker images -f "dangling=true"

# 特定仓库
docker images nginx

# 特定标签
docker images nginx:1.21

# 引用模式匹配
docker images --filter=reference="nginx:*"

# 之前创建的镜像
docker images --filter "before=nginx:latest"

# 之后创建的镜像
docker images --filter "since=mysql:8.0"

# 标签为latest
docker images --filter "dangling=false"

2.2 查看镜像详情

2.2.1 docker inspect命令

基本语法

docker inspect [OPTIONS] IMAGE [IMAGE...]

OPTIONS:
  -f, --format     格式化输出
  -s, --size       显示总文件大小
      --type       返回指定类型

使用示例

# 查看镜像详细信息
docker inspect nginx:latest

# 输出JSON格式
[
    {
        "Id": "sha256:7a86f8a2e1d4...",
        "RepoTags": [
            "nginx:latest"
        ],
        "RepoDigests": [
            "nginx@sha256:7a86f8a2e..."
        ],
        "Created": "2024-01-15T10:30:00.000000000Z",
        "Size": 142000000,
        "VirtualSize": 142000000,
        "Architecture": "amd64",
        "Os": "linux",
        "Layers": [
            "sha256:a2abf6c4d29d...",
            "sha256:aeb1c7d5e8d2...",
            ...
        ],
        ...
    }
]

# 格式化输出
docker inspect -f '{{.Id}}' nginx:latest
docker inspect -f '{{.Created}}' nginx:latest
docker inspect -f '{{.Size}}' nginx:latest
docker inspect -f '{{.Architecture}}' nginx:latest

# 查看镜像层
docker inspect -f '{{json .RootFS.Layers}}' nginx:latest | jq

2.2.2 关键信息解读

镜像元数据

Id:镜像唯一标识
├─ 完整ID:sha256:7a86f8a2e1d4...
└─ 用于唯一标识镜像

RepoTags:镜像标签
├─ 格式:仓库名:标签
└─ 示例:nginx:latest

RepoDigests:镜像摘要
├─ 格式:仓库名@摘要
└─ 用于精确拉取镜像

Created:创建时间
├─ ISO 8601格式
└─ 示例:2024-01-15T10:30:00Z

Size:镜像大小
├─ 单位:字节
└─ 所有层的总大小

Architecture:架构
├─ amd64、arm64等
└─ 必须与主机架构匹配

Os:操作系统
├─ linux、windows等
└─ 必须与主机OS匹配

Layers:镜像层
├─ SHA256列表
└─ 从底层到顶层

2.3 查看镜像历史

2.3.1 docker history命令

基本语法

docker history [OPTIONS] IMAGE

OPTIONS:
  -H, --human      人类可读格式(默认true)
      --no-trunc   不截断输出
  -q, --quiet      只显示ID

使用示例

# 查看镜像历史
docker history nginx:latest

# 输出示例
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
7a86f8a2e1d4   2 weeks ago    /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B        
<missing>      2 weeks ago    /bin/sh -c #(nop)  EXPOSE 80                    0B        
<missing>      2 weeks ago    /bin/sh -c #(nop) COPY file:xxx in /           4.62kB    
<missing>      2 weeks ago    /bin/sh -c apt-get update && apt-get install…   61.1MB    
<missing>      2 weeks ago    /bin/sh -c #(nop)  CMD ["bash"]                 0B        
<missing>      2 weeks ago    /bin/sh -c #(nop) ADD file:xxx in /            74.8MB    

# 不截断输出
docker history --no-trunc nginx:latest

# 只显示ID
docker history -q nginx:latest

理解输出

IMAGE:镜像ID或<missing>
├─ <missing>表示中间层,已被删除
└─ 有ID表示该层还存在

CREATED:创建时间
├─ 相对时间(如2 weeks ago)
└─ 或绝对时间

CREATED BY:创建命令
├─ Dockerfile指令
└─ 或其他操作

SIZE:层大小
├─ 该层增加的大小
└─ 0B表示只修改元数据

COMMENT:注释
├─ 通常为空
└─ 来自Dockerfile的COMMENT

三、镜像管理

3.1 镜像标签

3.1.1 docker tag命令

基本语法

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

使用示例

# 给镜像添加标签
docker tag myapp:v1.0 myapp:latest

# 添加多个标签
docker tag myapp:v1.0 myapp:stable
docker tag myapp:v1.0 myapp:production

# 推送到私有仓库
docker tag myapp:v1.0 registry.example.com/myapp:v1.0

# 推送到Docker Hub
docker tag myapp:v1.0 username/myapp:v1.0

# 查看标签
docker images myapp

标签理解

标签 = 镜像的别名
就像:一个人可以有多个称呼

示例:
镜像ID:a1b2c3d4e5f6
标签:
├─ myapp:v1.0
├─ myapp:latest
├─ myapp:stable
└─ username/myapp:v1.0

所有标签指向同一个镜像ID
删除一个标签不影响其他标签
删除所有标签后镜像才会被删除

3.2 删除镜像

3.2.1 docker rmi命令

基本语法

docker rmi [OPTIONS] IMAGE [IMAGE...]

OPTIONS:
  -f, --force    强制删除
      --no-prune   不删除未标记的父镜像

使用示例

# 删除镜像(通过名称)
docker rmi myapp:v1.0

# 删除镜像(通过ID)
docker rmi a1b2c3d4e5f6

# 强制删除(即使有容器使用)
docker rmi -f myapp:v1.0

# 删除多个镜像
docker rmi nginx:latest nginx:1.21

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

# 删除悬空镜像
docker image prune

3.2.2 删除注意事项

删除规则

可以删除:
✅ 没有容器的镜像
✅ 有多个标签的镜像(只删除标签)
✅ 强制删除运行中容器的镜像(不推荐)

不能删除:
❌ 正在被容器使用的镜像
❌ 被其他镜像依赖的中间层镜像

删除顺序:
1. 先删除依赖的容器
2. 再删除镜像

错误处理

# 错误:镜像被容器使用
Error: No such image: myapp:v1.0
Error response from daemon: conflict: unable to remove repository reference "myapp:v1.0" (must force) - container a1b2c3d4e5f6 is using its referenced image b2c3d4e5f6a7

# 解决方法1:先删除容器
docker rm a1b2c3d4e5f6
docker rmi myapp:v1.0

# 解决方法2:强制删除(不推荐)
docker rmi -f myapp:v1.0

3.3 清理镜像

3.3.1 docker image prune命令

基本语法

docker image prune [OPTIONS]

OPTIONS:
  -a, --all       删除所有未使用的镜像
      --filter    过滤条件
  -f, --force     不提示确认

使用示例

# 删除悬空镜像(无标签)
docker image prune

# 输出
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Deleted Images:
untagged: myapp@sha256:7a86f8a2e...
deleted: sha256:a1b2c3d4e5f6...
Total reclaimed space: 50MB

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

# 强制删除,不提示
docker image prune -f

# 过滤条件(超过24小时未使用)
docker image prune -a --filter "until=24h"

3.3.2 悬空镜像

什么是悬空镜像

悬空镜像(Dangling Image):
├─ 没有任何标签的镜像
├─ 通常是构建过程中产生的中间层
├─ 或新版本覆盖旧版本后留下的
└─ 通常可以安全删除

示例:
REPOSITORY   TAG       IMAGE ID       SIZE
<none>       <none>    a1b2c3d4e5f6   100MB  ← 悬空镜像
nginx        latest    b2c3d4e5f6a7   142MB

产生原因:
├─ docker build产生新镜像,旧镜像失去标签
├─ docker pull新版本,旧版本失去标签
└─ docker tag覆盖,旧标签失去引用

查看悬空镜像

# 方法1:使用filter
docker images -f "dangling=true"

# 方法2:使用grep
docker images | grep "<none>"

# 方法3:使用prune预览
docker image prune --dry-run

四、镜像导入导出

4.1 导出镜像

4.1.1 docker save命令

基本语法

docker save [OPTIONS] IMAGE [IMAGE...]

OPTIONS:
  -o, --output   输出到文件

使用示例

# 导出单个镜像到文件
docker save -o nginx.tar nginx:latest

# 导出多个镜像到一个文件
docker save -o images.tar nginx:latest mysql:8.0 redis:7

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

# 导出到标准输出
docker save nginx:latest > nginx.tar

# 导出所有镜像
docker save -o all-images.tar $(docker images -q)

使用场景

适用场景:
✅ 离线环境部署
✅ 镜像备份
✅ 跨网络传输
✅ 归档保存

注意事项:
⚠️ 文件较大(包含所有层)
⚠️ 导出的是镜像,不是容器
⚠️ 包含镜像元数据

4.2 导入镜像

4.2.1 docker load命令

基本语法

docker load [OPTIONS]

OPTIONS:
  -i, --input    从文件导入
  -q, --quiet    安静模式

使用示例

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

# 从标准输入导入
docker load < nginx.tar

# 从压缩文件导入
gunzip -c nginx.tar.gz | docker load

# 导入并查看
docker load -i images.tar
docker images

导入过程

docker load -i nginx.tar

输出:
Loaded image: nginx:latest

# 如果有多个镜像
Loaded image: nginx:latest
Loaded image: mysql:8.0
Loaded image: redis:7

4.3 导出容器

4.3.1 docker export命令

基本语法

docker export [OPTIONS] CONTAINER

OPTIONS:
  -o, --output   输出到文件

使用示例

# 导出容器文件系统
docker export -o container.tar mycontainer

# 导出到标准输出
docker export mycontainer > container.tar

# 导出并压缩
docker export mycontainer | gzip > container.tar.gz

save vs export

docker save(导出镜像):
├─ 导出镜像
├─ 包含所有层和元数据
├─ 可导入为镜像
├─ 保留镜像历史
└─ 文件较大

docker export(导出容器):
├─ 导出容器文件系统
├─ 只有一层(扁平化)
├─ 可导入为镜像
├─ 不保留镜像历史
└─ 文件较小

推荐:
✅ 使用save导出镜像
⚠️ export用于容器快照

4.4 导入容器快照

4.4.1 docker import命令

基本语法

docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

OPTIONS:
  -c, --change    应用Dockerfile指令
  -m, --message   提交信息

使用示例

# 从文件导入
docker import container.tar myimage:v1.0

# 从URL导入
docker import http://example.com/container.tar myimage:v1.0

# 从标准输入导入
cat container.tar | docker import - myimage:v1.0

# 导入并应用变更
docker import -c "ENV DEBUG=true" container.tar myimage:v1.0

# 导入并添加注释
docker import -m "Imported from container" container.tar myimage:v1.0

load vs import

docker load(导入镜像):
├─ 从save导出的文件导入
├─ 保留镜像历史和层
├─ 保留元数据
└─ 推荐使用

docker import(导入快照):
├─ 从export导出的文件导入
├─ 只有一层(扁平化)
├─ 不保留历史
└─ 用于容器快照

推荐:
✅ 使用load导入save的文件
⚠️ import用于export的文件

五、镜像搜索

5.1 命令行搜索

5.1.1 docker search命令

基本语法

docker search [OPTIONS] TERM

OPTIONS:
  -f, --filter    过滤条件
      --limit     限制结果数量
      --no-trunc  不截断描述

使用示例

# 搜索镜像
docker search nginx

# 输出示例
NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                             Official build of Nginx.                         18000     [OK]       
jwilder/nginx-proxy               Automated Nginx reverse proxy for docker c...   2100                 [OK]
richarvey/nginx-php-fpm           Container running Nginx + PHP-FPM capable...    800                  [OK]
bitnami/nginx                     Bitnami nginx Docker Image                      100                  [OK]
linuxserver/nginx                 An Nginx container, brought to you by Linu...   60                   
...

# 过滤官方镜像
docker search --filter is-official=true nginx

# 过滤星数
docker search --filter stars=1000 nginx

# 限制结果数量
docker search --limit 5 nginx

# 不截断描述
docker search --no-trunc nginx

5.1.2 搜索结果解读

字段说明

NAME:镜像名称
├─ 官方镜像:nginx
├─ 用户镜像:username/nginx
└─ 组织镜像:organization/nginx

DESCRIPTION:镜像描述
├─ 简短说明
└─ 可能被截断

STARS:星标数
├─ 用户收藏数
└─ 反映受欢迎程度

OFFICIAL:是否官方
├─ [OK]表示官方镜像
└─ 空白表示非官方

AUTOMATED:是否自动构建
├─ [OK]表示自动构建
└─ 空白表示手动构建

5.2 Docker Hub网页搜索

5.2.1 搜索技巧

高级搜索

1. 访问 https://hub.docker.com
2. 输入搜索关键词
3. 使用过滤器:
   ├─ Official Images(官方镜像)
   ├─ Verified Publisher(认证发布者)
   ├─ Open Source(开源项目)
   └─ Architecture(架构)

排序:
├─ Most stars(最多星标)
├─ Most pulls(最多下载)
└─ Newest(最新更新)

5.2.2 镜像详情

查看镜像信息

镜像页面包含:
├─ 描述和用途
├─ 支持的标签
├─ Docker命令示例
├─ 环境变量说明
├─ 数据卷说明
├─ 网络端口说明
├─ 使用示例
└─ 版本历史

重要信息:
✅ 支持的架构
✅ 环境变量
✅ 数据持久化
✅ 安全更新

六、本章小结

6.1 核心命令总结

6.1.1 镜像操作命令

获取镜像:
├─ docker pull:从仓库拉取
├─ docker build:从Dockerfile构建
└─ docker commit:从容器创建(不推荐)

查看镜像:
├─ docker images:列出镜像
├─ docker inspect:查看详情
└─ docker history:查看历史

管理镜像:
├─ docker tag:添加标签
├─ docker rmi:删除镜像
└─ docker image prune:清理镜像

导入导出:
├─ docker save:导出镜像
├─ docker load:导入镜像
├─ docker export:导出容器
└─ docker import:导入快照

搜索镜像:
└─ docker search:搜索镜像

6.1.2 常用命令速查

# 拉取镜像
docker pull nginx:latest

# 查看镜像
docker images
docker images -a
docker images -q

# 查看详情
docker inspect nginx:latest

# 查看历史
docker history nginx:latest

# 添加标签
docker tag nginx:latest mynginx:v1.0

# 删除镜像
docker rmi nginx:latest
docker rmi -f nginx:latest

# 清理镜像
docker image prune
docker image prune -a

# 导出镜像
docker save -o nginx.tar nginx:latest

# 导入镜像
docker load -i nginx.tar

# 搜索镜像
docker search nginx
docker search --filter is-official=true nginx

6.2 最佳实践

6.2.1 镜像管理建议

镜像命名:
✅ 使用明确的版本标签
✅ 使用语义化版本
✅ 标记环境(dev/test/prod)
❌ 避免在生产使用latest

镜像清理:
✅ 定期清理悬空镜像
✅ 删除无用镜像
✅ 使用prune命令
⚠️ 谨慎使用-a选项

镜像安全:
✅ 使用官方镜像
✅ 定期更新镜像
✅ 扫描镜像漏洞
✅ 使用可信仓库

6.2.2 性能优化

加速拉取:
✅ 使用镜像加速器
✅ 使用国内镜像源
✅ 使用分层缓存

节省存储:
✅ 定期清理无用镜像
✅ 使用alpine基础镜像
✅ 多阶段构建减小体积

加速构建:
✅ 利用构建缓存
✅ 合理安排指令顺序
✅ 使用.dockerignore

6.3 下一章预告

下一章:Dockerfile基础

将学习:

  • 📄 Dockerfile基本结构
  • 📝 常用指令详解
  • 🔨 构建最佳实践
  • 🎯 实战案例演练

📝 练习题

基础题

  1. 命令使用:拉取nginx:1.21镜像,查看镜像列表,然后删除该镜像。

  2. 镜像信息:使用docker inspect命令查看nginx镜像的架构、操作系统和大小。

  3. 镜像标签:给nginx:latest镜像添加一个新标签mynginx:stable。

进阶题

  1. 镜像导出导入:导出nginx镜像到文件,删除本地镜像,然后从文件导入。

  2. 镜像清理:查看并清理系统中的悬空镜像。

  3. 镜像搜索:搜索星标数超过1000的官方nginx镜像。

实践题

  1. 完整流程:编写一个简单的Dockerfile,构建镜像,添加标签,导出到文件,然后在另一台机器上导入并运行。

  2. 镜像优化:对比不同基础镜像(ubuntu、alpine、debian)的大小,选择最优基础镜像。