Skip to content

第 3 章 容器生命周期 ​

本章目标:掌握容器的创建、启动、停止、删除与日志查看,理解前台/后台/交互模式、端口映射、环境变量与重启策略。

1. 容器的生命周期状态 ​

容器不是只有"运行/停止"两种状态,完整状态机如下:

text
        docker create / run
        ┌──────────────┐
        ▼              │
created ──▶ running ──▶ exited(正常退出/被停止)
        │     │  │          │
        │     │  └─ paused   │
        │     ▼              ▼
        └── dead(强制终止,一般少见)
  • created:已创建(分配了文件系统与网络),尚未启动;
  • running:进程正在运行;
  • paused:进程挂起(CPU 冻结,内存保留),用 docker pause/unpause 切换;
  • exited:已退出或停止,文件系统仍保留,可再次 start 重启;
  • dead:无法正常停止的异常状态。

查看容器:

bash
docker ps            # 只看运行中的容器
docker ps -a         # 所有容器(含已退出)
docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}'   # 自定义列

docker ps 默认看不到已退出的容器,很多"容器不见了"的困惑都源于此——用 -a。

2. 创建与启动:create 与 run ​

docker run 是 docker create + docker start 的合并,日常直接用它:

bash
docker create --name web nginx:alpine   # 只创建
docker start web                        # 再启动
docker run --name web2 nginx:alpine     # 一步创建并启动(前台)

docker run 的常用选项:

选项作用
-d, --detach后台运行,立即返回容器 ID
-it交互模式(-i 保持 STDIN 打开,-t 分配伪终端),进 shell 用
--name <名字>指定容器名(不指定则随机取名)
--rm容器退出时自动删除(适合一次性任务)
--restart <策略>重启策略(见第 5 节)
-p 宿主:容器端口映射(见第 3 节)
-e 键=值设置环境变量(见第 3 节)
bash
docker run -d --name web -p 8080:80 nginx:alpine   # 后台运行 nginx
docker run --rm -it alpine sh                        # 起一个一次性交互 shell

--rm 与 --restart 语义相反(一个退出即删、一个退出即重启),不要同时使用。

3. 访问容器:端口映射与环境变量 ​

容器有自己的网络命名空间,宿主机默认访问不到容器内的端口,需要显式发布端口:

bash
docker run -d --name web -p 8080:80 nginx:alpine
curl http://localhost:8080     # 宿主机 8080 端口 → 容器内 80 端口

-p 8080:80 表示"宿主机 8080 映射到容器 80"。省略宿主机端口(-p 80)会随机分配宿主机端口;-P 把容器声明的所有 EXPOSE 端口都随机映射。

端口冲突:-p 的宿主机端口必须唯一,被占用时会报 port is already allocated,换个端口或先清理旧容器。

环境变量用于向容器传配置(数据库地址、密钥、运行参数),很多官方镜像都靠它定制行为:

bash
docker run -d --name db \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=app \
  mysql:8.0

多个变量可以用 --env-file 从文件读取:

bash
# env.list
MYSQL_ROOT_PASSWORD=secret
MYSQL_DATABASE=app
docker run -d --env-file env.list mysql:8.0

4. 运行中的管理:日志、进入容器、停止与删除 ​

bash
docker logs web                # 查看日志(-f 跟随、--tail 只看末尾 N 行)
docker exec -it web sh         # 进入运行中容器的 shell(nginx:alpine 里有 sh)
docker top web                 # 查看容器内进程
docker inspect web              # 查看容器的详细配置(JSON)
docker stats                    # 实时查看所有容器的资源占用

exec 是在运行中容器里执行命令;容器已退出时 exec 会失败,此时只能 docker start 或 docker logs 看历史输出。

停止与删除:

bash
docker stop web        # 优雅停止(发 SIGTERM,宽限期后 SIGKILL)
docker kill web        # 立即强杀(SIGKILL)
docker rm web          # 删除已停止的容器
docker rm -f web       # 删除运行中的容器(先强杀再删)
docker container prune # 批量清理所有已停止的容器

要点:

  • stop 与 kill 的区别:stop 给应用留优雅退出时间(默认 10 秒),kill 立即强杀;
  • 删除运行中的容器必须 -f;
  • 停止 ≠ 删除:docker stop 后容器还在(ps -a 可见、可 start 重启),docker rm 才真正释放。

5. 重启策略:容器挂了自己爬起来 ​

--restart 由 docker 守护进程负责拉起退出或宕掉的容器,适合部署场景:

策略行为
no(默认)不自动重启
on-failure[:N]非零退出码时重启,最多 N 次
unless-stopped退出即重启,除非管理员手动 stop
always总是重启(包括 docker 重启后)
bash
docker run -d --restart unless-stopped --name web -p 8080:80 nginx:alpine
docker restart web          # 手动重启
docker update --restart no web   # 修改已有容器的重启策略

实践建议:开发调试用 --rm,部署用 --restart unless-stopped。

常见误区 ​

  • 误区:docker ps 看不到容器 = 容器没了。 正确:已退出的容器用 docker ps -a 看;停止 ≠ 删除。
  • 误区:docker run -d 后想看输出就直接看。 正确:用 docker logs;-d 会把输出与终端分离。
  • 误区:端口映射失败是容器问题。 正确:先检查宿主机端口是否被占用(netstat -ano | findstr 8080)。
  • 误区:docker attach 和 docker exec 一样。 正确:attach 连的是容器主进程的 stdin/stdout(通常配合 -it 交互),exec 是在容器里新起一个进程(如 shell),更常用。
  • 误区:容器重启 = 数据还在。 正确:restart 保留文件系统;但 docker rm 重建容器会丢可写层数据——数据持久化要交给第 4 章的数据卷。

小结 ​

  • 状态流转:created → running → exited,停止 ≠ 删除,ps -a 看全部。
  • docker run = create + start;-d 后台、-it 交互、--name 命名、--rm 用完即删。
  • 容器内端口默认不对外,用 -p 宿主:容器 发布;配置用 -e / --env-file 传入。
  • 运维三件套:logs(看输出)、exec(进容器)、inspect(看配置)。
  • 开发用 --rm,部署用 --restart unless-stopped。

练习 ​

  1. 用 nginx:alpine 起一个后台容器(-d -p 8081:80 --name web),curl http://localhost:8081 确认返回页面,再用 docker logs 查看访问日志。
  2. 用 docker exec -it web sh 进入容器,echo hello > /usr/share/nginx/html/test.txt,浏览器访问 http://localhost:8081/test.txt 验证容器内文件对外可见。
  3. 依次执行 docker stop web、docker ps -a(观察状态)、docker start web、docker rm -f web,记录容器状态变化。
  4. 分别用 --rm 和 --restart unless-stopped 运行容器,比较两者在手动 stop 后的行为差异。

可运行示例见 examples/03-container-lifecycle/,按其中的 README 步骤执行。

📖本文阅读--次|📊全站访问--次|👥访客--人