# 3. Docker常用命令:镜像管理、容器生命周期、网络和卷
Docker的命令行工具,说真的,是我们日常打交道最多的东西。你想想看,不管是拉镜像还是跑容器,几乎每步都离不开它。我个人习惯把这些命令分成四类:镜像管理、容器生命周期、网络和存储卷。搞清楚这四块,Docker基本就上手了。
3.1 镜像管理命令
说白了,镜像就是容器的“模板”。你拉一个镜像下来,才能用它起容器。我刚开始用Docker时,就靠下面这几个命令活着。
| 命令 | 作用 | 常用场景 |
|---|---|---|
| docker pull | 从仓库拉取镜像 | 下载 ubuntu:22.04、nginx:alpine |
| docker images | 列出本地所有镜像 | 检查有哪些镜像可用 |
| docker rmi | 删除镜像 | 清理不再使用的旧镜像 |
| docker tag | 给镜像打标签 | 把本地镜像标记再推送 |
| docker inspect | 查看镜像元数据 | 排查镜像的配置和层信息 |
镜像管理里,我最常用的是 docker pull 和 docker images。先拉下来看看对不对,再决定删不删。我个人习惯用 docker images --format 来定制输出,只看我关心的字段。
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
小技巧:docker system df 可以查看所有镜像、容器、卷占了多少磁盘空间。我每个月跑一次,清理那些悬空的镜像层。
注意:docker rmi 只能删除没有被容器使用的镜像。如果有容器还在用这个镜像,会报错。你先停容器,再删镜像。
3.2 容器生命周期管理
容器是镜像的“运行实例”。这一块命令最多,也是我们平时敲得最频繁的。我记得刚开始带团队时,有个同事总是记不清 docker start 和 docker run 的区别。嗯,这里我展开说说。
3.2.1 容器创建与启动
- docker run:创建并启动一个新容器,等于 create + start 的合体。
- docker create:只创建容器,不启动。
- docker start/stop/restart:控制已创建容器的启停。
# 创建一个nginx容器,映射端口,并以守护模式运行
docker run --name my-nginx -d -p 8080:80 nginx:alpine
# 进入正在运行的容器,做调试或排查
docker exec -it my-nginx /bin/sh
# 查看容器日志
docker logs --tail 100 -f my-nginx
你想想看,docker run 背后其实做了好几件事:先检查本地有没有 nginx:alpine 这个镜像,没有就去拉,拉完才创建容器、启动容器、附加网络和存储。我在项目里遇到过有人反复用 docker run 来重启容器,结果发现容器 ID 每次都换,根本连不上。这其实是因为 run 每次都创建新实例,不是重启已有容器。
3.2.2 常用控制命令
| 操作 | 命令示例 | 说明 |
|---|---|---|
| 停止容器 | docker stop my-nginx |
优雅停止,发送 SIGTERM |
| 强制停止 | docker kill my-nginx |
立刻杀死(SIGKILL) |
| 启动已停止的容器 | docker start my-nginx |
不重建,直接用已有容器 |
| 删除容器 | docker rm -f my-nginx |
-f 强制删除运行中的容器 |
| 列出容器 | docker ps -a |
-a 显示所有状态 |
关键概念:容器一旦被删除,内部的所有变更都会丢失,除非你用了卷或commit。所以我在生产环境里,数据绝对不存容器内部。
3.3 网络管理
Docker默认的网络模式,说白了有三种:bridge、host、none。我个人最常用的是桥接模式,也是默认的。但多容器时,我建议你用 自定义bridge网络,因为内置的DNS解析功能可以让你直接通过容器名来访问,不用写IP。
# 创建一个自定义桥接网络
docker network create --driver bridge app-network
# 启动两个容器并连接到这个网络
docker run --name web --network app-network -d nginx
docker run --name db --network app-network -d postgres
# 在web容器里可以直接ping db,而不是写IP
docker exec web ping db
踩坑记录:我曾经在生产环境忘记指定网络,两个服务放在默认bridge里,结果靠IP地址通信。后来容器重启后IP变了,服务直接断掉。从那以后,我只要是多容器通信,一律用自定义网络 + 容器名访问。
3.4 存储卷管理
容器的文件系统是临时性的。容器删了,数据也就没了。所以数据持久化的核心就是 卷(Volume) 和 绑定挂载(Bind Mount)。我推荐优先用卷,因为卷由Docker管理,跨平台更安全。
| 存储方式 | 特点 | 适用场景 |
|---|---|---|
| 卷(Volume) | Docker管理,存储在宿主机特定目录 | 数据库、日志持久化 |
| 绑定挂载(Bind Mount) | 直接挂载宿主机的目录或文件 | 开发时热重载、配置文件 |
| tmpfs 挂载 | 存储在内存中,容器停止即消失 | 敏感凭证、临时缓存 |
# 创建卷
docker volume create mydata
# 启动容器挂载卷
docker run -d --name pg -v mydata:/var/lib/postgresql/data postgres:16
# 挂载宿主机目录(用于开发调试)
docker run -d --name dev -v $(pwd)/app:/app nginx
避坑指南:绑定挂载时,如果宿主机目录不存在,Docker会自动创建,但创建的是目录不是文件。我曾经想挂载一个配置文件,路径写错了没报错,结果容器里挂了一个空目录,服务启动失败。排查了我快一个小时。
嗯,回过头来看,命令再多也离不开这几个核心逻辑:镜像 pull 下来 → run 成容器 → 容器用网络通信 → 数据用卷持久化。你把这几个命令记熟,日常开发基本够用了。