ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

善用 docker --help:从新手到高手的命令排障指南

善用 docker --help:从新手到高手的命令排障指南 从业这么多年我观察到一个很有意思的现象很多人对docker --help的利用率低到令人发指。大部分人在装完 Docker 的第一天会敲一遍docker help扫两眼之后就和这条命令形同陌路。真正遇到问题的时候第一反应是打开搜索引擎翻三年前的博客或者去群里喊一句有没有人知道 docker 怎么挂载目录。而我自己的习惯恰恰相反排障的第一件事永远是先敲对应子命令的 --help。这不是装清高而是因为 help 输出是我这台机器上唯一一份和当前 Docker 版本严格同步的说明书——它不依赖网络不会因为某人记错了而误导我也不会像博客那样越写越旧。写这篇文章的起因是这半年指导新人时反复看到同一个问题他们不是不会用 Docker而是不知道怎么自己找到 Docker 的用法。所以我想围绕 Docker Help Command 这件事把它里里外外讲清楚help 输出的结构长什么样、怎么逐层往下钻、新手阶段靠它避开哪些常见的坑、以及当报错出现在屏幕上时怎么把 help 作为排查链路的第一环来用。这篇文章既适合刚装好 Docker Desktop 还没跑通第一个容器的新手也适合用了两三年 Docker但从来没完整读过docker run --help的老手。1. 顶层 help 的结构比你想的要讲究1.1 一张命令地图动作优先还是对象优先在终端里执行docker --help你会看到类似下面的输出不同版本略有差异但整体布局一致$ docker --help Usage: docker [OPTIONS] COMMAND A self-sufficient runtime for containers Common Commands: run Create and run a new container from an image exec Execute a command in a running container ps List containers build Build an image from a Dockerfile pull Download an image from a registry images List images logs Fetch the logs of a container stop Stop one or more running containers rm Remove one or more containers ... Management Commands: builder Manage builds compose Define and run multi-container applications with Docker Compose container Manage containers context Manage contexts image Manage images network Manage networks system Manage Docker volume Manage volumes ... Options: --config string Location of client config files -c, --context string Name of the context to use -D, --debug Enable debug mode in the client -H, --host list Daemon socket to connect to -l, --log-level string Set the logging level ...我建议把这份输出当成一张命令地图来看而不是流水账。整张地图分三块上面是 Common Commands动作优先docker run、docker ps这种动词宾语中间是 Management Commands对象优先docker container、docker image这种宾语动词最下面是全局 Options。为什么会有两套并存的风格这是 Docker CLI 演进的结果。早期的 docker 命令行全是动作优先docker ps、docker images、docker rm简单直接。后来为了把同一对象下的操作收拢到一起Docker 在 1.13 时代引入了 management command 体系把命令按对象分组docker container ls等价于docker psdocker image ls等价于docker images。了解这个差异对你有两个实际价值。第一遇到不认识的命令时你可以按对象去猜想知道怎么管理网络敲docker network回车它会把组内所有子命令列出来想知道卷怎么做备份敲docker volume看看有没有 snapshots 之类的子命令。第二当你在一篇老博客里看到docker ps而你手头的 help 只提到了docker container ls时你不会慌——它们本来就是同一件事help 里也通常还会保留旧写法。1.2 Usage 行里的符号不是装饰很多人直接跳过 help 的第一行但第一行恰恰是最重要的语法骨架。看几个例子$ docker --help Usage: docker [OPTIONS] COMMAND $ docker run --help Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] $ docker cp --help Usage: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-方括号[ ]表示可选参数尖括号或裸大写单词表示必填参数...表示可以重复追加。比如docker run [OPTIONS] IMAGE [COMMAND] [ARG...]的准确读法是docker run必须跟一个 IMAGECOMMAND 和 ARG 可带可不带。这个符号系统在 Docker 里是全局统一的。所以你只要学会看 Usage 行就能判断一条命令该怎么拼而不是靠死记。遇到docker cp这种双路径命令help 里会把源路径写成一个整体带:的形式有些命令后面还有|-表示目标路径可以写-代表从标准输入输出读或写。这些细节不读 help 真的很难猜。1.3 全局 Options 是排查远程连接问题的钥匙顶层 help 底部的 Options 栏很多人一辈子都用不上但排障时它是救命的。注意这几个-H, --host list Daemon socket to connect to --config string Location of client config files -c, --context string Name of the context to use -D, --debug Enable debug mode in the client --tlsverify Use TLS and verify the remotedocker 客户端默认通过 unix socketLinux 上一般是/var/run/docker.sock连接本机 daemon。一旦你设置了环境变量 DOCKER_HOST或者切换了 context客户端连接的就不是这个默认 socket 了。这时候你会发现明明 docker 服务好好的可命令就是报连接不上。我在后面的排查章节会专门讲这条链路这里先记住一个结论当 docker 客户端行为异常时优先怀疑两条线索——context 和 DOCKER_HOST 环境变量它们都会影响命令最终连到哪。2. 逐层往深钻子命令的 --help 才是日常主力2.1 为什么说子命令 help 是版本绑定的最新文档Docker 版本迭代很快参数在变默认值在变甚至命令本身都在变。网上的文章写的是作者当时装的那个版本他写这样跑没问题大概率没错但他没写的边界条件你不一定能碰到。而docker run --help是你当前安装的这个客户端程序自己吐出来的文本——它和你的二进制文件来自同一份源码天然不会过时。我见过最典型的一个例子某个项目要用docker build构建多架构镜像同事翻到一篇两年前的博客抄了一个依赖 buildx 扩展参数的写法某台机器上报错说参数不存在。我让他先敲一下docker buildx build --help才发现这台机器上正确的入口是 buildx 插件而不是老的 build 命令问题一下就清楚了。这就是 help 和博客的差距版本对不上时blog 会把你往沟里带help 不会。2.2 拿docker run --help当范本拆一次参数分组docker run --help是所有子命令 help 里最长也最有代表性的一个。它会把全部选项按字母序排成一张大表没有分组想靠肉眼全看完几乎不可能。我的建议是记住几个高频参数其他的在现场用 grep 去过滤。下面这张表是我平时最常翻的一段参数作用备注-d, --detach后台运行并打印容器 ID不写就是前台运行CtrlC 会停掉容器-i, --interactive保持标准输入打开配合-t使用连写成-it-t, --tty分配伪终端没有它很多交互命令比如 mysql 客户端行为会异常--rm容器退出后自动删除排障时慎用容器一退出日志和文件系统就没了-p, --publish把容器端口映射到宿主机格式宿主机IP:宿主端口:容器端口-P, --publish-all把所有 EXPOSE 的端口映射到随机端口大小写只差一个字母含义差很远-v, --volume绑定挂载目录/卷更规范的新写法是--mount但-v还是最常用-e, --env注入环境变量例如 MySQL 的MYSQL_ROOT_PASSWORD--name给容器起名不指定的话 Docker 会随机生成一个名字--restart重启策略no、always、on-failure、unless-stopped--network指定网络模式bridge、host、none或自定义网络名--platform指定拉取/运行的镜像平台在苹果芯片上跑 amd64 镜像时常用这里特别提醒两个容易踩的坑。一个是-p和-P小写是你自己指定端口映射大写是把所有暴露的端口随机映射两者字母只差大小写行为差了十万八千里。你如果只是想把 8080 映射到 80写错成-P不会报错但端口完全对不上——这种问题不看 help 很难想到。另一个是-d不加-d时容器在前台跑按 CtrlC 会直接把容器停掉很多新手以为这只是一次普通的中断其实是 SIGTERM 到达了主进程。help 里--detach那行写得很清楚Run container in background and print container ID。2.3 环境变量是一份隐藏的 helpdocker 的帮助信息除了命令行输出还通过环境变量承担了一部分配置职责。最典型的是DOCKER_HOST # 指定 daemon 地址如 unix:///var/run/docker.sock 或 tcp://1.2.3.4:2375 DOCKER_CONTEXT # 指定 context 名称 DOCKER_TLS_VERIFY # 是否启用 TLS 校验 DOCKER_CERT_PATH # TLS 证书路径检查当前 shell 里有没有被设置过env | grep DOCKER这一步在排障时优先级很高。因为很多团队会通过.bashrc或 IDE 的终端环境变量预设 DOCKER_HOST 指向某个远程 daemon或者指向一个已不复存在的地址。命令本身没写错但环境把连接目标改了表现就是docker 命令莫名其妙不好使。当你看到某台机器docker info显示的 Server 地址和本地 socket 对不上时第一反应就应该是env | grep DOCKER。3. 新手最容易踩的坑其实 help 里都写了3.1 run、create、start 的区别看 Usage 行就知道很多新手会把所有启动容器的操作都交给docker run但如果需要的是把一个已存在的容器重新跑起来正确命令是docker start。怎么判断看 help$ docker run --help Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] Create and run a new container from an image $ docker start --help Usage: docker start [OPTIONS] CONTAINER [CONTAINER...] Start one or more stopped containersdocker run的宾语是 IMAGEdocker start的宾语是 CONTAINER可多个。所以当你用docker run去启动一个已经用这个名字创建过的容器时会得到报错Conflict. The container name ... is already in use。正确姿势是docker start 容器名。我把这三条命令串起来理解run create startcreate 只负责创建容器但不动它start 负责把已停止的容器拉起来。这个理解一旦建立后面再看重启策略、生命周期管理就顺手很多。3.2 进容器到底用 exec 还是 attach怎么进入正在运行的容器这个问题大概被问烂了。网上的答案经常是用 docker attach但老手更推荐docker exec -it 容器 bash。两者的区别也在 help 里$ docker exec --help Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...] Run a command in a running container $ docker attach --help Usage: docker attach [OPTIONS] CONTAINER Attach local standard input, output, and error streams to a running containerattach 是把你的输入输出直接接到容器的主进程上类似直接连进去看它在跑什么而 exec 是在容器里另起一个进程最常见的就是起一个 shell。用 attach 去进容器操作一旦主进程退出attach 也会断开而且键盘输入会直达业务进程容易把生产环境搞出事故。所以我建议默认都走exec -it。如果哪天你把一条命令跑成前台、卡住了想退出docker attach --help里有个--detach-keys可以设置分离快捷键默认是 CtrlPQ——这行帮助信息救过我至少三次。3.3 清理类命令的边界rm、rmi、prune 各管一段磁盘快满的时候新手通常只知道docker rm和docker rmi。但真正得力的清理工具是docker system prune我建议第一次用它之前先把 help 读一遍因为它带破坏性$ docker system prune --help Usage: docker system prune [OPTIONS] Remove unused data Options: -a, --all Remove all unused images not just dangling ones --filter filter Provide filter values -f, --force Do not prompt for confirmation --volumes Prune anonymous volumes注意--volumes这个选项不写它匿名卷会被保留写了它所有没有容器引用的匿名卷会被直接删除。卷是存放数据的地方误删之后没有回收站。我第一次在测试环境执行docker system prune -a --volumes -f的时候顺手干掉了一个本地数据库的挂载卷当时以为还挂在容器上实际上那个容器已经停了、卷也成匿名了。所以我的习惯是生产环境绝不裸跑 prune先docker ps -a确认哪些容器是真不要了再加--filter把范围缩到某类资源。docker rm和docker rmi的边界也在 help 里写得清楚rm 删容器rmi 删镜像。删不掉的报错信息其实很友好比如image is being used by running container会提示你哪个容器在用。你只要顺着报错往下查基本都能解决。3.4 日志参数、资源限制这两组参数排障时几乎天天用docker logs --help里有几个参数值得刻进肌肉记忆-f, --follow Follow log output --since string Show logs since timestamp or relative -n, --tail string Number of lines to show from the end of the logs -t, --timestamps Show timestamps --until string Show logs before a timestamp容器日志动辄上千行直接docker logs 容器名会把屏幕刷爆。正确姿势是docker logs -n 200 --since 10m 容器名先看最近 10 分钟的最后 200 行配合-f实时跟踪。时间戳参数-t也很有用排查容器到底哪一刻崩的时有时间和没有时间完全是两种排查体验。资源限制参数集中在docker run --help里--memory、--cpus、--memory-swap、--pids-limit这一组。有个常见误区是以为--cpus1表示限制为单核实际上它更像总 CPU 时间配额1 表示最多用一个完整核心的计算量可以跨多个核分摊。help 里写的原文是 Number of CPUs但更准确的理解是 CPU 配额比例。这个如果靠猜很容易写错。4. 排障实战让 help 成为排查链路而不是最后手段4.1 permission denied 类错误先查 socket再谈权限最常见的报错之一长这样$ docker ps permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock这个报错出现时多数人的第一反应是重装 Docker。完全没必要。报错已经把关键信息说清楚了是 unix socket 的权限问题。排查链路应该是看 socket 的属主和权限ls -l /var/run/docker.sock正常情况属主是 root属组是 docker。看当前用户属于哪些组id确认有没有 docker 组。如果不在 docker 组执行sudo usermod -aG docker $USER然后重新登录或newgrp docker生效。这里要给一个提醒把用户加进 docker 组等于把这个用户提升到了接近 root 的权限因为 docker 可以挂载宿主机目录、可以跑特权容器。个人开发机无所谓但公司共用的服务器上加组之前要想清楚边界。4.2 Docker Desktop 虚拟化报错先看宿主机的虚拟化能力Windows 上很常见的一个报错是 Docker Desktop failed to start because virtualization support wasnt detected不同版本文案略不同。这类问题通常和 Docker 本身关系不大而是宿主机没有开启或没有正确提供虚拟化能力。排查顺序建议检查 Windows 的虚拟化功能是否启用任务管理器 - 性能 - CPU看虚拟化是否为已启用或者命令行跑systeminfo在 Hyper-V Requirements 一段确认。如果是物理机进 BIOS/UEFI 确认 Intel VT-x / AMD-V 已打开。这个改动后需要重启重启完 Docker 可能就能起来了。如果用的是 Windows 家庭版或者没装好 WSL2Docker Desktop 依赖 WSL2 后端时也会给出类似的失败。可以先确认wsl --status是否正常必要时wsl --update。Linux 上对应的问题是 KVM 不可用比如某些虚拟机里跑 Docker Desktop 或嵌套虚拟化场景检查/dev/kvm是否存在。这个场景里 help 起的作用相对间接但它提醒你别把问题全归在 Docker 上——很多时候你要先保证宿主机的虚拟化底座是通的再去谈 Docker 配置。4.3 daemon 连不上先分清客户端问题还是服务端问题另一个高频报错Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?先做一个快速分诊docker info。如果输出里 client 信息正常、Server 信息报错说明客户端能跑、连不上服务端。接下来按顺序查systemctl status docker # 本机 daemon 是否在跑 journalctl -u docker -n 100 # daemon 最近日志 env | grep DOCKER # 环境变量是否把连接目标改了 docker context show # 当前 context 是不是指向了别处 ls -l /var/run/docker.sock # socket 是否真实存在很多服务明明启动失败的求助帖最后发现是执行命令的机器上 DOCKER_HOST 指向了一个远程地址而远程 daemon 根本没起来。这种问题如果不先看环境变量和 context排查起来会绕远路。这也是我在前面特意强调全局 Options 的原因——docker context ls能一眼看出当前有哪些 contextdocker context show能告诉你正在用哪个。而这两条命令本身你都可以用docker context --help和docker system --help找到。4.4 实例一个 MySQL 容器反复退出的完整排查取一个大家都会碰到的场景用 docker 跑 MySQL 8.0。常见起动命令docker run --name mysql8 \ -e MYSQL_ROOT_PASSWORD123456 \ -p 3306:3306 \ -d mysql:8.0结果docker ps什么也没看到只能docker ps -a看到容器处于 Exited 状态。这时候 help 的价值体现在让每一步都有据可查先看docker run --help里的-e、-p参数格式确认环境变量名和端口映射写法没写错。MySQL 镜像要求MYSQL_ROOT_PASSWORD存在且非空缺它镜像的入口脚本会直接退出。执行docker logs mysql8看容器为什么退。如果日志里是端口绑定错误port is already allocated说明-p 3306:3306撞上了宿主机已有端口用ss -ltnp | grep 3306找出占用方或者改用-p 33061:3306这种非常见端口。如果日志里是架构不匹配exec format error检查宿主机 CPU 架构和镜像平台的匹配性此时docker run --help里的--platform参数就是你要的答案。如果确认原因后重新启动注意docker start mysql8和docker run --name mysql8不能混用——run 会再次撞上同名容器报冲突start 才是对的。这一步同样回到第 3 节说的命令边界问题。整个排查过程中help 并没有直接告诉你病根在哪但它保证了你的每一步操作都是按当前版本来执行的你可以放心地怀疑业务配置而不用怀疑命令写法本身。这条先按 help 校准操作 - 再看日志 - 再修配置的链路比漫无目的地重装 docker 高效得多。4.5 镜像拉取失败、磁盘空间与容器网络不通各查各的家底镜像拉不动、pull 超时、磁盘满这三个问题在现代 Docker 使用中几乎必经。磁盘满的时候docker pull会直接报 no space left on device或者 daemon 日志里出现类似信息。这时候先看家底docker system df # 查镜像、容器、卷、缓存分别占了多少 docker system df -v # 更细一层按对象列出这两个命令本身就在docker system --help里不需要去文档里翻。看完占用分布后再决定清理策略docker image prune清悬空镜像docker container prune清已退出的容器docker volume prune清理匿名卷各管各的比一把梭docker system prune -a --volumes -f安全得多。容器之间网络不通同样是高频问题。标准链路是先docker network --help看有哪些子命令再docker network ls看当前有哪些网络最后docker network inspect查看某网络的子网、网关和已挂载容器。大部分两个容器 ping 不通都是因为没把两个容器放到同一个自定义网络里而默认 bridge 网络并不是用来做容器间服务发现的。docker run --help里的--network参数就是从这里查出来的。关于镜像源网络质量的问题超出 help 范畴但你可以先用docker info看一下当前 Registry Mirrors 配置是否为空或异常再决定是修正配置还是换网络环境重试而不是同一个命令反复重试。提示遇到任何 connection reset by peer 或 timeout 类错误先确认宿主机网络和 registry 连通性再检查镜像源配置。help 能保证你的命令本身没写错但网络问题和镜像源问题需要由curl、ping、docker info这些工具交叉确认。5. 把 help 变成团队里的复用资产5.1 用管道过滤快速定位参数帮助文本太长不是问题问题是你不会过滤。Linux/macOS 下我常用这些docker run --help | grep -n restart # 找到 restart 相关参数 docker run --help | grep -A 1 -- --mount # 带上下文看参数说明 docker exec --help | grep -E user|workdir # 多个关键词Windows PowerShell 下的等价写法docker run --help | Select-String -Pattern restart另外docker help 子命令和docker 子命令 --help是等价的我习惯用后者因为手指不用反复切换位置。把 help 输出当作可检索的文本流而不是只翻不查的文档效率立刻不一样。要写 docker 命令的脚本时我的工作流是先敲docker 子命令 --help过滤确认参数名再写进脚本基本不会因为拼错参数名而导致脚本夭折。5.2 版本升级后用 help 校准旧习惯Docker 生态变过很多次名字docker ps依然存在但管理命令变成了docker container lsdocker-compose独立命令逐渐被docker compose插件取代多架构构建从普通docker build走向docker buildx build。如果你一直是从博客或旧脚本里学命令升级 Docker 后很容易遇到参数找不到了。我的建议是升级后花 10 分钟跑一遍顶部 help 和几个常用子命令的 help重点对比你平时用的参数还在不在。比如你习惯了docker run --gpus在旧版本或未安装 NVIDIA runtime 的环境里这个参数可能压根不在 help 里甚至直接报未知参数。又比如你的微服务项目一直在用docker-compose up -d升级后发现找不到命令docker compose --help会告诉你现在的入口是什么。这种差异只有当前机器的 help 能给你确定答案。5.3 团队里沉淀一份版本锁定的速查卡如果你的团队使用固定版本的 Docker可以把每个常用子命令的 help 输出导出成文本放到仓库的 docs 目录里docker run --help docs/docker-run-help-27.txt docker compose --help docs/docker-compose-help-27.txt docker system --help docs/docker-system-help-27.txt再把几个天天要用的别名沉淀到 shell 配置里alias drdocker run alias dpsdocker ps alias dcupdocker compose up -d alias dchelpdocker compose --help这样无论是 CI 脚本的维护者还是刚入职的新人都能在本地离线查到当前生产环境真实可用的参数集合而不是各自去网上搜。我所在团队就这么干过把docker run、docker compose、docker system三份 help 存进项目仓库每次升级 Docker 版本时同步更新减少了不少跨版本踩坑的口头沟通成本。6. 说点实话help 命令也有照顾不到的时候6.1 帮助文本不等于最佳实践help 只负责告诉你这个参数存在、语法是什么它不会告诉你这个参数在什么场景下该不该用。最典型的例子是docker run的-v和--mount两者在功能上高度重叠help 里都会列出但社区和官方文档在推荐--mount因为它语义更清晰、不容易踩-v的简写坑。而对新手来说-v更短更好记用起来也没毛病。这种该怎么选的问题help 回答不了只能靠实践经验和团队约定补上。另一个例子是--privileged。help 里它只是给容器扩展特权但实际用起来等于给了容器几乎宿主机级的权限。你要是图方便到处加--privileged后面安全审计一定会找你。help 不会拦你它只负责描述事实判断要自己来。6.2 某些参数的效果依赖 daemon 和宿主机docker run --help里有一堆参数你以为写完就能生效其实不一定。--gpus要宿主机有 GPU 和驱动--cgroupns要内核支持--memory-swap要宿主机开启了 swap accounting--device要看设备节点存不存在。这些依赖关系 help 不会提示报错也不一定直观。我处理这类问题的固定套路是先docker info看宿主机能力和 daemon 配置再决定用哪个参数。比如你想让容器用 GPU在 Linux 上先确认nvidia-smi能跑再去看docker info里的 Runtimes 是否包含 nvidia。如果 Runtimes 里根本没有那你把--gpus参数写成花也没用——问题在 daemon 侧。6.3 help 找不到答案时往这三个方向去第一man 页。部分 Linux 发行版会自带man docker-run比 help 详细不少能看到更完整的参数说明和历史背景。第二官方文档的 CLI 参考页尤其适合查某个参数默认值是什么这类 help 里没写细节的问题。第三本地源码或 GitHub 上的 CLI 仓库。这个属于进阶用法适合排查非常冷门的参数行为。但无论从哪个渠道拿到答案我最后都会回到本机 help 做一次版本核对避免照搬到另一个版本上直接翻车。说句个人体会收尾把先敲 help变成肌肉记忆是我觉得对新手性价比最高的一件事。它不能代替你理解容器原理也不能代替你修网络问题但它能保证你每一步操作都建立在当前版本的真实语法上把大量不确定性挡在门外。我教过的每个新同事我都建议他们从docker help开始而不是从收藏夹里的某篇教程开始。到现在这个建议还没让人失望过。
返回列表