
1. Docker 到底是什么为什么你必须掌握这些命令先说句大实话Docker 这玩意儿已经不是什么新鲜技术了但直到今天我依然能看到不少开发者和运维同事在终端里敲命令时一脸茫然靠复制粘贴过日子。复制粘贴本身没问题问题是很多人根本不知道自己粘贴的是什么出了问题也不会排查只能去搜索引擎碰运气。Docker 本质上解决的是“环境一致性”问题。以前你遇到最多的场景是什么本地代码跑得好好的一到测试环境就崩测试环境好了生产环境又出幺蛾子。原因无非就是环境依赖不同、系统库版本不同、配置参数有差异。Docker 把应用连同它的运行环境一起打包成镜像用一个容器把应用隔离起来运行镜像走到哪里运行环境就走到哪里。开发者本机、测试服务器、生产服务器只要 Docker 引擎在跑出来的效果就是一致的这个价值在微服务架构和 DevOps 实践里体现得尤其明显。对于刚接触 Docker 的人来说最友好的学习路径不是先啃操作系统原理、也不是死记容器编排概念而是先把日常使用频率最高的命令跑熟镜像怎么拉、容器怎么起、日志怎么看、端口怎么映射、目录怎么挂载、容器怎么进去、怎么停止删除。我今天把这些命令从使用频率、核心逻辑、底层原理到实操案例完整拆一遍再加上我真实踩过的坑和排查经验看完你至少能应付日常工作中九成以上的场景。这篇内容适合谁刚接触 Docker 的新手想系统梳理命令体系的人以及那些用 Docker 但总靠搜索解决问题的开发者。不用怕基础差我会把每个命令背后的逻辑讲清楚。2. 环境准备与 Docker 引擎起步2.1 Docker 安装的关键逻辑在正式玩转命令之前先把基础环境搞定。Windows、macOS、Linux 的安装方式有差异但核心逻辑是一样的Docker 是 C/S 架构你敲命令接触的是 Docker CLI 客户端真正干活的是 Docker Engine 守护进程。CLI 负责把命令发给守护进程守护进程负责创建容器、管理镜像、维护网络和数据卷。Linux 上安装 Docker 最常用的是官方脚本或 apt/yum 源curl -fsSL https://get.docker.com | bash装完以后记得把当前用户加进 docker 用户组不然每次都需要 sudosudo usermod -aG docker $USER加完组以后注销重新登录一次才能生效。这一步很多人忽略结果每次敲 docker 命令都要带 sudo烦得很。Windows 和 macOS 上建议直接用 Docker Desktop它会帮你打包好引擎和 CLI还能在系统托盘上直观看到引擎状态。不过有一类坑很典型Windows 上启动 Docker Desktop 时提示“Virtualization support not detected”或者“WSL 2 kernel update”之类的报错。前者是因为 BIOS 里没开启虚拟化需要重启进 BIOS 把 Intel VT-x 或者 AMD-V 打开后者通常需要执行一条命令更新 WSL2 内核。Docker Desktop 的“Settings → Resources → WSL Integration”里可以设置与哪个发行版集成想用命令行工具链的朋友建议勾上。验证安装是否成功用一个命令就够docker version这个命令会同时输出客户端和服务端版本信息。关键是看 Server 部分有没有内容。如果只有 Client 信息、Server 位置为空大概率是引擎没启动或者当前 shell 连不上守护进程。这是我在无数新人电脑上反复见到的现象先检查引擎别急着重装。2.2 启动与自启动设置Linux 下安装完 Docker 后引擎默认不是开机自启的需要手动设置sudo systemctl enable --now docker sudo systemctl status dockerWindows 上 Docker Desktop 则是在应用设置里勾选“Start Docker Desktop when you sign in”这个选项默认是关闭的。很多人的容器配置了 restartalways以为重启机器后容器会自动恢复结果发现 Docker 引擎根本没起来自然就白搭了。启动完了再跑一次docker version看到 Server 部分有版本号环境就算 OK 了。接下来进入正题命令的核心体系。3. 镜像管理命令拉取、查看、删除与构建3.1 拉取镜像的细节与镜像源镜像Image是容器的模板容器是镜像的运行实例。这句话是整个 Docker 命令体系的地基。拉取镜像的命令是docker pulldocker pull nginx:latest docker pull mysql:8.0 docker pull redis:7.2格式就是docker pull 仓库名:标签。标签不写默认是latest但这恰恰是个坑latest不是稳定版本它指的是最新推送到仓库的版本你两个月前拉的和现在拉的可能是两个完全不同的镜像生产环境千万别依赖latest。我自己的习惯是永远指定明确的版本号。镜像从哪里拉默认从 Docker Hub 拉。国内网络环境下 Docker Hub 的速度偶尔让人崩溃解决办法是配置国内镜像加速器。在 Linux 上修改/etc/docker/daemon.json{ registry-mirrors: [https://docker.m.daocloud.io] }改完重启 Dockersudo systemctl restart dockerWindows 上 Docker Desktop 在“Settings → Docker Engine”里直接编辑 JSON 配置效果一样。这里提示一句镜像加速器只对 Docker Hub 上的官方镜像有效不影响第三方源的拉取。3.2 镜像查看、删除与清理拉下来的镜像怎么管理最常用的是这三条docker images docker image ls docker image rm 镜像ID或名称docker images和docker image ls功能一样前者是旧写法后者是新版推荐写法。输出里的IMAGE ID是镜像的唯一标识删除时写前几位字符就行Docker 支持前缀匹配。删除镜像有个前置条件如果这个镜像被某个容器使用了直接删会报错。要么先删除容器要么用-f参数强制删但强制删的后果是那个容器虽然还在跑却变成了“无镜像可追溯”的状态这种孤儿容器后期很难维护所以能用正常方式就别用-f。清理孤儿镜像和无用缓存推荐这条docker system prune它会把所有停止的容器、无用的网络、悬空镜像和构建缓存一起清掉。如果连运行中的容器相关缓存也想清加-a参数。但这条命令一旦执行就是不可逆的我建议执行前先用docker system df看一下占用情况做到心里有数。3.3 构建镜像的常用姿势构建镜像是进阶内容但既然讲命令就不能略过。最简单的构建命令docker build -t myapp:1.0 .-t指定镜像名和标签.指定 Dockerfile 所在目录的构建上下文。构建上下文这个概念很多人不理解简单说就是 Docker 引擎会把当前目录打包发送给守护进程Dockerfile 里用到的文件必须在上下文目录内COPY 和 ADD 指令只能访问上下文里的文件。下一层是docker commit可以把一个容器的当前状态保存成新镜像docker commit 容器名 myapp:backup这个方法用来做临时快照还可以但绝对不推荐作为正式构建方式。因为用 commit 生成的镜像包含容器内部的所有历史变更体积会膨胀而且不具备可重复性——同一份代码在不同时间 commit 出来的镜像内容可能有差异。正确姿势永远是写 Dockerfile用docker build构建。Dockerfile 每一行指令对应镜像的一个新层有缓存机制构建一次以后未改动的层可以直接复用缓存构建速度会快很多。这个缓存优化技巧在企业项目里能省不少时间。镜像管理命令用一张表总结操作命令备注拉取镜像docker pull 镜像名:标签标签务必明确版本列出镜像docker images也可用docker image ls删除镜像docker image rm 镜像ID容器占用时需先删容器构建镜像docker build -t 名称:标签 .注意构建上下文磁盘占用docker system df查看镜像/容器/缓存占用整体清理docker system prune -a慎用不可逆容器转镜像docker commit 容器名 新镜像名不建议正式使用4. 容器生命周期管理最核心的命令群4.1 启动容器的完整参数讲解容器命令是整个 Docker 使用中最频繁的部分。启动一个容器的基础命令是docker rundocker run -d --name my-nginx -p 8080:80 nginx:latest这一条命令拆开来看-d后台运行模式。不加的话容器在前台运行日志会直接刷在当前终端CtrlC 后容器就停了。--name my-nginx给容器起个名字方便后续管理。不起名字的话 Docker 会随机生成一个像happy_curie这样的名字管理起来很崩溃。-p 8080:80端口映射。宿主机的 8080 端口映射到容器的 80 端口。格式是宿主机端口:容器端口。这个参数是容器对外提供服务的关键访问本机 8080 端口就等于访问容器里的 nginx。nginx:latest使用哪个镜像。docker run最容易被忽视的本质是它等于先创建容器再启动容器是docker createdocker start的组合。docker create创建一个容器但不启动docker start启动已存在的容器。这种设计让 Docker 可以灵活地“先准备环境再择机启动”。启动容器时还有个实际开发中很常用的参数-itdocker run -it ubuntu:22.04 /bin/bash-i表示保持标准输入打开-t表示分配一个伪终端。两个组合起来才能得到一个可以在交互模式下使用的 shell。这条命令在国外社区和各类 Docker 教学里都是高频场景很多人做实验时就用它进一个临时容器里执行各种测试命令。4.2 查看容器的运行状态容器启动完之后第一件事是确认它是否真的在运行docker ps输出里能看到容器 ID、镜像、启动命令、创建时间、当前状态、端口映射、容器名。这个命令通常加两个参数docker ps -a # 查看所有容器包括已停止的 docker ps -l # 查看最近一次创建的容器开发过程中用得最多的是docker ps -a。因为容器程序一旦崩溃退出docker ps就看不到了不加上-a就很难判断刚才那个容器到底是因为什么退出是报错了还是正常结束。如果容器运行有问题看 DNS 解析错没错、端口映射通不通、进程活着没docker ps -a后面还要配一个检查状态的命令docker inspect 容器名它输出一大坨 JSON 格式的配置信息包含网络配置、挂载卷、环境变量、健康检查状态等。用jq工具可以提取关键字段docker inspect my-nginx | jq .[].NetworkSettings.IPAddress拿到 IP 地址后可以绕开端口映射直接访问容器内网地址。4.3 停止、重启与删除容器容器生命周期管理的完整命令集docker stop 容器名 # 优雅停止给容器一段缓冲时间 docker kill 容器名 # 强制杀掉不等缓冲 docker restart 容器名 # 重启容器 docker rm 容器名 # 删除容器只能删已停止的 docker rm -f 容器名 # 强制删除运行中的容器也能删这里解释一个细节docker stop和docker kill的区别。stop 先发送 SIGTERM 信号给容器主进程让进程自行清理资源然后退出等待一个宽限期默认 10 秒超时后再发 SIGKILL。kill 则直接发 SIGKILL不给任何善后时间。数据库这类有状态应用能用 stop 就不用 kill强制杀掉可能导致数据不一致。删除容器时如果容器还在运行docker rm会报错必须先用docker stop停止再删除或者直接docker rm -f一把梭。-f实际逻辑是先发送 SIGKILL 再删除用起来方便但同样不建议对有状态应用滥用。批量清理已停止的容器我不建议一条条删用这条更高效docker container prune它会一次性把所有已停止的容器全部删掉运行中的不受影响。日常操作最常打错的一个组合是docker restart与docker start。前者等于先 stop 再 start后者只启动已存在但处于停止状态的容器不要搞混。我见过好几个同事在容器部署更新后明明改的是配置结果敲的是 restart 而不是重新 run 新镜像验证半天发现改的内容完全没进容器里因为容器还是旧的。4.4 进入容器的几种方式排查问题最常用的操作就是进容器内部看看。进入运行中容器的方式主要有三种docker exec -it 容器名 /bin/bash docker attach 容器名 docker exec -it 容器名 sh第一种是日常排查最常用的。exec是在容器里面新起一个进程和当前容器的内部环境完全隔离——你的 shell 进去之后不会影响容器里的主进程。第二个attach是把当前终端直接连接到容器的主进程上效果堪比直接看进程 stdout/stderr但如果主进程不支持交互会让你不舒服而且退出时容易把主进程带停掉。生产环境里我几乎不用 attach都是 exec 进入一个独立的 shell这更安全。有些精简镜像里没有 bash只有 sh所以进容器时先试 bash没有就试 shdocker exec -it 容器名 sh这个细节在实际操作里特别常见。镜像为了控制体积很多基于 Alpine Linux 的镜像不带 bash只有 busybox 提供的 sh 环境。4.5 日志查看与跟踪容器里应用输出到标准输出的内容会统一被 Docker 收集用docker logs查看docker logs 容器名 docker logs -f 容器名 # 实时追踪输出 docker logs --tail 200 容器名 # 只看最后200行 docker logs --since 5m 容器名 # 只看过去5分钟-f参数是我用得最多的调试时开着它看应用日志实时刷新。加--tail是因为完整日志可能很长几万行刷出来终端会卡住。有一个关键点docker logs只能查看容器主进程输出到 stdout/stderr 的内容。应用把日志写到容器内文件里的话Docker 默认收集不到需要配置日志驱动方案如 json-file、gelf、fluentd 等或者直接挂载日志目录到宿主机上查看。很多新手以为日志文件在/var/log里面就一定能用 docker logs 看到这是个误区。5. 数据卷与网络配置让容器数据不丢、服务能通5.1 数据卷挂载的三种方式容器是沙箱容器一删除里面的数据就跟着蒸发。数据库容器、缓存容器这种有持久化需求的服务必须使用数据卷Volume或者目录挂载bind mount。最常用的两种挂载方式docker run -d --name mysql8 -v /my/mysql-data:/var/lib/mysql mysql:8.0 docker run -d --name nginx -v /home/user/html:/usr/share/nginx/html nginx第一种是宿主机目录直接绑定到容器目录。用绝对路径把宿主机的/my/mysql-data挂载到容器的/var/lib/mysqlMySQL 进程写数据就是在写宿主机目录容器删了再新建一个指定同一个路径数据直接回来。第二种是匿名卷/命名卷方式不过上面写法是 bind mount。命名卷的正确写法docker volume create mysql-data docker run -d --name mysql8 -v mysql-data:/var/lib/mysql mysql:8.0命名卷由 Docker 自己管理在宿主机上默认存放于 Docker 的数据目录里你不用关心具体物理路径。和 bind mount 相比命名卷更安全跨平台兼容性更好Docker 官方也推荐用命名卷。但 bind mount 有一个好处是路径完全可控适合需要手动备份日志、手动查看数据文件的场景。挂载目录时最常踩的坑是权限错乱。容器内进程的 UID 和宿主机的 UID 不是一个人你新建的目录权限可能不允许容器内的 mysql 用户写入。处理办法是保证目录属主和容器内进程 UID 一致或者简单粗暴chmod 777——但生产环境慎用这个方案。查看挂载情况docker inspect 容器名 | jq .[].Mounts可以看到每个挂载的源路径、容器内路径以及读写模式。5.2 端口映射与跨容器通信容器内部是一个独立的网络命名空间默认情况下宿主机访问不到容器内部。想让外部能访问容器服务两个办法端口映射或者网络互联。端口映射就是前面提到的-pdocker run -d --name web -p 80:80 -p 443:443 nginx-p可以写多次按需映射多个端口。宿主机端口可以留空Docker 自动分配一个高位随机端口docker run -d --name web -p 80 nginx跑完之后docker ps显示的端口那栏会出现0.0.0.0:32768-80/tcp这种形态32768 是宿主机上自动分配的端口。两个容器之间通信用得最多的方案是自定义网络docker network create my-net docker run -d --name app --network my-net my-app docker run -d --name db --network my-net mysql:8.0同一个网络里的容器可以直接用容器名互相访问不需要知道对方 IP。这是因为 Docker 自带的 DNS 解析机制——同一个用户自定义网络里的容器名会被自动注册到内部 DNS 服务器上。这个方案比 link 机制更现代也是 compose 文件的默认通信方式。查看网络信息docker network ls docker network inspect my-net5.3 宿主机网络模式与性能场景有几种特殊网络模式下性能差异很大bridge默认模式容器通过虚拟网桥 NAT 访问外网。host容器直接使用宿主机网络栈没有端口映射概念性能损耗最小。none容器没有网络完全隔离。什么时候用 host 模式应用对网络性能敏感或者需要绑定大量端口的时候。比如某些监控采集服务或者游戏服务器直接--network host跑性能最好。但要付出代价容器里的服务监听端口等于直接在宿主机上监听多实例部署时端口冲突问题会很头疼。6. 容器编排、容器日志与生产环境扩展6.1 用 docker-compose 管理多容器应用生产环境里一个应用往往是多个容器协作前端容器、后端容器、数据库容器、缓存容器。用docker run一条条启动肯定不行既要记住端口映射、数据卷、环境变量又要保证启动顺序命令长到让人崩溃。dokcer compose 是解决这个痛的方案现在的官方定义已改为docker compose老命令docker-compose也兼容version: 3 services: web: image: nginx:latest ports: - 8080:80 volumes: - ./html:/usr/share/nginx/html db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root123 volumes: - mysql-data:/var/lib/mysql volumes: mysql-data:启动命令docker compose up -d查看状态与停止docker compose ps docker compose logs -f docker compose downcompose 的价值在于把服务定义变成代码版本化可复用。一个 mysql redis 后端 前端 的完整环境一条命令全部起起来这在本地开发和测试环境搭建时效率提升是肉眼可见的。注意docker compose down默认不删除数据卷数据保留在volumes里。如果想把数据卷一起删掉加-v参数。这个参数我在日常操作里踩过一次坑以为 down 就清理干净结果旧数据还在后面的测试全是脏数据。反过来想正是因为 down 不删卷误操作时才有一个后悔的机会。6.2 日志、进程与资源监控排查容器状态时常用的还有docker top 容器名 # 查看容器内进程信息 docker stats # 实时查看所有容器CPU/内存/网络占用 docker stats --no-stream # 单次输出不持续刷新 docker events # 查看Docker事件流docker stats非常实用。容器内存泄露问题在图像上看得肉眼看不出但docker stats能显示每个容器的内存使用趋势。如果内存持续增长不释放基本可以断定应用有内存泄漏。6.3 Docker 青龙与依赖管理近年来很多自动化、定时任务的玩家会用到一套叫“青龙管理面板”的方案常见做法就是把青龙跑在 Docker 容器里。涉及镜像拉取、容器创建、依赖安装核心命令依然是这一套docker pull whyour/qinglong:latest docker run -d --name ql -p 5700:5700 -v /data/ql:/ql/data whyour/qinglong:latest但这里有个高频坑进入容器内部安装依赖和执行任务时很多人发现容器里缺这缺那Python 环境、Node 环境、系统工具全没有。因为你用的镜像本身只包含运行面板所需的最小子集你需要在容器里手动补齐依赖。最常见操作是docker exec -it ql sh进去之后安装 nodejs、python3 等组件或者直接在面板后台的“依赖管理”里安装。用容器跑这类自动化任务时建议把需要长期保留的数据放到挂载目录里容器升级重建时数据不会丢。Docker 青龙这类场景最有价值的实践是把任务脚本和依赖都做到 Dockerfile 里构建成自己的镜像这样每次启动就是完整环境不用每次都手动装依赖。这一步做完容器的“环境一致性”优势才算真正发挥到极致。6.4 镜像仓库与推送容器化项目真正落地到团队协作时还有个绕不开的话题镜像仓库。打包好的镜像怎么分享给同事怎么部署到服务器答案是推送到私有仓库。构建镜像并推送docker tag myapp:1.0 myregistry.com/library/myapp:1.0 docker push myregistry.com/library/myapp:1.0docker tag给镜像重新打标签。镜像标签的格式是仓库地址/命名空间/镜像名:版本。推送之前必须先 tag让镜像名符合仓库地址规则。很多团队用 Harbor 或 Nexus 做私有镜像仓库部署到内网服务器上跨机器拉取镜像就变成内部网络传输速度快很多。服务器上拉取时可能还需要先docker login认证。这里补充一个镜像体积优化的概念push 到仓库前用docker system df检视一下镜像是不是过度膨胀。能用 alpine 系基础镜像就别用 ubuntu 系编译产物多的用多阶段构建瘦身一个小技巧是.dockerignore文件里排除本地依赖文件和中间产物。这些都是我在 GitLab CI 流水线里实打实验证过的经验。7. 日常故障排查与高频报错实录7.1 Docker 引擎层面的报错现象一执行任何 docker 命令都报Cannot connect to the Docker daemon at unix:///var/run/docker.sock。排查步骤确认 Docker 守护进程是否在运行sudo systemctl status docker不在运行就启动sudo systemctl start docker如果启动失败查看日志sudo journalctl -u docker -n 100现象二Windows 上 Docker Desktop 启动时报虚拟化相关错误。这通常意味着 BIOS 的虚拟化开关没开或者 WSL2 内核不兼容。重启进 BIOS 开启 VT-x 或者 AMD-V然后以管理员身份运行wsl --update。如果你忘了我上文的组号命令这里也会卡在一个“daemon 连不上”的循环里无法自拔。现象三镜像拉取超时或下载极慢。配置 registry-mirrors 加速器重启引擎后重试。有些企业内网有特殊网络策略可能还需要配置 HTTP 代理。总之这一步是我在国内环境里最常给同事解决的一个问题。7.2 容器启动失败排查docker run启动完马上退出docker ps看不到容器只有docker ps -a能看到 Exited 状态。核心排查手段就一招看日志。docker logs 容器名 docker logs --tail 100 容器名常见的退出原因端口被占用宿主机 8080 被别的进程占用、应用缺少环境变量直接崩溃、容器里挂载的目录权限不对导致无法写入、启动命令和镜像默认命令冲突。MySQL 容器起不来的一个高频原因是数据目录权限问题宿主机挂载目录属主是 root容器内 mysql 用户写不进去。解决方案是让目录属主改为 999 或 1000对应 mysql 镜像的 UID或者chmod -R 777——测试环境可用生产环境不建议。镜像启动时的环境变量记得写作--env或-e参数。MySQL 容器必须配置MYSQL_ROOT_PASSWORD之类才会真正启动初始化流程否则只是启动了一个什么都不干的空进程。7.3 网络不通的排查思路容器网络不通是最折腾人的问题之一排查思路要沿着“网络层”一步步剥先确认容器是否在运行docker ps -a再确认端口映射是否配置正确docker port 容器名然后在宿主机测试连通性curl http://localhost:8080再进容器内部测试docker exec -it 容器名 curl http://localhost:80最后检查防火墙与安全组有一种常见情况是容器能 ping 通网关但无法访问外网。排查 DNS 问题用docker exec -it 容器名 cat /etc/resolv.conf如果 DNS 指向 127.0.0.11 表示使用 Docker 内置 DNS那要对齐宿主机网络偏好指向 8.8.8.8 表示直接系统 DNS要看运营商那块通不通。多数网络问题都能被这条思路覆盖到。7.4 数据卷与镜像空间问题容器长期运行不清理数据卷和镜像缓存会越积越多终于有一天磁盘满了。排查命令docker system df docker system df -v如果发现悬空镜像占了几十 GB清理方案docker image prune docker image prune -aimage prune -a会把所有没有被容器使用的镜像全部删掉包括你将来可能要用但还没 pull 的版本。执行之前我强烈建议先docker images扫一眼确认哪些是留存底稿。磁盘空间紧张时docker system prune -a加docker builder prune一样别手滑。7.5 日志排查速查表症状排查命令常见原因容器Exiteddocker logs 容器名启动命令执行失败、端口占用镜像拉不动docker images 加速器配置网络问题、镜像名写错端口访问不了docker psdocker port端口映射没配、防火墙拦截数据丢失docker inspect 容器名Mounts忘记挂载数据卷容器网络不通docker execping 外网DNS配置、跨网段路由8. 一些真实经验和最后的建议用 Docker 这几年我最大的体会是命令本身不值得死记真正要理解的是容器、镜像、数据卷、网络这几个概念之间的关系。命令只是操作这些概念的工具而已。你理解了“容器是镜像的实例、删容器不影响数据卷、同一个网络里容器名就是主机名”这几个底层逻辑大多数命令都是推理出来的根本不需要背。再分享几个我从实际项目中沉淀下来的习惯。第一所有容器必须指定版本标签一律不写latest。这个习惯能让你在镜像升级后不至于因为行为差异而崩溃也让回滚有了明确参照。第二生产环境容器一律配置--restartalways或者restart: always。应用崩溃后 Docker 能自动拉起省去半夜收到告警再爬起来敲命令的痛苦docker run -d --restartalways --name my-app my-app:1.0第三用 compose 管理一切多容器应用。即使只是本地的 redis mysql我也写 compose 文件原因不是省命令输入而是让环境声明变得可见、可版本化、可复现。你三个月后回来再看一份 compose 文件能立刻唤起整个环境的所有细节而一组docker run命令的话当时怎么敲的已经想不起来了。第四镜像体积控制要从源头做起。基础镜像选 Alpine编译型语言用多阶段构建.dockerignore生效且完整。很多团队的仓库里躺着 3 GB 的镜像拉取慢、启动慢、占用磁盘多实际上里面一堆构建缓存和静态文件减去这些体积能削掉三分之二。第五定期执行docker system prune和docker builder prune进行清理但要先检查时间和预留镜像。Docker 命令体系不复杂一个下午就能把常用命令全部过一遍。真正拉开差距的从来不是背了多少命令而是遇到问题时的排查思路——日志第一配置第二网络第三权限第四。按这个顺序排查几乎能解决日常遇到的九成容器问题。剩下的那一成多看看官方文档的 FAQ通常也比到处问人有收获。