长安的Docker教程长安的Docker教程
首页
快速开始
编程指南
首页
快速开始
编程指南
  • 🎯 Docker入门篇

    • 快速开始
    • Docker是什么?
    • 为什么要用Docker?
    • 安装Docker
    • 第一个容器
  • 📦 Docker基础篇

    • Docker镜像详解
    • 容器操作详解
    • 编写Dockerfile
    • 数据卷(Volumes)
    • Docker网络
  • ⚡ Docker进阶篇

    • Docker Compose
    • 多阶段构建
    • Docker性能优化
    • Docker最佳实践
  • 🚀 实战项目

    • 实战:部署Node.js应用
    • 实战:搭建数据库环境
    • 实战:微服务架构
  • 💡 常见问题

    • 常见问题排查
    • 实用技巧

Docker镜像详解

嘿!长安来啦!上一章你已经会运行容器了,但可能还不太明白镜像到底是啥。今天咱们就深入聊聊Docker镜像!

🤔 镜像到底是什么?

生活化的解释

还记得长安之前的比喻吗?

镜像 = 菜谱
容器 = 做好的菜

镜像 = 游戏安装包
容器 = 运行中的游戏

镜像 = 类(Class)
容器 = 对象(Object)

镜像就是一个模板,包含了:

  • 程序代码
  • 运行环境
  • 依赖库
  • 配置文件
  • 一切运行所需的东西

技术层面的解释

Docker镜像是一个分层的只读文件系统。

什么叫分层?就像千层饼:

┌─────────────────────┐
│  你的应用代码        │  ← 第3层
├─────────────────────┤
│  Node.js运行环境     │  ← 第2层
├─────────────────────┤
│  Ubuntu基础系统      │  ← 第1层
└─────────────────────┘

每一层都是只读的,多个容器可以共享相同的层,超级节省空间!

📦 查看本地镜像

列出所有镜像

docker images

或者:

docker image ls

输出:

REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    605c77e624dd   2 weeks ago    141MB
python       3.11      fc7a60e86bae   3 weeks ago    1.01GB
hello-world  latest    feb5d9fea6a5   2 months ago   13.3kB

让长安解释一下每一列:

  • REPOSITORY:镜像名称(仓库名)
  • TAG:标签(版本号)
  • IMAGE ID:镜像的唯一ID
  • CREATED:创建时间
  • SIZE:大小

镜像的命名规则

完整的镜像名格式:

[registry/][namespace/]repository[:tag]

例子:

nginx:latest
# registry: 默认docker.io (Docker Hub)
# namespace: 默认library(官方镜像)
# repository: nginx
# tag: latest

docker.io/library/nginx:latest
# 这是完整名称

myregistry.com/mycompany/myapp:v1.0
# 自定义仓库

最常用的简写:

nginx              = nginx:latest
python             = python:latest
redis:6.2          = redis:6.2

🔍 搜索镜像

在Docker Hub上搜索

docker search nginx

输出:

NAME                      DESCRIPTION                                     STARS     OFFICIAL
nginx                     Official build of Nginx.                        19000     [OK]
nginx/nginx-ingress       NGINX Ingress Controller for Kubernetes         500
bitnami/nginx             Bitnami nginx Docker Image                      400

看STARS数和OFFICIAL标志,选择靠谱的镜像!

💡 长安建议:优先选择官方镜像(OFFICIAL那一列有[OK]的)

在浏览器上搜索

访问:https://hub.docker.com/

可以看到更详细的信息:

  • 镜像说明
  • 使用文档
  • 支持的标签(版本)
  • Dockerfile

⬇️ 拉取镜像

基本用法

docker pull <镜像名>[:标签]

例子:

# 拉取最新版nginx
docker pull nginx

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

# 拉取Python 3.11
docker pull python:3.11

拉取过程

$ docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete    ← 第1层
a9edb18cadd1: Pull complete    ← 第2层
589b7251471a: Pull complete    ← 第3层
...
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest

看到没?分层下载! 每一层下载完会缓存,下次不用重复下载。

🔎 查看镜像详情

查看镜像的详细信息

docker image inspect nginx

会输出一大堆JSON,包含:

  • 创建时间
  • 架构
  • 操作系统
  • 环境变量
  • 暴露的端口
  • 启动命令
  • 等等...

查看镜像的历史(分层信息)

docker image history nginx

输出:

IMAGE          CREATED       CREATED BY                                      SIZE
605c77e624dd   2 weeks ago   /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  STOPSIGNAL SIGQUIT           0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  EXPOSE 80                    0B
...

每一行就是一层! 可以看到每一层是怎么构建的。

🎯 镜像的标签(Tag)

什么是标签?

标签就是版本号,一个镜像可以有多个标签。

nginx:latest      # 最新版
nginx:1.25        # 1.25版本
nginx:1.25.3      # 1.25.3版本
nginx:alpine      # 基于Alpine Linux的版本(更小)

查看所有可用标签

去Docker Hub查看:https://hub.docker.com/_/nginx/tags

latest标签的真相

重要! latest并不一定是"最新版"!

latest只是一个默认标签,镜像维护者想指向哪个版本就指向哪个版本。

💡 长安建议:生产环境不要用latest,要用明确的版本号!

# ❌ 不推荐(生产环境)
docker pull nginx:latest

# ✅ 推荐
docker pull nginx:1.25.3

🏷️ 给镜像打标签

创建新标签

docker tag nginx:latest my-nginx:v1.0

查看:

docker images | grep nginx

输出:

nginx      latest    605c77e624dd   2 weeks ago   141MB
my-nginx   v1.0      605c77e624dd   2 weeks ago   141MB

看IMAGE ID,是同一个! 打标签不会复制镜像,只是创建一个别名。

💾 导出和导入镜像

导出镜像到文件

docker save nginx:latest -o nginx.tar

或者:

docker save nginx:latest > nginx.tar

查看文件:

ls -lh nginx.tar
# 输出:141M nginx.tar

导入镜像

docker load -i nginx.tar

或者:

docker load < nginx.tar

什么时候用?

  • 内网部署(没有外网)
  • 分享镜像给同事
  • 备份镜像

🗑️ 删除镜像

删除单个镜像

docker rmi nginx:latest

或者用IMAGE ID:

docker rmi 605c77e624dd

删除多个镜像

docker rmi nginx:latest python:3.11 redis:6.2

强制删除

如果有容器在使用这个镜像,删除会失败:

Error response from daemon: conflict: unable to remove repository reference "nginx:latest" (must force)

强制删除:

docker rmi -f nginx:latest

⚠️ 警告:强制删除会导致使用该镜像的容器无法启动!

删除所有未使用的镜像

docker image prune

删除所有镜像(包括正在使用的):

docker image prune -a

🎨 镜像的实战技巧

技巧1:选择合适的基础镜像

# 完整版(大)
python:3.11          # 1.01GB

# Slim版(中)
python:3.11-slim     # 125MB

# Alpine版(小)
python:3.11-alpine   # 50MB

怎么选?

  • 学习/开发:用完整版,工具全
  • 生产环境:用slim或alpine,更安全更小

技巧2:使用镜像加速器

国内拉取镜像慢?配置镜像加速器(安装章节有讲)。

验证是否生效:

docker info | grep -i registry

应该能看到你配置的镜像地址。

技巧3:定期清理镜像

# 查看镜像占用空间
docker system df

# 清理未使用的镜像
docker image prune

# 清理所有未使用的东西(镜像、容器、网络、缓存)
docker system prune

技巧4:使用镜像摘要(Digest)

# 使用标签(可能变化)
docker pull nginx:latest

# 使用摘要(永不变化)
docker pull nginx@sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31

摘要是镜像内容的哈希值,内容不变,摘要就不变。

📊 常用镜像推荐

长安给你推荐一些常用的官方镜像:

编程语言

python:3.11-slim      # Python
node:18-alpine        # Node.js
openjdk:17-slim       # Java
golang:1.21-alpine    # Go
ruby:3.2-slim         # Ruby

数据库

mysql:8.0             # MySQL
postgres:15           # PostgreSQL
mongo:6.0             # MongoDB
redis:7-alpine        # Redis

Web服务器

nginx:alpine          # Nginx
httpd:alpine          # Apache
caddy:alpine          # Caddy

其他

alpine:latest         # Alpine Linux(最小的Linux发行版)
ubuntu:22.04          # Ubuntu
busybox              # BusyBox(超小工具集)

💡 小结

今天长安教你搞懂了Docker镜像:

核心概念

  1. 镜像:只读的文件系统模板
  2. 分层结构:像千层饼,节省空间
  3. 标签:版本号(别乱用latest)
  4. 仓库:Docker Hub(镜像超市)

常用命令

docker images          # 查看镜像
docker search          # 搜索镜像
docker pull            # 拉取镜像
docker rmi             # 删除镜像
docker tag             # 打标签
docker save/load       # 导出/导入镜像
docker image inspect   # 查看详情
docker image prune     # 清理镜像

🤔 小练习

试试这些命令,加深理解:

# 1. 拉取一个Python镜像
docker pull python:3.11-slim

# 2. 查看镜像信息
docker images
docker image inspect python:3.11-slim

# 3. 给镜像打个标签
docker tag python:3.11-slim my-python:v1

# 4. 运行这个镜像
docker run -it my-python:v1 python

# 5. 导出镜像
docker save my-python:v1 -o my-python.tar

# 6. 删除镜像
docker rmi my-python:v1

# 7. 导入镜像
docker load -i my-python.tar

# 8. 清理
docker rmi my-python:v1
rm my-python.tar

🚀 下一步

现在你对镜像有深入理解了,下一章长安会教你更多 容器操作 技巧!


💬 长安的经验谈:

刚开始学Docker的时候,我总是分不清镜像和容器。后来我想明白了:

镜像是静态的,容器是动态的。

就像游戏安装包(镜像)和运行中的游戏(容器)。

理解了这个,Docker就容易多了!

对了,镜像管理很重要,定期清理一下,不然硬盘会被撑爆😂

下一章见!💪

在 GitHub 上编辑此页
Next
容器操作详解