4、Docker容器基础:创建与启动容器、查看容器状态、进入与退出容器、停止与删除容器

好,咱们进入正题。容器是Docker的核心,说白了就是一个个轻量级的「小虚拟机」。但别被这个比喻骗了——它跟虚拟机完全是两码事。我刚开始接触Docker时,也以为容器就是个跑得快的虚拟机,结果踩了不少坑。今天咱们就把容器的生命周期彻底捋一遍。

4.1 创建与启动容器

创建容器有两种方式:docker createdocker run。区别在哪?create 只是创建,容器处于「已创建」状态,不会启动。run 则是创建并立即启动。我个人习惯直接用 run,除非需要先准备好配置再手动启动。

先看个最简单的例子:

# 创建并启动一个 Nginx 容器
docker run --name my-nginx -d -p 8080:80 nginx:latest

解释一下参数:

  • --name:给容器起个名字,方便后续操作。不指定的话Docker会随机生成一个,比如「focused_curie」这种,记起来很麻烦。
  • -d:后台运行(detached模式)。不加的话终端会被容器日志刷屏,你连命令都敲不了。
  • -p:端口映射。把宿主机的8080端口映射到容器的80端口。
我的习惯:生产环境我从来不用 --name 手动命名,而是用 docker-compose 统一管理。但学习阶段,建议每次都加 --name,方便你快速定位容器。

如果你只想创建但不启动:

docker create --name my-redis -p 6379:6379 redis:7-alpine

创建后,用 docker start 启动它:

docker start my-redis

嗯,这里要注意:docker run 每次都会基于镜像创建一个新容器。如果你重复执行 docker run --name my-nginx ...,第二次会报错说名字已存在。我曾经因为这个在CI流水线里吃过亏——每次构建都生成新容器,磁盘很快就满了。

4.2 查看容器状态

容器跑起来了,怎么看它活得好不好?最常用的命令:

# 查看运行中的容器
docker ps

# 查看所有容器(包括已停止的)
docker ps -a

# 查看最近创建的容器
docker ps -l

输出大概长这样:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 nginx:latest "/docker-entrypoint.…" 2 minutes ago Up 2 minutes 0.0.0.0:8080->80/tcp my-nginx
f6e5d4c3b2a1 redis:7-alpine "docker-entrypoint.s…" 5 minutes ago Exited (0) 3 minutes ago my-redis

STATUS 列是关键:

  • Up:正常运行中,后面跟运行时长。
  • Exited:已退出,括号里是退出码。0表示正常退出,非0表示有错误。
  • Paused:被暂停了。
  • Created:只创建了,还没启动。
避坑指南:我曾经遇到一个情况,容器状态显示「Up」,但业务就是访问不了。后来发现是容器内的进程挂了,但Docker守护进程没检测到。所以别光看 docker ps,还得配合 docker logs 看日志。

想看更详细的信息?用 docker inspect

docker inspect my-nginx

这会输出一个巨大的JSON,包含容器的IP地址、挂载卷、网络配置、环境变量等等。我经常用它来排查网络问题——比如两个容器能不能互通,查一下IP就知道了。

4.3 进入与退出容器

有时候你需要进到容器里面看看,比如调试配置、检查日志文件。常用的方式有两种。

方式一:attach(不推荐)

docker attach my-nginx

这会直接连接到容器的标准输入输出。但有个大坑:如果你用 Ctrl+C 退出,容器也会跟着停止。为什么?因为 attach 会把你的终端信号直接传给容器的主进程。我刚开始用Docker时就被这个坑过——想退出看看配置,结果把生产容器给停了。

方式二:exec(推荐)

# 进入容器并启动一个交互式 shell
docker exec -it my-nginx /bin/bash

# 如果容器里没有 bash,试试 sh
docker exec -it my-nginx /bin/sh

参数说明:

  • -i:交互模式,保持标准输入打开。
  • -t:分配一个伪终端,让你能看到命令提示符。

这两个参数通常一起用,写成 -it。你想想看,不加 -t 的话,你敲命令连个回显都没有,跟盲打似的。

进入容器后,你会看到类似这样的提示符:

root@a1b2c3d4e5f6:/#

这时候你就可以随意操作了——查看文件、安装工具、调试进程。退出时用 exit 命令或者 Ctrl+D,容器会继续在后台运行,不会受影响。

我的习惯:我一般用 docker exec -it 进入容器,但不会在里面做永久性修改。因为容器一旦删除,所有修改都会丢失。真要改配置,我会在Dockerfile里改好,或者用挂载卷。

4.4 停止与删除容器

容器用完了,得清理掉。不然磁盘空间会被占满——我见过有人服务器上挂了上百个停止的容器,还纳闷为什么磁盘报警。

停止容器:

# 优雅停止(发送 SIGTERM 信号,给容器10秒时间清理)
docker stop my-nginx

# 强制停止(发送 SIGKILL 信号,直接杀掉)
docker kill my-nginx

stopkill 的区别:

  • stop:先发 SIGTERM,等10秒(可配置),如果还没停就发 SIGKILL。
  • kill:直接发 SIGKILL,不给任何缓冲时间。

生产环境我永远用 stop。为什么?因为容器里的应用可能需要做清理工作——比如数据库要刷缓存、Web服务器要断开连接。直接 kill 可能导致数据丢失。我曾经有一次在凌晨做维护,手快用了 kill,结果数据库没来得及刷盘,重启后花了半小时做恢复。

删除容器:

# 删除已停止的容器
docker rm my-nginx

# 强制删除运行中的容器
docker rm -f my-nginx

# 删除所有已停止的容器(慎用)
docker container prune

注意:docker rm 只能删除已停止的容器。如果你想删正在运行的,得加 -f 参数,相当于先 killrm

警告:docker container prune 会删除所有已停止的容器,没有确认提示。我建议你养成习惯:删除前先 docker ps -a 看一眼,确认哪些容器是可以删的。特别是刚学的时候,别一股脑全删了。

还有个实用技巧:清理所有不再使用的资源(容器、网络、镜像、卷):

docker system prune -a

这个命令很猛,会删掉所有未被使用的镜像和容器。我一般在开发环境每周跑一次,生产环境从不乱用。

小结

容器的生命周期其实就这几个动作:创建→启动→运行→停止→删除。你想想看,跟咱们平时用虚拟机是不是有点像?但容器快就快在「秒级启动」和「轻量隔离」。记住几个关键点:

  • docker run 创建并启动,用 docker exec -it 进入调试。
  • 查看状态用 docker ps -a,排查问题用 docker logsdocker inspect
  • 停止用 stop 别用 kill,删除前先确认。

下一章咱们聊聊数据持久化——容器删了数据还在,这才是生产环境该有的样子。