18附录:命令速查

命令速查
按主题汇总全系列出现过的命令。同一条命令往往在好几关里反复出现,所以这里只收一处,正文在用到时链到对应小节。
上下文
| 命令 | 作用 |
|---|---|
docker context ls | 列出所有上下文,带 * 的是当前在用的那个 |
docker context use <名字> | 切换当前上下文 |
docker --context <名字> <子命令> | 只对这一条命令指定上下文,不动全局设置 |
容器生命周期
| 命令 | 作用 |
|---|---|
docker run hello-world | 最简的一次运行:拉镜像、建容器、跑一次、退出 |
docker run -d -p 8080:80 nginx | 后台运行一个容器,把宿主机 8080 转发到容器的 80 |
docker ps | 列出运行中的容器 |
docker ps -a | 连已停止的容器一起列出 |
docker start <容器> | 启动一个已停止的容器 |
docker stop <容器> | 停止一个运行中的容器 |
docker restart <容器> | 重启容器 |
docker rm <容器> | 删除容器 |
docker rm -f <容器> | 强制删除,运行中的也能删 |
docker rename <容器> <新名字> | 改容器名,运行中或已停止都能改,不用重启 |
运行时的参数
| 命令 | 作用 |
|---|---|
docker run -d --name <名字> <镜像> | 给容器指定名字;不指定则随机生成一个,用名字或 ID 指代容器都可以 |
docker run --hostname <名字> <镜像> | 指定主机名;不写就是容器 ID。容器名(--name)和主机名是两回事,内建 DNS 两个都登记 |
docker run --rm <镜像> | 容器退出后自动删除 |
docker run -e 名字=值 <镜像> | 用环境变量改掉镜像的默认行为,要传几个就写几遍 |
docker run -v 宿主路径:容器路径 <镜像> | 把宿主机的目录或文件接到容器里,顺序是「宿主<容器>容器>」 |
docker run -v 宿主路径:容器路径:ro <镜像> | 同上,但容器里只能读不能改 |
docker run <镜像> <命令> | 覆盖镜像默认启动的那个程序(顶掉的是 CMD) |
docker run --entrypoint <程序> <镜像> | 连 ENTRYPOINT 一起换掉,而不只是换 CMD |
日志与进入容器
| 命令 | 作用 |
|---|---|
docker logs <容器> | 查看容器主进程的输出 |
docker logs -f <容器> | 持续跟随输出 |
docker inspect --format '{{.LogPath}}' <容器> | 看这个容器的日志文件落在哪(在虚拟机里) |
docker run --log-opt max-size=10m --log-opt max-file=3 <镜像> | 给日志设上限:单文件最大 10m,最多留 3 个 |
docker exec -it <容器> bash | 在运行中的容器里另起一个进程,通常是开一个交互式终端 |
进程与信号
| 命令 | 作用 |
|---|---|
docker top <容器> | 列出容器里跑着的进程 |
docker stop -t <秒> <容器> | 改那个宽限期;默认 10 秒,-t 0 直接发 SIGKILL |
docker kill <容器> | 直接发 SIGKILL,不给商量的余地 |
docker kill -s <信号> <容器> | 发指定信号,发完就走,不等 |
镜像
| 命令 | 作用 |
|---|---|
docker login [仓库] | 登录仓库,不写就是 Docker Hub;正经场景用 access token 而不是账号密码 |
docker logout [仓库] | 退出登录 |
docker pull <镜像> | 把镜像从仓库拉到本地 |
docker tag <镜像> <新名字> | 给同一个镜像再挂一个名字,不复制镜像 |
docker push <名字:标签> | 把镜像推到仓库;名字要带上仓库里的路径,否则不知道往谁那儿推 |
docker images | 列出本地已有的镜像 |
docker rmi <镜像> | 删除镜像,前提是没有容器还引用着它 |
docker inspect <镜像或容器> | 打出完整的配置,包含镜像的默认值与这次运行实际用的值 |
docker inspect --format '{{.State.ExitCode}}' <容器> | 只取一个字段,不用在整段 JSON 里翻;{{json .Config.Env}}、{{json .Mounts}} 同理 |
构建镜像
| 命令 | 作用 |
|---|---|
docker build -t 名字:标签 . | 用当前目录的 Dockerfile 构建;末尾的 . 指的就是当前目录,材料都从这儿取 |
docker build --no-cache -t 名字:标签 . | 不用缓存,每次都从零重来 |
docker build --target <阶段> . | 多阶段构建里,只建到指定阶段为止 |
docker builder prune | 清掉构建缓存 |
docker history <镜像> | 列出这个镜像是一层层怎么来的 |
docker commit <容器> <新镜像> | 把容器当前的改动冻成一个新镜像(不推荐当常规手段) |
卷与数据
| 命令 | 作用 |
|---|---|
docker volume create <名字> | 建一个卷 |
docker volume ls | 列出所有卷;看起来像一长串随机字符的是匿名卷 |
docker volume inspect <名字> | 看这个卷在磁盘上的位置 |
docker volume rm <名字> | 删卷,前提是没有容器在用它 |
docker volume prune | 清掉所有没被使用的卷(不问就删) |
docker run -v 卷名:容器路径 <镜像> | 把卷挂进容器 |
docker run -v 容器路径 <镜像> | 只写一边 → Docker 自动建一个匿名卷 |
docker run --tmpfs 容器路径 <镜像> | 挂一块内存盘,不落磁盘,容器一停就没 |
网络
| 命令 | 作用 |
|---|---|
docker network ls | 列出所有网络;bridge、host、none 是自带的三张 |
docker network create <名字> | 建一张自定义网络 |
docker network inspect <名字> | 看这张网里有谁、各自的 IP |
docker network connect <网络> <容器> | 把容器接上网络,运行中的也能接 |
docker network disconnect <网络> <容器> | 摘下来 |
docker network rm <名字> | 删网络,前提是没有容器还挂在上面 |
docker network prune | 清掉没有容器在用的网络(不问就删) |
docker run --network <名字> <镜像> | 起容器时直接接上某张网络 |
docker run --network host <镜像> | 容器不单独隔离网络——但 macOS 上那个「host」是虚拟机,见第 5 关 |
Compose
| 命令 | 作用 |
|---|---|
docker compose up -d | 按当前目录的 compose.yaml 后台拉起整个项目,缺的镜像先拉 |
docker compose down | 停并删掉项目的容器和它自动建的网;卷不删 |
docker compose down -v | 连文件里声明的卷一起删,数据就没了 |
docker compose ps | 只看这个项目的容器,STATUS 一列带 (healthy) 这类健康状态 |
docker compose logs -f <服务> | 跟踪输出,不写服务名就是整个项目 |
docker compose exec <服务> <命令> | 在某个服务里另起一个进程,服务名就是文件里的键 |
docker compose config | 校验并打印合并后的完整配置(叠了多份文件时,用它看最后长什么样) |
docker compose -f a.yaml -f b.yaml up -d | 按顺序叠多份文件,后面的覆盖前面的 |
docker compose --profile <名> up -d | 连同这个 profile 的服务一起起;可写多遍,或用 "*" 全开 |
docker compose up -d <服务> | 只起点名的那个服务;就算它的 profile 没激活也会起 |
Compose 常用字段
正文用到的字段(image、ports、environment、volumes、depends_on、healthcheck、profiles)在各关讲过。下面这些同样常用,只是还没轮到,写到对应关再展开:
| 字段 | 作用 |
|---|---|
build: . | 不用现成镜像,就地按 Dockerfile 构建 |
command: / entrypoint: | 覆盖镜像的启动命令,相当于 docker run 的 <命令> 和 --entrypoint |
restart: unless-stopped | 重启策略:no(默认)/ on-failure / always / unless-stopped |
env_file: .env | 从文件读环境变量,一行一个 名字=值 |
container_name: <名字> | 固定容器名(默认是 <项目>-<服务>-<序号>);名一固定,这个服务就不能起多个副本 |
networks: | 显式定义、接入网络;不写就用项目自建的那张 |
secrets: | 敏感数据,以文件形式挂在 /run/secrets/<名字>;只支持 Linux 容器 |
deploy: | 资源上限、副本数等;哪些键本地 docker compose 认、哪些只给 Swarm,看官方参考 |
logging: | 日志驱动与上限,如 max-size、max-file(为什么要限制,第 11 关讲) |
完整字段清单见官方 Compose file reference。
系统与清理
| 命令 | 作用 |
|---|---|
docker version | 分别列出客户端与服务端的版本 |
docker info | 列出服务端的详细信息(存储、内核、内存等) |
docker system df | 查看镜像、容器、卷、构建缓存各占多少空间 |
docker system df -v | 同上,再列出每一项具体是谁 |
docker container prune | 清掉已停止的容器 |
docker image prune | 清掉悬空镜像;加 -a 连没被任何容器引用的镜像也清 |
docker system prune | 清理未使用的容器、网络与悬空镜像 |
docker system prune -a | 连未被引用的镜像与构建缓存一起清理 |
docker system prune -a --volumes | 再加一样:连没在用的卷也清 |
用法备忘
这些不是命令,是命令里那些容易记反、记漏的地方。
带冒号的参数,两边都是「宿主机在前,容器在后」——-p 宿主:容器(端口同理)和 -v 宿主:容器 一个规矩。
-v 的第一段决定它是路径还是卷名:
/开头是绝对路径,./、../开头是相对当前目录的路径;- 不是这两种开头的(如
mysql-data:/var/lib/mysql),会被当成卷的名字(见前面「卷与数据」); ~由 shell 展开,所以不能写进引号——-v "~/x:/y"会把字面量~传给 Docker,开头不是/,于是被当成卷名而报错。
:ro 是 Linux 挂载的 read-only 选项(mount -o ro 的那两个字母),写在末尾让容器里只能读。对称的 :rw 是默认值,一般不用写。这套挂载只对那一个容器可见,宿主机的目录树不变。
docker build 末尾的那个 . 指的就是当前目录,不是 Dockerfile 的位置。COPY 只能从当前目录里拿东西,而这里面的东西随时可能被复制进镜像——不想要的用 .dockerignore 挡掉(写法同 .gitignore)。目录里东西多时这一步也可能变慢;守护进程跑在本机时不一定全传,但「可能被复制进镜像」永远成立。
-t 名字:标签:冒号前是名字、后是标签;不写标签就是 latest(那个陷阱见第 10 关)。一个镜像可以挂多个「名字<标签>标签>」。
latest 不是「最新」,只是「没写标签时的默认值」——它随时会变,指向哪由最后一次推送决定。生产用明确版本(1.0、提交号),别用它。想看「绝对跑的是这一份」,用 digest:nginx@sha256:...,由内容算出来、变一个字节就变,天生不可变。
镜像名的完整结构:[仓库地址/]命名空间/名字:标签。省掉前两段时默认是 Docker Hub 加你自己的账号;官方镜像的命名空间是 library(所以 nginx 就是 docker.io/library/nginx)。
构建会复用上次的层——每条指令算一个指纹(RUN 是命令本身,COPY 是文件内容),没变就打 CACHED;一变,它后面所有层一起重做,不是只有那一条。所以 Dockerfile 里不会变的放前面、会变的放后面。
COPY --from=<阶段> 源 目标 从另一个阶段(或另一个镜像)的文件系统里拷文件——多阶段构建靠它把编译产物挑出来、把编译工具留在门外。
VOLUME 声明过的目录,docker run 时会自动生成匿名卷,哪怕一个 -v 都没写——这是僵尸卷的一大来源。
三种挂载怎么选:要长期留住、要交付给别人 → 卷;开发时改文件、要能用编辑器直接看到 → 绑定挂载;不该落盘的临时东西 → --tmpfs。卷住在虚拟机里(docker volume inspect 能看到位置),绑定挂载就是你磁盘上的一个目录——所以 macOS 上绑定挂载慢一截。
备份一个卷:开一个临时容器,同时挂上「要备份的卷(:ro)」和「宿主机上一个落地的目录」,在里头 tar。两个 -v 少一个都不行;打包时加 -C 卷里的路径,否则包里会带上绝对路径。
-it 两个参数缺一不可:-i 保持输入,-t 分配终端,少一个就没有交互。
docker stop 和 docker kill 不是一回事——stop 先发 SIGTERM 再等(默认 10 秒),等不到才 SIGKILL;kill 默认直接 SIGKILL,-s 可换信号但同样不等待。
信号只发给容器里的 1 号进程,不会挨个通知。真正干活的程序想收到信号、想优雅退出,它自己就得是 1 号——ENTRYPOINT 脚本结尾的 exec、以及 CMD 用数组写法而不是整句话交给 shell,都是为了让它顶上 1 号。
想无条件钻进任何镜像,用 --entrypoint sh——它在 Docker 这一层直接换掉 ENTRYPOINT,不看镜像自己怎么写。直接用 docker run -it <镜像> sh 不保证有效:镜像名后面那个位置的含义由镜像决定,有的镜像把它当「要跑的程序」启动,有的只当「参数」。
docker network ls 里三张自带网的差别,在 DRIVER 那一列:bridge(驱动 bridge)搭一台虚拟交换机,是容器默认接的那张;host(驱动 host)不给容器单独建网络、直接用宿主机的;none(驱动叫 null)什么都不搭。自己建的网络驱动也是 bridge——所以「默认 / 自定义」的差别不在驱动,在有没有内建 DNS(下一条)。
容器名能被解析,靠的是内建 DNS,不是默认网络——默认网络(bridge)不做名字解析:它的 /etc/resolv.conf 指向宿主机 DNS,里面没有容器名;自定义网络里 /etc/resolv.conf 是 nameserver 127.0.0.11,那是 Docker 内建的 DNS,容器名就登记在它那儿。所以容器之间要用名字互相访问,得先接上同一张自定义网络。
判断名字解析对不对,看 getent hosts <名字>,别看 curl 通不通——两者不是一回事。
host.docker.internal 是容器里指回宿主机的名字(Docker Desktop 提供),容器要访问宿主机上的服务就用它。
-p 在 macOS 上等于 Docker Desktop 在宿主机上占住了那个端口——lsof -nP -iTCP:<端口> -sTCP:LISTEN 看到的是 com.docker.backend(Windows 用 netstat -ano | findstr :<端口>)。不写 -p,这个端口在宿主机上就不存在。
compose 的服务名就是容器之间互相叫的名字,网络也不用自己建——compose 自动建一张 <项目名>_default 网,项目名默认是 compose.yaml 所在目录的名字。挂载写命名卷,卷要在文件末尾的顶层 volumes: 里声明。
depends_on 只管顺序,不管就绪——它只等对面跑起来,不等它能应答。要等真的就绪,得给对面写 healthcheck,再用 condition: service_healthy(还有 service_started、service_completed_successfully)。start_period 是开头宽限期,这期间的失败不计数,专治启动慢的服务。
叠多份文件,后一份覆盖前一份,但按条目类型分:单值项(image、command)直接换;键值项(environment、labels)按键名合并;挂载(volumes)按容器路径合并;而 ports、expose 是累加,不是替换——以为第二份文件写了新端口就顶掉了旧的,是错的。拿不准就先 docker compose config 看合并结果。文件名叫 compose.override.yaml 时会被自动叠上,不用写 -f。
profile 只控制「起不起」:没写 profiles 的服务永远起,写了的一律默认不起,得 --profile <名> 激活。点名 docker compose up -d <服务> 可以绕过 profile 直接起。down 默认不碰带 profile 的服务。
容器主进程写进 stdout/stderr 的东西,Docker 全接住存成文件——路径用 docker inspect --format '{{.LogPath}}' <容器> 看(在跑引擎的那台机器上),docker logs 读的就是它。默认没有上限,话多的容器能把磁盘写满。设上限:单次用 --log-opt,或全局改守护进程配置 daemon.json 的 log-opts(Linux 是 /etc/docker/daemon.json,Docker Desktop 走 Settings → Docker Engine。改完重启,只对新容器生效)。轮转的代价是旧日志会被丢。
prune 不碰正在跑的容器的日志,也不治根——缓存会再攒、匿名卷会再造。它是扫帚不是堵源头:真办法是日志设上限、.dockerignore、RUN 里装完就清。
macOS 上 prune 释放的空间不一定立刻还给硬盘——Docker Desktop 的磁盘镜像是只长不缩的。
退出码直接说明「怎么死的」:0 正常结束;1 程序报错;125 docker run 自己参数错;126 命令不可执行;127 命令找不到;137 被 SIGKILL(128+9,常见于内存超限或 stop 超时);143 被 SIGTERM(128+15)。
Connection refused 和 Connection timed out 是两回事:前者说明到了那台机器、只是端口上没人在听(服务没起 / 没就绪 / 端口写错);后者说明包根本没到(网络不通)。
docker inspect 不用整段读:Config.Cmd、Config.Entrypoint 看启动配置;Config.Env 看最终环境变量(镜像默认值和你 -e 的合并);Config.ExposedPorts 看端口;Mounts 看挂载;State.ExitCode、State.Error、State.OOMKilled 看死因。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!





