3、Docker基础命令:镜像管理与容器生命周期

好,咱们直接进入正题。Docker 的命令说多不多,说少不少。但真正日常高频使用的,其实就是镜像管理和容器生命周期这两块。我刚开始接触 Docker 时,也试图背下所有命令,后来发现没必要——把核心的十几个命令用熟,就能覆盖 90% 的工作场景。

这一章,咱们就聚焦在这两类命令上。你跟着我敲一遍,基本就记住了。

3.1 镜像管理命令

镜像是什么?说白了就是容器的「模板」。你要跑一个容器,得先有这个镜像。就像你要做菜,得先有菜谱一样。

3.1.1 docker pull:拉取镜像

这是你接触 Docker 后用的第一个命令。从远程仓库(默认是 Docker Hub)把镜像下载到本地。

docker pull nginx:latest
docker pull ubuntu:22.04
docker pull registry.cn-hangzhou.aliyuncs.com/library/nginx:1.21

我个人习惯,拉镜像时尽量指定具体版本标签,而不是用 latest。为什么?因为 latest 是个动态标签,今天拉的和明天拉的可能是不同版本。我在项目中遇到过,测试环境用的 latest,生产环境也用的 latest,结果某天镜像更新后,测试通过了但生产挂了——因为两个环境拉取的时间点不同。嗯,从那以后,我所有脚本里都写死了版本号。

小技巧: 国内拉 Docker Hub 镜像慢?可以配置镜像加速器,或者直接用阿里云、腾讯云的镜像仓库。我一般用阿里云的,速度稳定。

3.1.2 docker images:查看本地镜像

拉下来之后,怎么确认有没有成功?用 docker images 查看本地镜像列表。

docker images
# 或简写
docker image ls

输出结果会显示仓库名、标签、镜像 ID、创建时间和大小。你想想看,如果本地镜像越来越多,这个列表会变得很长。我一般会配合 grep 来过滤:

docker images | grep nginx

这样只显示跟 nginx 相关的镜像,清爽多了。

3.1.3 docker rmi:删除镜像

镜像占磁盘空间,尤其是那些调试用的临时镜像。用 docker rmi 删除不需要的镜像。

docker rmi nginx:1.21
docker rmi 镜像ID

注意:如果某个镜像正在被容器使用,你是删不掉的。Docker 会提示你「有容器依赖这个镜像」。这时候你得先删容器,再删镜像。我曾经犯过这个错——想清理空间,结果删不掉,还以为是命令出问题了。

警告: 删除镜像前,确认没有容器在使用它。可以用 docker ps -a 查看所有容器(包括已停止的)。

3.1.4 docker tag:给镜像打标签

这个命令很实用。你可以给一个镜像打上多个标签,方便管理。比如,你从官方拉了一个 nginx:latest,想把它标记成自己仓库的版本:

docker tag nginx:latest myregistry.com/mynginx:v1.0

这样,你后续推送镜像到私有仓库时,就用这个新标签。我个人习惯,在 CI/CD 流程中,每次构建完镜像都会打上两个标签:一个是版本号(如 v1.2.3),一个是 latest。这样既方便回滚,也方便开发环境使用。

3.2 容器生命周期命令

镜像有了,接下来就是跑容器。容器的生命周期,说白了就是:创建→运行→停止→删除。这四个阶段对应四个核心命令。

3.2.1 docker run:创建并启动容器

这是最常用的命令,没有之一。docker run 等于先 docker createdocker start,一步到位。

docker run -d --name my-nginx -p 8080:80 nginx:1.21

解释一下参数:

  • -d:后台运行(detached mode)。不加的话,终端会被容器日志占满。
  • --name:给容器起个名字。我建议每次都起名,不然 Docker 会随机生成一个名字,比如 focused_curie,你根本记不住哪个是哪个。
  • -p:端口映射。宿主机端口:容器端口。

我记得刚学 Docker 时,经常忘记加 -d,结果一关终端容器就停了。后来养成了习惯,生产环境必加 -d,调试时才不加。

重点: docker run 如果指定的镜像本地没有,会自动执行 docker pull。但我不建议依赖这个自动拉取行为——显式 pull 更可控。

3.2.2 docker start:启动已存在的容器

容器创建后如果停止了,可以用 docker start 重新启动。注意,它不会重新创建容器,只是把已有的容器跑起来。

docker start my-nginx

这个命令我用的场景不多,更多是在调试时:先 docker stop 停掉,改完配置再 docker start 启动。但说实话,现在我更倾向于删掉容器重新 docker run,因为这样更干净。

3.2.3 docker stop:停止容器

停止一个运行中的容器。Docker 会给容器发送 SIGTERM 信号,让它优雅退出。如果超时(默认10秒)还没停,就发 SIGKILL 强制杀死。

docker stop my-nginx
docker stop -t 30 my-nginx  # 自定义超时时间

你想想看,为什么要有优雅退出?因为有些应用需要做清理工作,比如保存状态、关闭数据库连接。我曾经遇到过,直接 docker kill 导致数据丢失的情况。所以,能用 stop 就别用 kill

3.2.4 docker rm:删除容器

容器停止后,它还在磁盘上占着空间。用 docker rm 彻底删除。

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

我一般会定期清理不用的容器:

docker rm $(docker ps -aq)  # 删除所有已停止的容器

注意,-f 参数会直接杀死容器再删除,相当于 docker kill + docker rm。慎用。

3.3 常用命令组合速查表

为了方便你日常查阅,我把这些命令整理成了一张表。你可以保存下来,忘了就瞄一眼。

命令 作用 常用参数 使用频率
docker pull 拉取镜像 指定版本标签 ⭐⭐⭐⭐
docker images 查看本地镜像 配合 grep 过滤 ⭐⭐⭐⭐
docker rmi 删除镜像 镜像名或 ID ⭐⭐⭐
docker tag 打标签 源镜像:标签 目标镜像:标签 ⭐⭐⭐
docker run 创建并启动容器 -d, --name, -p, -v ⭐⭐⭐⭐⭐
docker start 启动已停止的容器 容器名或 ID ⭐⭐
docker stop 停止容器 -t 超时时间 ⭐⭐⭐⭐
docker rm 删除容器 -f 强制删除 ⭐⭐⭐

3.4 避坑指南

最后,分享几个我踩过的坑,你遇到了能少走弯路。

  • 镜像越拉越多,磁盘爆了:我建议每周执行一次 docker system prune,它会清理所有未使用的镜像、容器和网络。但注意,它会删掉所有未被容器引用的镜像,如果你有需要保留的,先确认好。
  • 容器名冲突:如果你 docker run 时用了已经存在的容器名,Docker 会报错。要么删掉旧容器,要么换个名字。我习惯在名字后面加日期,比如 my-nginx-20240101,避免冲突。
  • 端口被占用:启动容器时如果端口映射冲突,Docker 会直接报错退出。先用 lsof -i :端口号 检查端口占用情况,再决定用哪个端口。

好了,这一章的内容就这些。镜像管理和容器生命周期是 Docker 操作的基础,你把这几个命令练熟了,后续的镜像构建、编排部署才能顺手。下一章,咱们聊聊 Dockerfile 的编写技巧——那才是真正体现功力的地方。