Docker 常用命令全解:从容器启停到 Compose 编排(速查手册)
面向日常运维与开发的 Docker 命令速查手册。全文按「镜像 → 容器 → 排障 → 网络 → 存储 → 编排 → 清理」的顺序组织,每条命令均给出可直接复制的最小示例,并在关键处标注易踩的坑。
一、命令的分类,先建立心智模型
Docker 的命令看着多,其实只有六类。把命令挂到类别上,记忆负担会小很多:
| 类别 | 作用对象 | 代表命令 |
|---|---|---|
| 镜像管理 | 静态的、只读的模板 | pull images build tag rmi save/load |
| 容器生命周期 | 镜像运行起来的实例 | run start stop restart kill rm ps |
| 运行时观测 | 容器内部状态 | logs top stats inspect exec cp |
| 网络与端口 | 容器对外通信 | -p port network |
| 数据卷 | 数据持久化 | -v volume |
| 编排与清理 | 多容器 / 磁盘回收 | compose system prune |
一句话区分镜像与容器:镜像是类,容器是对象。 镜像不会被"启动",被启动的永远是容器。
二、镜像管理
2.1 查看与搜索
docker images # 查看本地镜像
docker images -a # 含中间层镜像(构建缓存)
docker images -q # 只输出 IMAGE ID,便于脚本处理
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
docker search nginx # 在 Docker Hub 搜索(仅对公共仓库有效)
2.2 拉取与打标签
docker pull nginx:1.25 # 不写 tag 时默认 latest,生产环境不要依赖 latest
docker tag nginx:1.25 registry.example.com/library/nginx:1.25
docker tag 是给同一个镜像 ID 起别名,不产生新的存储占用。它是推送私有仓库前的必要一步:仓库地址必须出现在镜像名里。
2.3 构建镜像
# 基本形式:-t 指定 名称:版本,末尾是构建上下文目录(注意是目录,不是 Dockerfile 文件)
docker build -t "java75-nginx:2.1" /root/docker-75/1/
# 指定 Dockerfile 位置与额外参数
docker build -t java75-nginx:2.2 -f /root/docker-75/2/Dockerfile \
--build-arg ENV=prod --no-cache /root/docker-75/2/
要点:
- 构建上下文会被整体发送给 Docker daemon,目录里不要放无关的大文件,用
.dockerignore排除。 - 层缓存按指令顺序命中,
COPY package.json与COPY .的顺序会显著影响构建速度。 --no-cache用于排查"明明改了代码但镜像没变"的问题。
2.4 导出与导入
docker save -o nginx-1.25.tar nginx:1.25 # 镜像 → tar 文件(保留历史层与 tag)
docker load -i nginx-1.25.tar # tar 文件 → 镜像
docker export -o container.tar mycontainer # 容器快照 → tar(丢失历史与元数据)
docker import container.tar myimage:latest # tar → 镜像(无 CMD/ENV,需重新指定)
save/load 面向镜像,export/import 面向容器文件系统,离线迁移优先用 save。
2.5 删除镜像
docker rmi nginx:1.25
docker rmi -f nginx:1.25 # 强制删除,多个 tag 指向同一 ID 时需 -f
docker rmi $(docker images -q -f "dangling=true") # 清理悬空镜像(<none>:<none>)
三、容器的生命周期
3.1 一张图看懂状态流转
docker create docker start
(无) ───────────────────► Created ─────────────────► Up (running)
▲ │
│ docker stop │
└────── Exited ◄─────────────┘
│
│ docker start(可再次启动)
▼
Up
docker rm ──► 彻底删除(不可恢复)
3.2 docker run:创建并启动
docker run = create + start,是最常用的命令,也是参数最多的命令。
# 交互式启动,进入容器 shell
docker run -it --name mycentos centos /bin/bash
# 后台启动,映射端口,设置开机自启
docker run -d -p 10001:80 --restart=always --name nginx-demo \
nginx:java75 /usr/sbin/nginx -g "daemon off;"
上例的三个关键点:
| 片段 | 含义 |
|---|---|
-p 10001:80 |
宿主机 10001 端口映射到容器 80 端口(宿主机:容器) |
--restart=always |
Docker 服务重启或容器异常退出后自动拉起 |
/usr/sbin/nginx -g "daemon off;" |
覆盖镜像的启动命令,让 nginx 在前台运行;容器的主进程一旦退出,容器即结束 |
常用参数速查:
| 参数 | 说明 |
|---|---|
-i |
保持标准输入开启 |
-t |
分配伪终端(TTY) |
-d |
后台运行,返回容器 ID |
--name |
指定容器名,便于后续操作 |
-p 宿主:容器 |
端口映射,可重复使用多个 |
-P |
随机映射镜像暴露的所有端口 |
-v 宿主路径:容器路径 |
挂载目录或文件 |
-e KEY=VALUE |
注入环境变量 |
--network |
加入指定网络 |
--restart |
重启策略,见第九节 |
--rm |
容器退出后自动删除,适合一次性任务 |
--privileged |
赋予几乎全部宿主机权限,非必要不用 |
3.3 启动、停止、重启、杀死
docker start 容器名 # 启动已存在的容器(不重新创建)
docker stop 容器名 # 优雅停止:先发 SIGTERM,10 秒后 SIGKILL
docker restart 容器名 # 重启
docker kill 容器名 # 直接 SIGKILL,进程没有机会清理现场
docker pause 容器名 # 冻结进程(cgroup freezer)
docker unpause 容器名
run 与 start 的区别是新手最容易混淆的一点: run 用镜像创建一个新容器再启动;start 只是把已存在的、处于 Exited 状态的容器重新跑起来。想改端口、改挂载、改环境变量,start 做不到,必须 rm 后重新 run。
stop 与 kill 的区别: stop 给进程留出收尾时间(关闭连接、刷盘、提交事务);kill 直接断电式终止,数据库类容器可能产生脏数据或需要恢复。生产环境优先用 stop。
3.4 查看容器
docker ps # 运行中的容器
docker ps -a # 所有容器,含已停止
docker ps -q # 只输出 ID
docker ps -qa # 所有容器 ID(批量操作的输入源)
docker ps -s # 附带容器可写层占用大小
docker ps -a --filter "status=exited"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
3.5 删除容器
docker rm 容器名 # 删除已停止的容器
docker rm -f 容器名 # 强制删除运行中的容器(先 kill 再删)
docker rm -f $(docker ps -qa) # 删除全部容器
⚠️
docker rm -f $(docker ps -qa)会连生产容器一起清掉。执行前先用docker ps -a核对,或改用--filter精确圈定范围。数据若无持久化,删除即永久丢失。
四、进入容器:attach 与 exec 的关键差异
docker attach 容器名 # 接入容器的主进程标准输入输出
docker exec -it 容器名 /bin/bash # 在容器内新开一个进程与终端
两者都能"进入容器",但行为完全不同,这是必须掌握的区别:
| 对比项 | docker attach |
docker exec |
|---|---|---|
| 本质 | 连接到 PID 1 的标准流 | 在容器内 fork 一个新进程 |
| 退出方式 | 输入 exit 或 Ctrl+D 会使主进程结束,容器停止 |
exit 只结束这个 shell,容器继续运行 |
| 安全退出的快捷键 | Ctrl+P 再 Ctrl+Q(detach) |
无需特殊操作 |
| 适用场景 | 查看主进程实时输出 | 调试、改配置、查文件 —— 日常首选 |
结论:除了观察前台进程输出,一律用 exec。 若容器是精简镜像(如 alpine)没有 bash,改用 /bin/sh:
docker exec -it 容器名 sh
五、观测与排障
5.1 日志
docker logs 容器名 # 输出全部日志
docker logs -f 容器名 # 持续跟踪(类似 tail -f)
docker logs --tail 100 容器名 # 只看最后 100 行
docker logs -f --since 10m 容器名 # 最近 10 分钟并持续跟踪
docker logs -t 容器名 # 每行附加时间戳
排查顺序建议固定为:ps -a 看状态 → logs 看报错 → inspect 看配置 → exec 进容器验证。
5.2 进程与资源
docker top 容器名 # 容器内进程列表(对应宿主机 PID)
docker stats # 实时 CPU / 内存 / 网络 / 磁盘 IO
docker stats --no-stream 容器名 # 取一次快照,适合脚本采集
docker top 输出的 PID 是宿主机视角的 PID,排查"宿主机 CPU 被打满但不知道是哪个容器"时非常有用。
5.3 详情与 IP
docker inspect 容器名 # 完整 JSON(配置、网络、挂载、状态)
docker inspect -f '{{.State.Status}}' 容器名 # 只看运行状态
docker inspect -f '{{.NetworkSettings.IPAddress}}' 容器名 # 只看 IP
| 原始写法 `docker inspect 容器名 | grep IPAddress 也能用,但会输出整行 JSON("IPAddress": "172.17.0.2",),后续处理不便。推荐 -f`(Go 模板)精确取值,便于写进脚本。 |
注意:默认 bridge 网络下容器 IP 在每次重建后会变化,不要把它写死在配置文件里。容器间通信应使用自定义网络 + 容器名解析(见第七节)。
5.4 其他排查用命令
docker port 容器名 # 查看端口映射关系
docker diff 容器名 # 容器可写层相对镜像的文件变化
docker events --since 1h # 守护进程事件流(启停、OOM、健康检查)
docker history 镜像名 # 镜像分层历史,用于分析体积膨胀来源
docker diff 是排查"容器里被改了什么"的利器:输出 A(新增)、C(修改)、D(删除)。若发现该持久化的目录出现在列表里,说明数据卷没挂对。
六、宿主机与容器之间传文件
# 宿主机 → 容器
docker cp ./app.jar 容器名:/opt/app/app.jar
# 容器 → 宿主机
docker cp 容器名:/var/log/app.log ./app.log
# 容器 → 容器
docker cp 容器A:/data ./backup
路径规则:容器侧必须以"容器名:"开头,否则会被当成宿主机路径。目录拷贝默认递归,加 -a 保留权限位。
一个常被忽略的点:docker cp 是"一次性搬运",不是同步。需要双向实时同步时应使用数据卷挂载。
七、网络与端口
7.1 端口映射
docker run -d -p 8080:80 nginx # 指定映射:宿主 8080 → 容器 80
docker run -d -p 127.0.0.1:8080:80 nginx # 只监听本机回环,不对外暴露
docker run -d -P nginx # 随机映射镜像 EXPOSE 的端口
docker port 容器名 # 反向查询映射关系
排查"端口不通"的固定三板斧:
docker ps确认PORTS列有映射;- 容器内
curl localhost:端口确认服务真的起来了; ss -lntp | grep 端口确认宿主机端口没被其他进程占用(-p 8080:80报port is already allocated就是此因)。
7.2 自定义网络
docker network create mynet
docker network ls
docker run -d --name api --network mynet myapp:1.0
docker run -d --name web --network mynet nginx
docker exec -it web ping api # 同网络内可用容器名直接解析
在同一个自定义网络里,Docker 内置 DNS 会把容器名解析为 IP,这比记 IP 可靠得多,也是 Compose 服务间通信的基础。
八、数据卷:容器的"持久层"
容器可写层随容器删除而消失,需要保留的数据必须落在卷上。
8.1 绑定挂载(bind mount)
docker run -v ~/60/data:/data -it centos /bin/bash
三个部分的含义:
| 片段 | 含义 |
|---|---|
-v |
声明数据卷 |
~/60/data |
宿主机目录,不存在会自动创建(以 root 身份创建,常见权限坑) |
/data |
容器内目录,不存在同样会自动创建 |
带名字的容器与卷:
# --name 命名容器,同时把宿主机目录挂进容器
docker run -it --name=v-1 -v ~/docker-75/data:/data centos /bin/bash
8.2 命名卷(named volume)
docker run -d --name mysql -v mysql-data:/var/lib/mysql mysql:8
docker volume ls
docker volume inspect mysql-data
两种挂载的取舍:
| 方式 | 写法 | 适用场景 |
|---|---|---|
| 绑定挂载 | -v /宿主/绝对路径:/容器路径 |
开发时改代码即时生效、挂配置文件 |
| 命名卷 | -v 卷名:/容器路径 |
数据库、日志等运行数据,由 Docker 统一管理,跨平台一致 |
8.3 只读挂载与权限
docker run -v /etc/localtime:/etc/localtime:ro -d nginx # 只读挂载,常用于时区同步
若容器内进程因权限写不了挂载目录,优先检查宿主机目录属主 UID 与容器内用户 UID 是否一致,而不是直接 chmod 777。
九、重启策略:让容器"活着"
docker run -d --restart=always nginx
docker update --restart=always nginx-demo # 修改已存在容器的策略
原文中的
update --restart=always nginx-demo缺少docker前缀,正确写法是上面这条。
四种策略的差异:
| 策略 | 行为 |
|---|---|
no |
默认值,不自动重启 |
on-failure[:N] |
非 0 退出码时重启,最多 N 次 |
always |
无论退出码如何都重启;docker stop 后不再重启,但重启宿主机后会拉起 |
unless-stopped |
同 always,但手动 stop 后即使宿主机重启也不拉起 |
生产环境推荐 unless-stopped:always 会让运维手动停掉的容器在机器重启后"自己复活",反而干扰故障处理。
十、清理:磁盘告警时的标准动作
docker system df # 先看占用分布:镜像/容器/卷/构建缓存
docker system df -v # 明细到单个镜像与卷
docker container prune # 删除所有已停止的容器
docker image prune # 删除悬空镜像
docker image prune -a # 删除所有未被容器使用的镜像
docker volume prune # 删除未被使用的卷
docker system prune -a --volumes # 全家桶清理,危险
⚠️
docker system prune -a --volumes会删除所有未使用镜像、已停止容器与所有未被引用的数据卷(含数据库数据)。执行前务必确认没有"停着但还要用"的容器。
安全的排查顺序是:system df → 定位大头 → 针对性地 image prune / container prune,不要一上来就全家桶。
十一、Docker Compose 常用命令
docker-compose 面向单机多容器编排,一条命令拉起整套依赖。
docker-compose up -d # 构建并启动所有服务,后台运行
docker-compose up -d --build # 强制重新构建镜像后再启动
docker-compose ps # 查看各服务运行状态
docker-compose logs -f # 跟踪所有服务日志
docker-compose logs -f myApp # 只看某个服务
docker-compose restart # 重启所有服务
docker-compose restart myApp # 只重启 myApp
docker-compose start # 启动(不重建)所有服务
docker-compose start myApp # 只启动 myApp
docker-compose stop # 停止所有服务(保留容器)
docker-compose stop myApp # 只停止 myApp
docker-compose rm # 删除已停止的服务容器
docker-compose rm myApp # 只删除 myApp 的容器
docker-compose down # 停止并删除容器与网络(推荐用它代替 rm)
docker-compose down -v # 额外删除数据卷
docker-compose config # 校验并打印合并后的配置
docker-compose exec myApp sh # 在运行中的服务里执行命令
两个容易混淆的点:
- `stop` 与 `down`:`stop` 只停容器,容器和网络都还在;`down` 会删除容器和网络,下次 `up` 是全新创建。
- `restart` 不会重新读取 `docker-compose.yml` 的修改。**改了编排文件必须 `up -d`**,`restart` 只重启进程。
Compose V2 中命令为 `docker compose`(中间是空格,作为 Docker CLI 插件),V1 是 `docker-compose`(独立二进制)。两者参数基本一致,新环境建议用 V2。
### 一个最小可用示例
```yaml
services:
web:
image: nginx:1.25
ports:
- "10001:80"
volumes:
- ./html:/usr/share/nginx/html:ro
- /etc/localtime:/etc/localtime:ro
restart: unless-stopped
depends_on:
- api
api:
build: ./api
environment:
- TZ=Asia/Shanghai
restart: unless-stopped
若使用独立的 compose 二进制,首次还需赋予执行权限:
chmod +x docker-compose
十二、速查表
| 需求 | 命令 |
|---|---|
| 后台起一个容器并映射端口 | docker run -d -p 8080:80 --name web nginx |
| 交互式进入新容器 | docker run -it --name c1 centos /bin/bash |
| 进入运行中的容器 | docker exec -it 容器名 bash |
| 安全脱离 attach | Ctrl+P Ctrl+Q |
| 看日志并跟踪 | docker logs -f --tail 100 容器名 |
| 看资源占用 | docker stats |
| 取容器 IP | docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 容器名 |
| 拷贝文件进容器 | docker cp ./a.jar 容器名:/opt/ |
| 构建镜像 | docker build -t app:1.0 . |
| 导出 / 导入镜像 | docker save -o a.tar app:1.0 / docker load -i a.tar |
| 设开机自启 | docker update --restart=always 容器名 |
| 批量删容器 | docker rm -f $(docker ps -qa) |
| 看磁盘占用 | docker system df |
| 拉起整套服务 | docker compose up -d |
| 停掉并清理整套服务 | docker compose down |
十三、八个高频坑
run -it启动服务类容器,一exit服务就停。 服务应使用-d后台运行,调试点用exec进入。- 用
attach调试后exit,容器跟着退出。 记住Ctrl+PCtrl+Q,或直接改用exec。 run之后再想改端口/挂载。 改不了,必须删掉重建,或改用 Compose 管理配置。- 容器名写错但没报错。
docker rm -f对不存在的容器会报错,但脚本里用$(docker ps -qa)拼参数时若结果为空,可能变成参数缺失的意外行为,加set -e更稳。 kill掉数据库容器后起不来。 断电式终止会留下未完成的事务或锁文件,优先stop。- 挂载目录权限报
Permission denied。 是 UID 不一致,不是"没给 777 就好"。 - 时区不对。 容器默认 UTC,挂载
/etc/localtime:ro或设置TZ=Asia/Shanghai。 - 数据卷忘了挂,删容器丢数据。 建容器前先想清楚:哪些目录必须在卷上。
小结
日常使用中,真正高频的命令不超过二十条:run ps logs exec cp stop rm images build inspect stats prune 以及 compose up/down。把这二十条用熟,再理解"镜像与容器分离""容器主进程退出即结束""数据必须落在卷上"这三条原则,绝大多数 Docker 操作都能自己推导出来。
排障时保持固定顺序:先看状态,再看日志,再看配置,最后进容器验证。 顺序稳定,效率就不会被情绪带偏。
浙公网安备 33010602011771号