4、Docker容器基础:创建与启动容器、查看容器状态、进入与退出容器、停止与删除容器
好,咱们进入正题。容器是Docker的核心,说白了就是一个个轻量级的「小虚拟机」。但别被这个比喻骗了——它跟虚拟机完全是两码事。我刚开始接触Docker时,也以为容器就是个跑得快的虚拟机,结果踩了不少坑。今天咱们就把容器的生命周期彻底捋一遍。
4.1 创建与启动容器
创建容器有两种方式:docker create 和 docker 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:只创建了,还没启动。
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
stop 和 kill 的区别:
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 参数,相当于先 kill 再 rm。
docker container prune 会删除所有已停止的容器,没有确认提示。我建议你养成习惯:删除前先 docker ps -a 看一眼,确认哪些容器是可以删的。特别是刚学的时候,别一股脑全删了。
还有个实用技巧:清理所有不再使用的资源(容器、网络、镜像、卷):
docker system prune -a
这个命令很猛,会删掉所有未被使用的镜像和容器。我一般在开发环境每周跑一次,生产环境从不乱用。
小结
容器的生命周期其实就这几个动作:创建→启动→运行→停止→删除。你想想看,跟咱们平时用虚拟机是不是有点像?但容器快就快在「秒级启动」和「轻量隔离」。记住几个关键点:
- 用
docker run创建并启动,用docker exec -it进入调试。 - 查看状态用
docker ps -a,排查问题用docker logs和docker inspect。 - 停止用
stop别用kill,删除前先确认。
下一章咱们聊聊数据持久化——容器删了数据还在,这才是生产环境该有的样子。