一、容器的一生:从出生到死亡
"小陈,容器也有'一生'。搞懂它,你才能不慌。"老周画:
容器的生命周期:
创建(create)→ 启动(start)→ 运行(running)
│
┌─────┴─────┐
│ 正常运行 │ ← 主进程活着
│ 主进程退出 │
└─────┬─────┘
▼
停止(stopped)
│
删除(rm)→ 彻底消失(数据没了!)
"关键概念:容器的'生死'跟它的主进程绑定。 容器里那个 CMD 命令的进程一退出,容器就停了。比如 CMD ["python", "app.py"]——python 进程挂了,容器就停止。容器不是一个'系统',是一个'进程'的隔离环境。"
# 生命周期相关命令
docker create --name web01 nginx # 创建(不启动)
docker start web01 # 启动
docker stop web01 # 优雅停止(发 SIGTERM,等一会再 SIGKILL)
docker kill web01 # 强制杀死(直接 SIGKILL)
docker restart web01 # 重启
docker rm web01 # 删除(容器没了)
docker rm -f web01 # 强制删除(运行中也删)
"stop 和 kill 的区别要记住:stop 是'请优雅退出'(给应用时间保存数据),kill 是'直接砍死'。 生产环境优先 stop。"
二、前台 vs 后台:为什么 docker run nginx 会"卡住"
小陈第一次跑 nginx 容器,发现终端"卡住"了,没反应。
老周:"你卡住的其实是 nginx 的前台日志。容器有两种运行方式:"
前台运行(默认):
docker run nginx
→ 容器的输出直接打到你的终端(适合调试、看日志)
→ Ctrl+C 退出 = 容器停止
后台运行(生产常用):
docker run -d --name web01 nginx
→ 容器在后台跑,终端不占用(-d = detached)
→ 日志不显示,用 docker logs 查看
交互式运行(进容器操作):
docker run -it ubuntu bash
→ -i 保持标准输入打开,-t 分配终端
→ 像 ssh 进了一台机器(其实进了容器)
"生产环境用 -d 后台跑,调试用前台或 -it 进容器。 这是最基本的习惯。"
三、进入容器:exec 与 attach
"容器跑起来之后,想进去看看?用 exec:"老周说:
# 进入正在运行的容器(开一个 bash)
docker exec -it web01 bash
# 在容器里执行单条命令(不进交互)
docker exec web01 ls /etc/nginx
# 看容器的"主进程"日志(attach 到主进程输出)
docker attach web01
exec vs attach:
exec :在容器里"新开一个进程"(常用,如开 bash 排查)
attach :"连到容器主进程的输出"(相当于看前台日志)
调试首选 exec -it bash
"exec 是你排查容器问题的最常用武器——进不去容器,你都不知道里面发生了什么。"
四、日志:容器说没就没,日志去哪了
"容器最大的坑之一:它死了,日志也跟着没了(如果没配置)。"老周说,"所以要从一开始就把日志管好:"
# 查看容器日志
docker logs web01 # 看全部日志
docker logs -f web01 # 实时跟踪(-f = follow)
docker logs --tail 100 web01 # 只看最后 100 行
docker logs --since 1h web01 # 看最近 1 小时的
# 日志的坑:默认日志都写在容器的可写层
# 容器删除 → 日志消失!
# 生产环境必须配"日志驱动"或把日志写到数据卷/外部收集
docker run -d --name web01 \
--log-driver json-file \ # 默认就是这个
--log-opt max-size=10m \ # 每个日志文件最大 10MB(防爆盘)
--log-opt max-file=3 \ # 最多 3 个文件(循环)
nginx
"日志管理三原则:容器内别写日志文件(写 stdout)、日志要限制大小(防爆盘)、日志要能持久化(配数据卷/收集到 ELK)。 后面第五章讲数据卷,第八章讲镜像仓库时都会碰到日志。"
五、容器挂了怎么办:重启策略
"容器里的应用崩了,容器就停了。谁来把它拉起来?"老周说,"靠重启策略(Restart Policy):"
# 重启策略(--restart)
docker run -d --name web01 \
--restart=always \ # 挂了自动重启(常用)
nginx
# 四种策略:
no # 不自动重启(默认)
on-failure[:N] # 非正常退出才重启,最多 N 次
always # 无论什么原因退出都重启(docker stop 除外)
unless-stopped # 总是重启,除非手动 stop
"生产容器几乎都用 --restart=always(或 unless-stopped)——让 Docker 引擎当'保姆',容器挂了自动拉起来。这是最简单的一层'自愈'。"
六、资源限制:防止一个容器吃垮整台机器
"还记得第一章说的'容器共享内核,隔离弱'吗?"老周说,"所以必须用 Cgroup 给容器上'紧箍咒':"
# 资源限制(第一章提过,这里完整版)
docker run -d --name ai01 \
--cpus=2 \ # 最多 2 核
--memory=1g \ # 最多 1GB 内存
--memory-swap=1g \ # 内存+swap 总共 1G(禁止 swap 溢出)
--pids-limit=100 \ # 最多 100 个进程(防 fork 炸弹)
--restart=always \
yunjian/ai-recommend:v1
# 查看容器的资源使用
docker stats # 实时看所有容器的 CPU/内存
"不设资源限制的容器 = 定时炸弹——一个内存泄漏的容器能把整台服务器拖垮。上线前必配:--cpus + --memory + --restart。 这是容器运维的'安全三件套'。"
七、章末:老周的第三层总结
第三层:容器生命周期
├── 生命周期:create → start → run → stop → rm
│ 容器生死 = 主进程生死(容器是"进程隔离",不是"系统")
├── 运行方式:前台(调试)/ -d 后台(生产)/ -it 交互
├── exec:进容器排查(-it bash);attach:看主进程输出
├── 日志:写 stdout、限制大小(max-size)、要持久化
├── 重启策略:--restart=always(容器挂了自动拉起)
└── 资源限制:--cpus/--memory/--pids-limit(安全三件套)
"小陈,现在你有个很扎心的问题要回答我:如果 web01 容器挂了,我们把它删了、重新 run 一个——容器里写的数据(比如用户上传的图片、数据库文件)还在吗?"
小陈想了想:"……好像不在了?容器删了不就全没了?"
"对!这是容器最大的'骗局'——容器内的文件系统是临时的! 下一章,我们解决这个问题:数据卷(Volume)。学会它,你的容器才能'删了又起,数据不丢'。"