Docker03-镜像与容器管理
Docker 镜像与容器管理:核心对象实操
目录
- 准备工作
- 镜像管理:拉取、查看、标记与推送
- 镜像分层与存储原理
- 容器生命周期:从创建到删除
- 容器常用运维命令
- 资源限制:CPU 与内存
- 进入容器:exec 与 attach
- 镜像与容器的清理
- 常见问题排查
- 总结
- 参考资料
0. 准备工作
开始前请确认 Docker 已安装并启动(第 2 篇已完成):
docker version # 查看 Client 与 Server 版本
docker info # 查看引擎整体信息
若 Server 部分为空,先启动服务:
sudo systemctl enable --now docker
本篇所有命令都可以在普通用户下运行(前提是你已把用户加入 docker 组,见第 2 篇 3.4 节),否则每条前面加 sudo。
一、镜像管理:拉取、查看、标记与推送
1.1 拉取镜像:docker pull
从仓库拉取镜像到本地:
docker pull nginx:1.25
docker pull ubuntu:24.04
格式是 docker pull 仓库名:标签。不写标签默认 latest。
在国内,直接拉取 Docker Hub 可能慢或失败。解决办法:先按第 2 篇第 4 章配置好镜像加速器,再执行 pull;或者显式指定镜像源前缀(如 docker pull docker.m.daocloud.io/library/nginx:1.25),不同加速站前缀不同。
1.2 查看本地镜像:docker images
docker images
输出列:
- REPOSITORY:镜像所属仓库名;
- TAG:标签(版本);
- IMAGE ID:镜像唯一 ID(前 12 位);
- CREATED:创建时间;
- SIZE:镜像体积。
查看某个镜像更详细的信息:
docker inspect nginx:1.25
会输出一长串 JSON,包含镜像的配置、层级、入口命令等。
1.3 标记镜像:docker tag
给镜像打标签(相当于复制一个指向同一镜像的别名):
docker tag nginx:1.25 myrepo/nginx:v1
docker tag nginx:1.25 registry.example.com/nginx:1.25
常用于:准备推送到私有仓库前,把镜像标记为带仓库地址的完整名字。tag 不复制镜像内容,只是新增一个名称引用。
1.4 推送镜像:docker push
把本地镜像推送到仓库(需要先登录):
docker login # 输入用户名密码
docker push myrepo/nginx:v1
推送到公共 Docker Hub 或自己的私有仓库都可以。登录信息存储在 ~/.docker/config.json。
1.5 查看镜像历史:docker history
docker history nginx:1.25
展示镜像的每一层是哪个指令生成的、体积多大——这对理解镜像分层、排查体积问题很有用。
二、镜像分层与存储原理
2.1 为什么镜像要分层
第 1 篇讲过,镜像由多个只读层叠加而成。分层带来两大好处:
- 共享存储:多个镜像共用相同的底层只存一份,节省磁盘;
- 增量传输:拉取时只需下载本地没有的层,已存在的层直接复用,更新镜像很高效。
2.2 用 history 观察分层
用 docker history 看 nginx 镜像的分层:
docker history --no-trunc nginx:1.25
每一行对应镜像的一层,最下面是基础层(debian/ubuntu 等),往上是各条 Dockerfile 指令产生的层。
2.3 存储驱动:overlay2
Docker 用**存储驱动(storage driver)**实现分层与联合挂载。现代 Linux 默认使用 overlay2:
docker info | grep -i storage
# Storage Driver: overlay2
overlay2 把只读镜像层和一个可写容器层联合成一个视图,实现了「只读底层 + 可写顶层」的容器文件系统。RHEL/Rocky 与 Ubuntu 现代版本都默认 overlay2。
2.4 一个容易混淆的概念:镜像 ID 与层 ID
- 镜像 ID(IMAGE ID):整个镜像的标识;
- 层(layer):镜像由若干层组成,层有自己的 ID。
两个不同的镜像如果从同一个基础镜像构建,会共享基础层,这从 docker images 的 SIZE(可能是共用后的大小)和磁盘占用上都能体现。
三、容器生命周期:从创建到删除
一个容器会经历 创建、启动、运行、停止、删除 等阶段。下面逐个命令讲清。
3.1 运行容器:docker run
docker run = 创建 + 启动 + 运行。最常见的几个用法:
# 前台运行,直接看到输出(Ctrl+C 停止)
docker run nginx:1.25
# 后台运行(detach),返回容器 ID
docker run -d --name web nginx:1.25
# 交互式运行,进入容器 shell(常用于调试)
docker run -it --name shell ubuntu:24.04 bash
# 指定端口映射 + 数据卷
docker run -d --name web -p 8080:80 -v mydata:/data nginx:1.25
常用参数:
- -d:后台运行;
- --name:命名;
- -it:交互式终端(-i 交互、-t 分配伪终端);
- -p:端口映射;
- -v:挂载卷;
- --rm:容器停止后自动删除(适合一次性任务)。
3.2 查看容器:docker ps
docker ps # 只看运行中的容器
docker ps -a # 看所有容器(含已停止)
输出列:CONTAINER ID、IMAGE、COMMAND、CREATED、STATUS、PORTS、NAMES。
3.3 停止与启动
docker stop web # 优雅停止(发送 SIGTERM,等待超时后 SIGKILL)
docker start web # 启动已存在的容器
docker restart web # 重启
docker kill web # 强制停止(直接 SIGKILL)
区别:stop 先发 SIGTERM 让进程优雅退出(默认 10 秒),超时才强杀;kill 直接发 SIGKILL 立即终止。生产上尽量用 stop。
3.4 删除容器
docker rm web # 删除已停止的容器
docker rm -f web # 强制删除运行中的容器
docker rm $(docker ps -aq) # 删除所有容器(谨慎)
删除容器会一并删除容器的可写层数据(数据卷 volume 除外,卷是独立存储)。
3.5 生命周期总结
docker run(创建+启动) docker stop / start
镜像 ───────► 容器(运行) ────────► 容器(停止)
│ │
│ docker rm │ docker rm
▼ ▼
删除(可写层数据丢失) 删除
四、容器常用运维命令
4.1 查看日志:docker logs
docker logs web # 查看完整日志
docker logs -f web # 跟随输出(类似 tail -f)
docker logs --tail 100 web # 只看最后 100 行
docker logs --since 10m web # 只看最近 10 分钟
容器日志默认输出到标准输出/错误,docker logs 能捕获它们。生产环境建议配日志驱动集中收集。
4.2 查看进程:docker top
docker top web # 查看容器内正在运行的进程(类似宿主机的 ps)
用于排查容器内 CPU/内存占用最高的进程。
4.3 查看资源占用:docker stats
docker stats # 实时查看所有容器 CPU/内存/网络/IO
docker stats --no-stream # 只输出一次,不持续刷新
这是判断容器资源使用情况最直接的手段。
4.4 查看详情:docker inspect
docker inspect web # 查看容器完整配置(JSON)
inspect 能拿到容器的 IP、挂载、环境变量、健康状态等几乎所有信息,是排错利器。如果想只取某个字段,可用 -f 加 Go 模板语法(如 docker inspect -f '{{.State.Status}}' web)。
4.5 查看端口映射:docker port
docker port web # 查看容器的端口映射关系
输出如 80/tcp -> 0.0.0.0:8080,说明容器 80 映射到宿主机 8080。
五、资源限制:CPU 与内存
5.1 为什么要限制资源
默认情况下容器可以使用宿主机的全部 CPU 和内存。若某个容器失控(内存泄漏、死循环),可能拖垮整台机器,影响其他容器。生产环境必须为容器设置资源上限。
5.2 限制内存
# 限制内存最多 512MB
docker run -d --name app --memory 512m myapp
# 限制内存 + 限制 swap 总量为 768MB
docker run -d --name app --memory 512m --memory-swap 768m myapp
单位:b/k/m/g(字节/千字节/兆/吉)。--memory 限制常驻内存,--memory-swap 限制「内存 + swap」总量。
5.3 限制 CPU
# 限制最多使用 1.5 个 CPU 核心
docker run -d --name app --cpus 1.5 myapp
# 用相对份额限制(1024 为基准,值越大占 CPU 越多)
docker run -d --name app --cpu-shares 512 myapp
--cpus 是直观的「核数」限制,推荐使用。--cpu-shares 是相对权重,只在你机器上有多个容器争抢 CPU 时才有意义。
5.4 查看与修改限制
运行中的容器不能直接改资源限制(需重建),但可以查看和部分更新:
docker inspect -f '{{.HostConfig.Memory}}' app # 内存限制(字节)
docker inspect -f '{{.HostConfig.NanoCpus}}' app # CPU 限制(纳核)
docker update --cpus 2 app # 更新 CPU 限制
docker update --memory 1g app # 更新内存限制
六、进入容器:exec 与 attach
6.1 docker exec:在运行中的容器里执行命令
这是最常用的进入容器方式:
# 进入容器并打开交互式 shell
docker exec -it web bash
# 在容器里执行单条命令,不进入交互
docker exec web ls /etc/nginx
# 以 root 身份进入(容器默认用户可能不是 root)
docker exec -it -u root web bash
注意:exec 在正在运行的容器里执行新命令,不影响容器主进程。这是排错和调试的首选方式。
6.2 docker attach:挂到容器主进程
docker attach web
attach 把当前终端附着到容器的主进程上,看到的是容器主进程的输出,且 Ctrl+C 可能直接终止容器。相比之下 exec 更安全,日常多用 exec。
6.3 两者的区别
| 方式 | 作用 | 风险 |
|---|---|---|
| docker exec | 在容器里开新进程执行命令 | 不影响主进程,安全 |
| docker attach | 附着到容器主进程 | Ctrl+C 可能终止容器 |
日常排错、查看、改文件,优先用 exec。
七、镜像与容器的清理
7.1 磁盘占用问题
随着镜像、容器、卷越来越多,/var/lib/docker 会占用大量磁盘。定期清理是运维常态。
7.2 清理未使用的对象:docker system prune
docker system prune # 清理停止的容器、无用网络、悬空镜像、构建缓存
docker system prune -a # 连带清理所有未被使用的镜像
docker system prune -a --volumes # 连带清理未使用的卷(小心:会删数据)
-a 会删除所有未被任何容器使用的镜像,--volumes 会删除未挂载的卷——后者可能误删数据,执行前一定确认。
7.3 单独清理
docker container prune # 清理所有已停止的容器
docker image prune # 清理悬空镜像(没有标签的)
docker volume prune # 清理未使用的卷
docker network prune # 清理未使用的网络
7.4 查看磁盘占用:docker system df
docker system df # 查看镜像/容器/卷/构建缓存的磁盘占用
像 df 一样展示各类对象的磁盘占用,方便决定该清理什么。
八、常见问题排查
8.1 容器一直退出(Exited)
容器主进程退出,容器就结束。用日志看原因:
docker ps -a # 看到 STATUS 是 Exited
docker logs <容器名> # 查看退出原因
常见原因:应用报错、前台进程意外退出、命令不存在。
8.2 端口被占用
docker run ... -p 8080:80 ... # 报端口已被占用
docker ps # 查看哪个容器占了 8080
sudo ss -ltnp | grep 8080 # 或查看宿主机谁在监听 8080
换一个宿主端口,或先停掉占用它的容器。
8.3 拉取镜像超时/失败
- 确认镜像加速器配置生效(第 2 篇第 4 章);
- 检查网络能否访问镜像源;
- 尝试换一个加速地址或显式指定镜像源前缀。
8.4 磁盘满导致容器无法启动
docker system df # 看占用
docker system prune -a # 清理(确认后再加 --volumes)
df -h # 确认磁盘释放
8.5 权限被拒(permission denied)
普通用户执行 docker 报权限错误:确认已加入 docker 组并重新登录(newgrp docker),或用 sudo。
九、总结
- 镜像管理:pull 拉取、images 查看、tag 标记、push 推送、history 看分层、inspect 看细节;
- 分层原理:镜像由只读层叠加,overlay2 存储驱动实现联合挂载,不同镜像共享基础层;
- 生命周期:run 创建启动、ps 查看、stop/start/restart、rm 删除(删除会丢可写层数据);
- 运维命令:logs 日志、top 进程、stats 资源、inspect 详情、port 端口;
- 资源限制:--memory/--cpus 限制内存和 CPU,生产必配;
- 进入容器:优先用 exec(开新进程),attach 会附着主进程有风险;
- 清理:system prune 清理无用对象,system df 查看占用。
参考资料
- Docker 官方:镜像命令参考(docker image):https://docs.docker.com/engine/reference/commandline/image/
- Docker 官方:容器命令参考(docker container):https://docs.docker.com/engine/reference/commandline/container/
- Docker 官方:存储驱动 overlay2:https://docs.docker.com/storage/storagedriver/overlayfs-driver/
- Docker 官方:资源限制(--cpus/--memory):https://docs.docker.com/config/containers/resource_constraints/
- Docker 官方:清理未使用数据(system prune):https://docs.docker.com/engine/reference/commandline/system_prune/
