
用过几年Docker之后你会发现一个规律真正高效的人不是背下了所有命令而是脑子里有一张清晰的“命令地图”——知道查什么、用什么、在什么场景下组合哪些命令。网上零零散散的Docker命令教程很多但大多是文档式堆砌看完记不住遇到问题还是抓瞎。这篇文章我把日常开发和运维中会高频用到的命令按职责拆成几个板块每个命令除了给语法还会解释背后的逻辑和踩坑点。不管你是刚接触容器的新手还是已经写了不少Dockerfile的老手都应该能从中找到一些有价值的东西。1. 先把Docker的命令体系搞清楚学习Docker命令最大的障碍不是命令多而是不知道命令之间是什么关系。我个人的划分方式是按“操作对象”来分而不是按“动词”来记镜像Image、容器Container、网络Network、数据卷Volume、编排Compose、系统System。这六个对象基本覆盖了所有日常操作。镜像构建、拉取、查看、删除、导入导出是容器的“模板”。容器创建、启动、停止、进入、日志、删除是真正跑起来的东西。网络容器之间怎么通信端口怎么映射自定义网络怎么建。数据卷容器删了数据还在这个靠volume。编排多容器一起管理本地就是Docker Compose。系统Docker本身的信息、资源占用、无主数据清理。这个思路梳理清楚之后命令就不再是零散的碎片了。查容器状态就用docker ps体系查镜像信息就用docker image体系每一个命令按docker 对象 动作的规律去推基本不会跑偏。值得多说一句的是Docker命令的很多参数是“全局通用”的比如-q表示只返回ID、-f表示按条件过滤、--format表示自定义输出模板。掌握这几个通用参数能省掉大量手写解析的麻烦。2. 镜像相关命令从拉取到推送上云2.1 拉取与查看别只盯着pulldocker pull是大多数人接触的第一个命令从仓库拉取镜像到本地。常见用法是docker pull nginx:1.24指定版本号很重要。很多人直接docker pull nginx拉latest结果过几天一看镜像更新了行为变了排查了半天发现是版本变了。查看本地镜像用docker images或者更完整的docker image ls。这里有一个很实用的技巧docker image ls --digests可以显示镜像的摘要信息当你在生产环境需要锁定某个精确版本时用digest比用tag更可靠。同一个tag可能被覆盖但digest是内容寻址的不会被篡改。另一个容易忽略的是docker image inspect用来看镜像的详细信息比如架构、系统、暴露的端口、默认命令等。排查“为什么这个镜像跑起来行为不对”的时候先inspect一下往往能找到答案。2.2 构建与标签管理构建是门手艺docker build是把Dockerfile变成镜像的命令日常用法是docker build -t myapp:v1.0 .。注意最后这个点它是构建上下文路径。很多人把这个路径理解为Dockerfile所在目录实际上它决定了哪些文件能被COPY进镜像。如果上下文路径太大构建会很慢所以用.dockerignore排除不需要的文件是必须的操作。构建时还有两个高频率参数--no-cache强制重新构建所有层--build-arg传递构建参数。我建议在CI流程中默认加缓存但本地排查诡异问题的时候--no-cache是第一步试错手段。docker tag用来给镜像打标签用法是docker tag myapp:v1.0 myregistry.example.com/dev/myapp:v1.0。它的本质不是复制镜像而是给同一个镜像加一个引用名。推送到远程仓库用docker push注意这里的坑如果你没有先tag成仓库地址格式push一定会失败这是新手最常见的报错。2.3 镜像清理与空间回收本地镜像越攒越多磁盘一下子满了。这时候docker image prune就派上用场了。不加参数时它只清理“悬空镜像”没有tag关联的加上-a会清理所有未被任何容器使用的镜像。加--filter until24h可以只清理24小时前的镜像这个在自动清理脚本里非常好用。docker rmi是手动删除指定镜像删除时需要先确认没有容器在用它。如果提示“image is being used by stopped container”说明有已经停止但没删除的容器仍然占用着镜像。执行docker container prune把停止的容器清掉再删镜像就顺利了。3. 容器生命周期管理从run到rm的完整闭环3.1 docker run参数就是生产力和事故源docker run是最强大的命令也是参数最多的命令。核心模式是docker run [选项] 镜像 [命令]。我按使用频率把选项拆分一下参数作用说明-d后台运行没有它容器在前台跑终端一关就停-it交互式终端进容器操作或调试时必备--name指定容器名不指定的话Docker会随机生成一个名字-p端口映射-p 8080:80表示宿主机8080映射到容器80-v数据卷挂载-v /data:/var/lib/data或是命名卷--network指定网络默认bridge生产建议自定义网络--restart重启策略unless-stopped是常用策略--env/-e注入环境变量配置密码、版本号等--rm退出后自动删除临时调试容器强烈推荐docker run --rm是我个人很推崇的一个参数。临时调试时加上它退出即清理不会留下一堆死容器占空间。但注意一点加了--rm的容器不能再和--restart一起用这是定义上的冲突。还有一个细节-p映射端口时如果宿主机端口被占启动会直接报错。我建议先用docker port或ss -lntp确认端口占用情况再启动别等报错了才排查。3.2 docker ps查看容器的正确姿势docker ps查看运行中的容器docker ps -a查看所有容器包括已停止的。这两个是基础但真正提升效率的是过滤docker ps -a -q只返回容器ID适合批量操作场景。docker ps -a --filter statusexited只看已退出的容器清理时配合rm使用。docker ps -a --filter nameredis按容器名模糊过滤。docker ps --format table {{.Names}}\t{{.Status}}\t{{.Ports}}自定义输出只显示关心的字段。我在维护一批容器时习惯用--format写一个固定模板一眼扫过去就知道哪个容器状态异常、哪个端口映射不对。3.3 启动、停止、重启与删除容器的生命周期命令很简单docker start、docker stop、docker restart、docker rm。docker stop会先给容器发SIGTERM信号等待一段时间默认10秒再发SIGKILL。如果你的应用优雅停机逻辑比较慢用docker stop -t 30手动指定等待时间避免进程被强杀导致数据损坏。这个参数很少人用但在数据库或消息队列容器上非常关键。docker rm删除容器默认只能删已停止的容器加-f可以强制删除运行中的容器。但我在生产环境不会轻易用-f它等同于直接kill可能会打断正在处理的请求。优雅的做法是先docker stop再docker rm。批量删除用docker rm $(docker ps -aq)可以一次清掉所有容器。这个组合在清理环境时很爽但也容易误删执行之前先跑一下docker ps -aq看看列表确认没有要保留的东西。3.4 进入容器的姿势对比exec与attach进入运行中的容器主流方式是docker exec -it container bash。它是在容器内起一个新进程执行完退出不影响容器主进程日常调试基本都用它。而docker attach是连接到容器当前的主进程。它的坑在于退出attach时可能一并终止容器主进程除非按CtrlPCtrlQ组合键detach。所以我的建议是平时调试一律用docker exec不要用attach。除非你要看主进程的标准输出交互否则attach的坑远多于收益。还有一种是docker run -it image sh直接启动一个新容器并进入shell。适合快速验证镜像内容比如查看镜像里的文件结构。因为加了--rm退出即销毁不占空间。4. 日志、进程与资源监控容器内部到底发生了什么4.1 查看日志docker logs的实用场景docker logs用来查看容器日志最常用的是docker logs -f --tail 100 container。--tail只看末尾100行-f持续跟随输出排障的时候比看文件高效得多。注意docker logs只能看到容器主进程写的标准输出和标准错误如果你的应用把日志写到了文件里而没有打出来docker logs是看不到的。这是一个常见误区很多人排查半天发现容器“没日志”其实是宿主机上日志文件在增长但容器没有把日志打到stdout。--since和--until可以根据时间过滤日志比如docker logs --since 2024-06-01T15:00:00 container看某个时间点之后的日志。这个在定位偶发问题时非常有用不用大海捞针翻全部日志。4.2 容器资源占用stats和topdocker stats展示容器的CPU、内存、网络I/O、磁盘I/O。不加参数时是实时刷新的加--no-stream可以只输出一次快照适合写脚本采集数据。这里有个容易被忽略的点docker stats显示的内存包括page cache实际应用内存可能比显示值小判断内存泄漏时要小心。docker top查看容器内进程用法和Linux的ps一致比如docker top container aux。它是直接查看容器内进程视图而不是宿主机的。当你想确认某个进程是不是在容器里运行、PID是多少时很有用。4.3 inspect与port信息洞察的利器docker inspect返回容器的完整配置和状态格式是JSON。直接看一长串JSON确实头疼我一般配合--format取字段docker inspect -f {{.State.Status}} container看容器当前状态。docker inspect -f {{.NetworkSettings.IPAddress}} container看容器IP地址。docker inspect -f {{json .Mounts}} container看挂载情况。--format用的是Go模板语法。刚开始记不住字段路径我建议先用docker inspect container查全量找到目标字段的位置再提炼出模板语句。docker port container显示容器端口映射关系。比如你用-p 8080:80启动了一个nginx跑docker port container就能看到本机8080对应的容器端口80。当端口访问不通时第一步就是检查这里确认映射是否真的生效。5. 网络与数据卷容器通讯和持久化的底层逻辑5.1 网络命令自定义网络才是正经玩法默认情况下Docker启动容器用的是bridge网络所有容器通过NAT访问外网容器之间通过IP直接互通。但bridge的缺点是不支持DNS自动解析容器重启后IP会变靠IP互相访问很不稳。正确做法是创建自定义网络docker network create mynet然后在启动容器时加--network mynet。自定义网络里的容器可以直接用容器名互相访问Docker内置了DNS解析。这个体验上的差距是非常明显的我在本地跑多容器应用时从来只用自定义网络。查看网络列表用docker network lsdocker network inspect mynet可以查看网络里连接了哪些容器以及它们的IP。容器加入或移出网络用docker network connect和docker network disconnect这个在做网络隔离调整时很实用。删除网络用docker network rm注意有容器连接时会被拒绝。5.2 数据卷容器删了数据不能没数据卷主要有三种形式命名卷、绑定挂载、tmpfs。命令上主要关注命名卷。创建命名卷docker volume create mydata查看卷列表docker volume ls查看卷详情docker volume inspect mydata删除卷docker volume rm mydata启动容器时挂载命名卷docker run -d -v mydata:/var/lib/data nginx。命名卷的优点是数据由Docker管理备份、迁移、跨容器共享都比较方便。绑定挂载则是-v /宿主机绝对路径:/容器路径直接在宿主机目录上读写适合开发场景改代码即时生效。这里有一个容易踩的坑容器里被挂载目录的原有内容会被隐藏。比如你把主机一个空目录挂载到容器/usr/share/nginx/html容器里原来的页面就看不到了因为目录被“覆盖”了。需要理解挂载的逻辑而不是惊讶“我的文件怎么不见了”。5.3 网络排查的基本套路容器之间网络不通是常见问题排查命令基本是这套组合拳docker network inspect mynet查看各容器是否在同一网络。docker exec -it container ping 其他容器名测试容器间连通性。docker exec -it container curl http://服务名:端口测试具体端口。docker port container确认宿主机端口映射是否正确。如果还有宿主机防火墙或云平台安全组规则挡路那是Docker之外的问题。6. Docker Compose与批量管理多容器不再手忙脚乱6.1 compose核心命令一条命令拉起整套环境当应用由多个容器组成时一个容器一个docker run可就太累了。docker compose用YAML文件描述服务、网络、卷一条docker compose up -d全部搞定。日常高频命令docker compose up -d启动所有服务-d后台运行。docker compose down停止并删除服务网络、容器默认不删数据卷。docker compose ps查看项目内服务状态。docker compose logs -f跟随查看所有服务日志。docker compose exec 服务名 bash进入某个服务的容器。docker compose restart重启所有服务。down有个重要变体docker compose down -v会把数据卷一起删掉。开发环境清理时很爽但如果里面有数据库数据执行前要三思。我见过不止一个人在测试库上执行down -v结果数据全没了。6.2 compose项目的常见参数docker compose up -d --build是日常开发时的高频操作先重新构建镜像再启动。这解决了“改了代码但镜像还是旧的”问题。docker compose ps --format table {{.Name}}\t{{.Status}}可以自定义输出看起来更清爽。docker compose up -d --scale api3可以快速扩展服务实例数配合负载均衡容器使用本地演示水平扩容时很方便。但注意如果你没有配置负载均衡或服务发现扩展出来的实例之间不会自动分担流量。7. 系统级维护与清理命令Docker本身也得管7.1 查看Docker系统状态docker version显示Docker客户端和服务端版本排障时先确认版本是否一致。docker info显示Docker引擎的系统信息包括存储驱动、Cgroup驱动、CPU/内存数量、镜像容器数量等。这两条命令在排查Docker自身问题时是第一步。docker system df类似于Linux的df显示镜像、容器、数据卷、构建缓存各自占用的磁盘空间。当你觉得“磁盘怎么莫名其妙满了”时先跑这个命令找元凶。7.2 prune全家桶一次清掉所有垃圾Docker长期使用会积累大量无主资源两个命令足够用docker system prune清理停止的容器、无用的网络、悬空镜像、构建缓存。docker system prune -a --volumes再进一步清理所有未使用的镜像和数据卷。--volumes这个参数尤其要注意它会把没被任何容器使用的命名卷一起删掉。如果卷里有重要数据这一下就全没了。我的经验是-a可以适当用--volumes除非确认卷都不需要否则别加。还可以按时间过滤docker system prune --filter until72h只看72小时前的垃圾这个参数在生产环境做定时清理时非常实用。8. 高频故障与排查笔记8.1 容器启动失败容器启动后立刻退出最常见原因是启动命令或入口脚本报错。排查步骤docker ps -a确认容器状态是Exited。docker logs container查看退出前日志90%的问题都能在这里看到。docker inspect -f {{.State.ExitCode}} container查看退出码。如果日志为空考虑是不是启动命令本身就写错了。用docker run -it image sh直接进容器手动跑启动命令能快速复现问题。8.2 端口冲突与网络不通启动时报“port is already allocated”时说明宿主机端口已被占用。用docker ps -a看看哪个容器占用了端口或者用ss -lntp | grep 端口确认是不是容器外的进程占用的。容器能启动但访问不通先检查docker port container看映射是否生效再检查容器内服务是否真的监听在正确的IP和端口上最后检查宿主机防火墙。8.3 镜像与空间问题docker pull出现“no space left on device”时先跑docker system df看看是哪类资源占满了。镜像缓存和悬空镜像通常是最大元凶docker system prune能释放大量空间。如果还不行可能需要检查Docker根目录所在文件系统的扩容方案。8.4 常用退出码速查退出码含义常见原因0正常退出服务主动结束或被正常stop1一般错误启动命令执行失败、配置不对137被信号9杀掉内存资源耗尽或手动强制kill143被信号15终止docker stop优雅停机默认信号125Docker自身错误容器启动过程异常如加载镜像失败126命令无法执行命令不存在或没有执行权限让我自己在实际使用中印象最深的一个教训是别在数据卷和镜像上偷懒别随意对运行中的容器执行-f强删。Docker的命令体系并不难难的是养成“先查文档、再查日志、最后动手”的习惯。命令大全类的文章只能帮你快速定位工具真正决定你能不能用好Docker的是你对镜像分层、容器生命周期、网络模型这几块底层逻辑的理解。把这篇文章里的命令串起来跑一遍再结合自己的项目场景做几次实战演练比单纯背命令有用得多。最后再分享一个小技巧把高频使用的命令组合写成Shell别名或小脚本比如一键清理无用容器、一键查看所有容器资源占用。刚开始会觉得多此一举等你管理几十个容器、每天重复同样操作时就知道节省的时间有多可观。