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]的)
在浏览器上搜索
可以看到更详细的信息:
- 镜像说明
- 使用文档
- 支持的标签(版本)
- 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镜像:
核心概念
- 镜像:只读的文件系统模板
- 分层结构:像千层饼,节省空间
- 标签:版本号(别乱用latest)
- 仓库: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就容易多了!
对了,镜像管理很重要,定期清理一下,不然硬盘会被撑爆😂
下一章见!💪
