ARTICLE DETAIL

资讯详情

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

Docker 常用指令速查:从镜像管理到容器编排一册搞定

Docker 常用指令速查:从镜像管理到容器编排一册搞定 Docker 用了这么多年被问得最多的往往不是“怎么安装”而是“装完了下一步敲什么”。说实话Docker 的单条指令并不难难的是脑子里缺一张命令地图什么时候该拉镜像什么时候该起容器容器起来之后怎么进去改配置、怎么拷贝文件、怎么把玩坏的容器删掉重来。这篇 Docker 常用指令速查手册就是按这个思路整理的。不管你是在 Windows 上刚把 Docker Desktop 装起来的新手还是从微服务、K8s 方向转过来想补容器基础的同学把这套指令捋顺了至少能少走七八成弯路。先说明一下这份手册不是照搬官方文档而是我这些年实际操作中“用得多、踩过坑、回头查”的命令集合。每条命令我都会交代它为什么存在、什么时候用、有什么容易翻车的地方。毕竟容器这东西真正降低心智负担的不是命令本身而是你对“镜像、容器、网络、数据卷”这几个概念的理解方式。1. 先建立一张 Docker 命令心智图1.1 镜像、容器、仓库到底在说什么很多人一开始学 Docker 就被这三个词绕晕。我习惯用一个比方镜像就像是装系统的安装光盘或者模板它只负责定义“这个环境里预装了什么、默认执行什么”容器就是拿这张光盘启动出来的“正在运行的机器”同一个光盘可以启动多台机器每台机器的运行时状态互不影响仓库就是专门放光盘的公共货架你要用哪个镜像就从货架上取下来pull用完了还可以把改动重新打包成新镜像push放上去。把这三个概念区分开Docker 的指令其实就分成了三条线管镜像的、管容器的、管仓库的。再加上数据卷、网络、Compose 编排这几条辅助线整张命令地图就清晰了。1.2 命令格式与帮助信息是最后的救命稻草任何命令吃不准时最先该敲的不是搜索引擎而是帮助信息docker --help docker run --help docker compose --helpdocker --help会列出所有一级子命令docker run --help则告诉你某个具体命令支持哪些参数。我这些年养成的习惯是想不起来参数先--help连不上服务先docker version和docker info。这两个命令能很快定位是客户端问题还是服务端问题。比如 Windows 上 Docker Desktop 启动失败时docker version通常会出现“客户端正常、服务端连不上”的提示问题基本就锁定在后台引擎没起来而不是你命令敲错了。另外docker info能看到 Docker 的存储驱动、镜像数量、容器数量、是否开启了 Swarm 模式等信息排查环境问题时的价值很高。2. 镜像管理先有好料才能做好菜2.1 拉取镜像从仓库拿东西的几种姿势最常用的三条命令docker search mysql docker pull mysql:8.0 docker pull mysqldocker search用于在镜像仓库里搜索可用镜像适合不确定有没有官方镜像时快速确认。docker pull则是把指定镜像拉到本地。这里必须提醒一句默认的latest标签是个“移动靶”。同一个latest今天拉的版本和一个月后拉的版本可能完全不同。凡是用于生产环境或有明确版本依赖的场景都建议显式指定版本号比如mysql:8.0.40、redis:7.4、ubuntu:22.04这样后续排障能复现、能回溯。再补一个细节如果你的机器是 ARM 架构比如苹果的 M 系列芯片、树莓派或者反过来是 x86 架构默认拉取的是当前平台对应的镜像。万一在 ARM 机器上拉了一个只有 x86 的镜像运行时会报exec format error。遇到这种情况可以用docker manifest inspect查看镜像支持的平台列表然后按需加--platform参数例如docker pull --platform linux/amd64 openjdk:172.2 查看与清理本地镜像docker images docker image ls -a docker inspect 镜像ID docker rmi 镜像ID或镜像名docker images是最常用的列出本地镜像的命令能看到仓库名、标签、镜像ID、创建时间和大小。docker image ls -a会额外显示中间层镜像排查磁盘占用时很有用。docker inspect用于查看镜像或容器的底层 JSON 配置包括环境变量、EntryPoint、暴露端口等这个命令排障时经常用到。清理镜像用docker rmi但要注意如果某个镜像还有容器在用即使是已停止的容器直接删会报错。解决方案是先找到关联容器删掉或清理掉容器后再删镜像。批量清理悬空镜像没有标签且没有被容器引用的镜像可以用docker image prune加-a会删除所有未被使用的镜像清理效果更强但要把本地重要镜像先确认一遍别误删。2.3 构建与导入导出让镜像能复现、能迁移docker build -t myapp:1.0 . docker commit 容器ID myapp:1.0 docker save -o myapp.tar myapp:1.0 docker load -i myapp.tardocker build是基于 Dockerfile 构建镜像这是推荐方式因为 Dockerfile 记录了构建步骤别人拿到就能复现。docker commit是把一个正在运行的容器的当前状态打包成新镜像应急时有用但不推荐作为日常构建手段——它相当于把“手工改过的系统”直接做成了镜像后期根本说不清里面改了什么。docker save和docker load是“打包镜像文件 导入镜像”的组合适用于内网环境离线迁移比如你在测试机上构建好镜像拷到生产机上load进去。3. 容器生命周期跑起来、看状态、清理掉3.1 用 docker run 起一个容器参数是你和 Docker 的“合同”docker run -d --name mysql8 -p 3306:3306 -e MYSQL_ROOT_PASSWORD123456 -v /data/mysql:/var/lib/mysql mysql:8.0这条命令是上手最常用的组合式命令。拆开看-d后台运行而不是卡在前台刷日志。不加-d的话CtrlC 退出时容器也会被终止。--name给容器起个固定名字后续操作都免去查容器ID的麻烦。-p 宿主机端口:容器端口把容器内端口映射到宿主机。外部访问3306时实际连的是宿主机端口再由 Docker 转发给容器。-e传入环境变量。MySQL 镜像正是靠MYSQL_ROOT_PASSWORD来初始化 root 密码的不同镜像的-e参数差异很大用之前先看镜像文档。-v 宿主机目录:容器目录挂载数据卷。这是容器数据持久化的核心我把数据卷单独放在后一章节细讲。排障时还有一个常用参数--rm容器停止后自动删除适合临时跑测试命令或调试工具。docker run --rm -it ubuntu:22.04 bash这条命令启动一个 Ubuntu 容器并直接进入交互式 shell退出后容器自动删掉不留垃圾。对只想“临时体验下某个镜像”的场景非常好用。3.2 查看容器状态docker ps 不只是列列表docker ps docker ps -a docker statsdocker ps只看正在运行的容器docker ps -a连已退出的也显示。已停止的容器不会自动消失会一直占用磁盘空间这也是为什么很多人用了一阵 Docker磁盘莫名被占满。docker stats实时显示每个容器的 CPU、内存、网络和磁盘 IO 占用排查“哪只容器拖垮了宿主机”时非常直观。有一类常见误区是容器状态是 Exited 但不明白为什么退出。这时要看退出码和日志而不是反复docker start。退出码 0 表示正常结束137 多半是被 OOM Kill 或手动 Kill1 或非 0 要看应用日志。3.3 进入容器内部exec 和 attach 的区别docker exec -it 容器名 bash docker attach 容器名docker exec是在运行中的容器里额外启动一个进程比如启动一个 bash。它的特点是在 bash 里敲exit只是退出这个交互进程不会影响容器本身。而docker attach是连接到容器的主进程直接看主进程的标准输入输出按 CtrlC 很可能会把容器主进程也杀掉。日常调试我基本只用exec不太碰attach。容器里没装 bash 的可以试试shdocker exec -it nginx sh另外调试前建议先看日志docker logs -f 容器名-f是 follow 模式持续跟踪日志输出和tail -f效果差不多。3.4 停止、启动、删除别让容器堆积成山docker stop 容器名 docker start 容器名 docker restart 容器名 docker rm 容器名 docker rm -f 容器名停止和删除是两个动作。docker stop给容器发停止信号容器可以安全收尾docker rm是删除容器文件已停止的容器也会占磁盘空间。docker rm -f是强制停止并删除慎用。批量清理场景比较常用的一组命令docker stop $(docker ps -q) # 停止所有容器 docker rm $(docker ps -aq) # 删除所有容器包括已退出把命令组合嵌套在$( )里是 Shell 基本功初次接触的读者可以理解成“先执行括号里的把结果当参数传给外层命令”。3.5 资源限制别让一只容器吃掉整台机器docker run -d --name app --cpus 1.5 -m 1g nginx--cpus限制容器最多使用几个 CPU 核心-m限制最大内存。在很多小主机或旧机器上比如 N100 这种低功耗平台同时跑十几个容器时资源限制就特别重要。不限制的话任何一个容器内存泄漏都可能把宿主机拖到 SSH 都连不上。经验值每个容器先给-m 512m或-m 1g看监控再调整而不是一开始就放开跑。4. 数据卷与网络容器最容易被忽略的两块4.1 数据卷容器删了数据不能跟着没容器的文件系统是“临时”的。容器被删除后内部产生的文件默认会跟着容器一起消失。所以凡是数据库、日志、配置、上传文件这一类需要长期保存的数据都要通过数据卷挂载到宿主机目录。docker run -d --name mysql8 -v /data/mysql:/var/lib/mysql mysql:8.0/data/mysql是宿主机目录/var/lib/mysql是容器内 MySQL 的数据目录。容器删了重建只要挂载同一个宿主机目录数据就还在。这就是“删容器不删数据”的机制。除了刚才用的绝对路径挂载方式Docker 还提供“具名卷”docker volume create mysql-data docker run -d --name mysql8 -v mysql-data:/var/lib/mysql mysql:8.0具名卷的好处是目录由 Docker 统一管理不用关心宿主机上的具体路径备份和迁移也方便。两个容器需要共享数据时可以同时挂载同一个卷或同一个宿主机目录。日常我建议临时测试用绝对路径挂载正式项目用具名卷因为具名卷配合docker compose管理更顺手。4.2 自定义网络容器之间通信的正确姿势默认情况下Docker 创建一个叫bridge的桥接网络所有容器都在这个网络里可以互相访问但依赖动态分配的 IP容器重启后 IP 可能变化。跨主机或需要稳定访问时更好的做法是创建自定义网络docker network create app-net docker run -d --name redis --network app-net redis:7.4 docker run -d --name app --network app-net myapp:1.0在同一个自定义网络里容器可以直接用“容器名”作为主机名互相访问。app 容器访问 redis 时直接连redis:6379即可不再依赖动态 IP。这个特性在搭建 Redis 主从、微服务集群等场景下非常实用。另外--network host模式会让容器直接使用宿主机网络没有独立 IP通常不建议除非你对网络性能有极端要求或者容器本身需要监听大量随机端口。4.3 端口映射与网络排查常用命令docker port 容器名 docker network inspect app-netdocker port查看容器的端口映射关系docker network inspect查看网络里所有容器的 IP、网关等信息排查网络问题时这两条命令很有用。进入容器后优先用curl或wget测试连通性因为很多精简镜像里连ping都没装第一反应是ping不通就判定网络有问题往往会把排查方向带偏。5. 编排与运维从单容器走向一整套服务5.1 Docker Compose用一份 YAML 管一整套服务单容器用docker run足够但一个项目往往要同时跑 MySQL、Redis、后端应用、前端等多个容器。逐条敲docker run不仅容易漏参数且没法统一管理。Docker Compose 就是干这个的把服务定义写在一个docker-compose.yml里一条命令拉起所有服务。一个非常典型的最小示例services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: 123456 volumes: - mysql-data:/var/lib/mysql ports: - 3306:3306 backend: build: ./backend ports: - 8080:8080 depends_on: - mysql volumes: mysql-data:核心命令docker compose up -d docker compose down docker compose ps docker compose logs -f docker compose configup -d按 YAML 定义创建并启动服务down停止并删除容器和网络。config用于校验 YAML 语法和最终解析结果改动配置后建议先跑一遍能省不少启动报错的排查时间。depends_on只控制启动顺序不保证依赖服务“已就绪”比如 MySQL 容器起来了但初始化还没完成后端可能连接失败。生产环境需要更可靠的等待逻辑比如健康检查。新版 Docker 已经内置 Compose 插件所以直接docker compose不需要单独安装docker-compose。5.2 日常运维日志、监控、磁盘清理docker logs -f 服务名 docker stats docker system df docker system prune -adocker system df能统计镜像、容器、数据卷和构建缓存各占了多少磁盘空间是我排查“磁盘满了”问题的第一站。docker system prune -a会清理所有未使用的镜像、容器、网络和构建缓存清理效果非常明显但前提是你确认不再需要这些内容。注意清理不包含“正在使用”的镜像和容器所以相对安全但构建缓存删了之后下次构建会变慢需要权衡。顺手提醒一个在 Windows 上很常见的问题Docker Desktop 的磁盘占用会越来越大因为 WSL2 的虚拟磁盘文件ext4.vhdx只会膨胀不会自动收缩。即使你各种prune磁盘占用可能还是高。这时候需要手动压缩 vhdx 文件方法是在 PowerShell 里执行wsl --shutdown然后用diskpart或Optimize-VHD压缩。这类操作建议搜一下当前版本的具体步骤但核心思路是“先停 WSL再收缩磁盘”。5.3 进阶场景GPU 容器与构建辅助需要跑深度学习或大模型推理镜像时常在docker run里加docker run --gpus all --ipchost --name vllm-server vllm/vllm-openai:v0.27.1--gpus all让容器访问宿主机所有 GPU 设备。前提是宿主机已经装好 NVIDIA 驱动以及 nvidia-container-toolkit否则会报找不到 GPU 设备。--ipchost在部分 PyTorch 推理场景下能避免共享内存不足的报错。这类镜像通常体积很大首次拉取建议预留足够磁盘空间。打包镜像时除了命令行docker build在 IntelliJ IDEA 里可以借助 Docker 插件直接在 IDE 中构建和推送镜像适合 Java 项目。但底线一样最终绕不开 Dockerfile 的编写质量。6. 常见问题排查与避坑速查6.1 Docker Desktop 启动失败virtualization support not detectedWindows 上启动 Docker Desktop 最常见的报错是 “Docker Desktop failed to start because virtualisation support wasn‘t detected”。这通常不是 Docker 本身的问题而是虚拟化能力没开或没生效。排查路径按顺序来进 BIOS/UEFI确认 CPU 虚拟化Intel VT-x 或 AMD SVM已开启。检查“启用或关闭 Windows 功能”里Hyper-V和适用于 Linux 的 Windows 子系统WSL2是否勾选。确认默认版本是 WSL2可在 PowerShell 执行wsl --set-default-version 2。如果电脑里装了 VMware 或 VirtualBox注意它们和 Hyper-V 可能冲突必要时按官方文档调整。大部分“启动 Docker 失败”的报错按这个顺序排查基本都能解决。如果你机器上确实关着 Hyper-V那docker version会提示连接不上服务端问题同样指向这里。6.2 Permission denied while trying to connect to the Docker APILinux 上不加sudo执行docker ps报权限错误原因是一般用户不在docker用户组内。解决办法sudo usermod -aG docker $USER newgrp dockernewgrp docker让当前会话立即生效免去重新登录。这里提醒一句加入 docker 组相当于获得近似 root 的权限因为 Docker 可以挂载宿主机目录所以只给可信用户加组别图省事给所有人都放进去。6.3 服务启动失败failed to start docker application container engine这类报错往往出现在 Docker 引擎启动阶段。先说排查思路先看引擎日志。Linux 上通常是systemctl status docker journalctl -u docker -n 100常见原因包括磁盘空间不足、iptables 规则冲突、之前异常退出导致的数据损坏。如果日志里出现bridge-nf-call-iptables相关问题通常是防火墙或内核网络参数配置导致需要检查宿主机的/etc/sysctl.conf和 iptables 规则。这类问题环境相关性强日志是关键别靠猜。6.4 镜像拉取慢或下载失败拉镜像卡在等待输出时大概率是网络到默认镜像仓库的链路不够顺畅。常见优化手段在 Docker Desktop 的 Settings 或/etc/docker/daemon.json里配置可用的镜像加速地址Windows 上直接修改配置文件后重启引擎。拉取时加--platform参数避免拉取到不需要的多架构镜像减少传输量。检查下Docker Desktop是不是处于运行状态以及本地 DNS 是否正常。DNS 解析异常也会导致拉取超时。注意改daemon.json后必须重启 Docker 引擎才生效。Linux 上执行systemctl restart dockerWindows 上重启 Docker Desktop 即可。6.5 容器内网络不通一条典型排查路径docker ps确认容器状态是 Up。docker exec -it 容器名 sh进入容器curl目标地址。如果目标在另一个容器里确认两个容器是否在同一个自定义网络内。默认 bridge 里也可以用 IP 访问但 IP 重启后会变化。docker inspect 容器名查看网络信息确认 IP、网关、网络模式。有个特别容易踩的坑默认 bridge 网络里的容器可以通过--link相互访问但--link是老机制新项目一律建议用自定义网络。我见过很多 redis 主从搭不起来最后发现是容器在不同网络里互相连不上。6.6 容器频繁重启或退出码异常容器一直重启最有效的工具是日志docker logs 容器名退出码 137 大概率是内存超限被系统杀掉先在docker stats看实际占用再调整-m限制。应用本身报错的比如数据库初始化失败、配置文件路径不对日志里会直接显示之后修正配置重建容器即可。容器如果配置了--restartalways但本身一直报错会产生高频重启建议先去掉该参数调试稳定后再加。6.7 磁盘占用突然异常上升docker system df看哪些对象占空间通常是这三类悬空镜像、构建缓存、旧容器可写层。处理方式docker image prune -a docker builder prune docker container prune以上都属于清理类命令执行前确认容器和数据卷都被正确挂载和备份。数据卷占用的空间通过prune不会清理需要手动删卷比如docker volume prune。但删卷等于彻底删数据务必先备份。最后分享一点我自己的日常习惯用了几年 Docker我慢慢形成的纪律是构建镜像一律走 Dockerfile绝不用docker commit做“快照镜像”凡是有状态的服务一律挂数据卷绝不依赖容器可写层多容器项目无论多简单都上 Compose哪怕只是两个服务。这样做的最大好处是“可重来”——删掉重建、换机器部署都只是一条命令的事不会因为某个容器的临时状态被绑死。另外我习惯在 Shell 里加几条 alias日常操作会顺手很多alias dpsdocker ps --format table {{.Names}}\t{{.Status}}\t{{.Ports}} alias dlogsdocker logs -f --tail 100 alias dprunedocker system prune -a --volumes这几条别名看着简单但每天能省下很多重复输入的时间。如果你刚开始接触 Docker建议先把pull/run/ps/exec/logs/rm这六条命令练熟再慢慢扩展等遇到真实项目时Compose、网络、数据卷这些内容自然会串起来。
返回列表