云原生学习笔记(六) Docker 常用基础指令

233 阅读22分钟

Docker 常用基础指令可以分为几个类别:镜像管理容器管理网络与数据管理Dockerfile 构建相关 等。以下是常用命令及简要说明,适合作为学习笔记或速查手册使用。


📦 镜像管理相关

命令说明
docker images列出本地所有镜像
docker pull <镜像名>从远程仓库拉取镜像
docker rmi <镜像ID或名>删除镜像
docker build -t <镜像名:标签> .使用 Dockerfile 构建镜像
docker tag <镜像ID> <新标签>给镜像打标签
docker save -o xxx.tar <镜像名>将镜像保存为 tar 包
docker load -i xxx.tar从 tar 包加载镜像

🔍 docker images(完整形式:docker image ls

  • 作用:列出本地所有镜像。

  • 别名docker image ls 是正式写法,docker images 是简写形式。

  • 常用参数

    • -a, --all:显示所有镜像(包含中间层镜像)
    • --digests:显示镜像摘要(SHA256)
    • --filter, -f:按照条件筛选(如 dangling=true)
  • 示例

    docker images
    docker image ls -a
    docker image ls --filter "dangling=true"
    

⬇️ docker pull <镜像名>

  • 作用:从远程镜像仓库(默认 Docker Hub)拉取镜像。

  • 语法补充

    docker pull <镜像名>:<标签>
    
  • 示例

    docker pull nginx
    docker pull python:3.10-slim
    
  • 说明

    • 默认拉取 latest 标签;
    • 如果镜像来自私有仓库,需登录后操作:docker login

🗑️ docker rmi <镜像ID或名>(完整形式:docker image rm

  • 作用:删除本地镜像。

  • 常用参数

    • -f, --force:强制删除(即使镜像被容器使用)
  • 示例

    docker rmi nginx
    docker image rm nginx:1.19
    docker rmi -f 镜像ID
    
  • 注意事项: 删除前确保镜像未被任何容器引用(docker ps -a 查看)。


🛠️ docker build -t <镜像名:标签> .(完整形式:docker buildx build

  • 作用:根据当前目录下的 Dockerfile 构建镜像。

  • 推荐使用docker buildx build 是新版多平台构建入口。

  • 常用参数

    • -t:指定镜像名称与标签
    • -f:指定 Dockerfile 路径
    • --platform:构建目标平台(如 linux/amd64, linux/arm64)
    • --push:构建后直接推送镜像到远程仓库
  • 示例

    docker build -t myapp:latest .
    docker buildx build --platform linux/amd64 -t myapp:v1 .
    
  • 建议: 本地简单构建使用 docker build 即可,跨平台构建推荐使用 docker buildx build


🏷️ docker tag <源镜像> <新标签>

  • 作用:给已存在的镜像打新标签(类似于重命名/版本号切换)

  • 示例

    docker tag nginx myrepo/nginx:custom
    docker tag myapp:latest registry.example.com/myapp:1.0.1
    
  • 说明: 打标签不会创建新的镜像副本,仅是指向同一个镜像 ID。


💾 docker save -o xxx.tar <镜像名>(完整形式:docker image save

  • 作用:将镜像导出为 .tar 文件,便于离线传输或备份。

  • 参数

    • -o:输出文件路径
  • 示例

    docker save -o nginx.tar nginx:1.21
    
  • 说明: 可导出多镜像:

    docker save -o apps.tar app1 app2
    

📂 docker load -i xxx.tar(完整形式:docker image load

  • 作用:从 .tar 文件中加载镜像回 Docker 本地。

  • 参数

    • -i:指定输入文件
  • 示例

    docker load -i nginx.tar
    
  • 说明: 加载后镜像会出现在 docker images 中。


📦 容器管理相关

命令说明
docker ps列出运行中的容器
docker ps -a列出所有容器(含停止)
docker run <镜像>创建并运行一个容器
docker run -it <镜像> /bin/bash进入交互式终端容器
docker start <容器ID>启动容器
docker stop <容器ID>停止容器
docker restart <容器ID>重启容器
docker rm <容器ID>删除容器
docker exec -it <容器ID> bash在运行中容器内执行命令
docker logs <容器ID>查看容器日志

🚟 docker ps

说明 列出当前所有正在运行的容器。

别名/全名

  • docker container ls(官方推荐全名)

示例

docker ps
docker container ls

输出示例

CONTAINER ID   IMAGE         COMMAND                  CREATED         STATUS         PORTS                    NAMES
a1b2c3d4e5f6   nginx:latest  "nginx -g 'daemon of…"   2 hours ago     Up 2 hours     0.0.0.0:80->80/tcp       webserver

ℹ️ docker ps -a

说明 列出所有容器,包括运行中和已停止的。

别名/全名

  • docker container ls -a

示例

docker ps -a
docker container ls -a

🚙 docker run <镜像>

说明 创建并启动一个新容器,基于指定的镜像,执行默认命令。

别名/全名

  • docker container run

示例

docker run ubuntu

此命令会拉取 ubuntu 镜像(若本地没有),创建容器并运行默认命令(一般是 bashsh)。


👟 docker run -it <镜像> /bin/bash

说明 创建并启动一个容器,进入该容器的交互式终端(TTY),通常用于调试或手动操作。

参数说明

  • -i 保持 STDIN 打开
  • -t 分配伪终端

示例

docker run -it ubuntu /bin/bash

运行后,会进入容器内的 bash 交互终端。


▶️ docker start <容器ID>

说明 启动已创建但当前处于停止状态的容器。

别名/全名

  • docker container start

示例

docker start a1b2c3d4e5f6

⏹️ docker stop <容器ID>

说明 优雅停止一个正在运行的容器,默认会发送 SIGTERM 信号,允许容器正常退出,超过默认时间后强制终止。

别名/全名

  • docker container stop

示例

docker stop a1b2c3d4e5f6

🔁 docker restart <容器ID>

说明 停止并立刻启动一个容器,相当于 stop 后紧接 start

别名/全名

  • docker container restart

示例

docker restart a1b2c3d4e5f6

docker rm <容器ID>

说明 删除一个已经停止的容器。若容器运行中需要先停止才能删除,或使用强制删除参数。

别名/全名

  • docker container rm

示例

docker rm a1b2c3d4e5f6
# 强制删除运行中容器(不推荐)
docker rm -f a1b2c3d4e5f6

🏃‍♂️‍➡️ docker exec -it <容器ID> bash

说明 在运行中的容器内执行命令,并且以交互终端方式进入。常用于进入容器调试或运行额外命令。

别名/全名

  • docker container exec

docker exec 深度解析:连接容器的不止是 Bash,还有更多场景

docker exec 允许我们在正在运行中的容器中执行命令,是日常调试、运维、日志查看、动态配置的强大工具。但这条命令的真正威力远不止“进入容器执行命令”这么简单。


一、基本用法:在运行容器中执行命令

docker exec -it mycontainer bash
  • -i:保持标准输入流(interactive)
  • -t:分配伪终端(tty)
  • mycontainer:容器名称或 ID
  • bash:在容器中运行的命令

💡 说明:

  • 如果容器内没有 bash(如 Alpine),你可以尝试:

    docker exec -it alpine-container sh
    

二、运维场景:动态调试 + 临时任务执行

查看容器内环境变量
docker exec myapp printenv
临时运行诊断工具
docker exec -it nginx curl -I http://localhost
拷贝、解压、生成数据
docker exec myapp tar -czf /data/backup.tar.gz /app/data

📌 注意:exec 执行的是当前容器上下文环境下的命令,不依赖宿主机。


三、结合用户身份与安全控制

docker exec -u 1001 myapp whoami
  • -u <UID|user>:指定用户运行命令,适合有多用户角色的服务容器。
  • 某些基础镜像(如 debian, ubuntu)会默认创建多个用户角色,可配合使用。

🚨 安全提示:

  • 避免以 root 身份执行高风险命令(如 rm -rf /data),除非你清楚权限边界。
  • 若容器内部已运行低权限服务,应保持一致的执行环境。

四、在 CI/CD 中批量执行命令

在 CI/CD 脚本中,docker exec 常被用于部署后配置、热更新、动态注册等操作

docker exec webapp sed -i 's/debug=true/debug=false/' /app/conf/settings.ini
docker exec webapp systemctl reload nginx

📦 示例场景

  • 将容器内配置与外部环境同步
  • 容器运行后加载 secrets 或注册到 Consul、etcd 等配置中心

五、与 docker run 的区别与边界

功能点docker rundocker exec
作用对象创建并启动新的容器已运行容器中执行命令
是否新建容器
应用场景启动服务容器/临时任务容器远程登录容器/动态运维
生命周期命令完成后容器可能销毁 (--rm)不影响原容器运行状态

六、常见误区与性能注意

  1. docker exec 执行后台命令并不会自动 detach,比如:

    docker exec myapp sleep 1000
    

    会阻塞执行,直到 sleep 完成。

  2. ❌ 不能在未运行的容器中使用 docker exec

    Error response from daemon: Container <id> is not running
    

    ➜ 正确做法是先 docker start <id>,再 exec

  3. ❌ 不适合执行复杂任务(建议用 docker cp + bash script


七、高级技巧与替代方案

使用 nsenter 与宿主机隔离交互

可选安装 nsenter 工具用于更底层方式进入容器(如进入 pause 容器),但一般不推荐。

通过 Entrypoint + signal 控制替代 exec

对于需要热重载配置的容器,不推荐频繁 exec,而应设计好 ENTRYPOINT 支持监听 SIGHUPSIGUSR1 信号:

docker kill --signal=HUP myapp

这是一种更“优雅”的容器通信方式。


八、总结:docker exec 是容器中的 SSH,但别滥用

docker exec 是连接容器最直接的通道,也是最容易造成误操作的接口。合理使用可大幅提升运维效率,但不规范使用也可能绕过配置管理系统,制造技术债。

✅ 推荐使用场景:

  • 临时调试、运维
  • 动态查看或注入信息
  • 脚本中批量任务执行

❌ 不推荐使用场景:

  • 持续性任务(用 volume + CMD)
  • 容器初始化配置(应在 Dockerfile 或 entrypoint 中完成)

📓 docker logs <容器ID>

说明 查看指定容器的标准输出日志。

别名/全名

  • docker container logs

示例

docker logs a1b2c3d4e5f6
# 监听日志实时输出
docker logs -f a1b2c3d4e5f6

🗂️ 网络与端口/数据卷

命令说明
docker network ls查看网络列表
docker network create <网络名>创建自定义网络
docker volume ls查看所有数据卷
docker volume create <卷名>创建数据卷
docker run -v <本地路径>:<容器路径> <镜像>绑定挂载
docker inspect <容器/镜像>查看详细元信息

🛜 docker network ls

说明

  • 列出本机上的所有 Docker 网络。包括内置(bridge、host、none)和用户自建网络。

别名/全名

  • 官方全称:docker network ls

示例

docker network ls

# 输出示例
# NETWORK ID     NAME      DRIVER    SCOPE
# abcd1234efgh   bridge    bridge    local
# ijkl5678mnop   host      host      local
# qrst9012uvwx   none      null      local
# yzab3456cdef   network1  bridge    local

🆕 docker network create

说明

  • 创建一个自定义网络,支持多种驱动(bridge、overlay、macvlan 等),可指定子网、网关、IP 范围。

别名/全名

  • 官方全称:docker network create

常用参数示例

# 创建一个默认 bridge 网络,名称 network1
docker network create network1

# 指定子网与网关
docker network create \
  --driver bridge \
  --subnet 172.18.0.0/16 \
  --gateway 172.18.0.1 \
  network2

# 创建 overlay 网络(用于 Swarm 集群)
docker network create \
  --driver overlay \
  --attachable \
  swarm-net

📜 docker volume ls

说明

  • 列出本机上所有 Docker 卷(volume),包括挂载状态和驱动类型。

别名/全名

  • 官方全称:docker volume ls

示例

docker volume ls

# 输出示例
# DRIVER    VOLUME NAME
# local     mydata
# local     db_volume

🗞️ docker volume create

说明

  • 创建一个新的 Docker 卷,可指定驱动和驱动选项,用于持久化容器数据。

别名/全名

  • 官方全称:docker volume create

常用参数示例

# 创建一个默认 local 驱动的卷
docker volume create mydata

# 使用自定义驱动及选项(例如 rexray)
docker volume create \
  --driver rexray \
  --opt size=10 \
  --opt encrypted=true \
  secure_vol

# 创建带标签(label)的卷
docker volume create \
  --label project=demo \
  --label env=prod \
  labeled_vol

✉️ docker inspect

说明

  • 输出低层次的对象(容器、镜像、网络、卷等)详细 JSON 信息,包括配置、状态、网络设置、挂载点等。
  • 可结合 -f(format) 参数使用 Go 模板过滤输出字段。

别名/全名

  • 官方全称:docker inspect

常用参数示例

# 查看容器详细信息
docker inspect mycontainer

# 只查看某个字段,如容器的 IP 地址
docker inspect -f '{{ .NetworkSettings.IPAddress }}' mycontainer

# 查看网络详细信息
docker inspect network1

# 查看卷挂载信息
docker inspect mydata

🏃‍♂️ docker run

说明

  • 拉取(若本地无镜像)并创建一个新容器,执行镜像默认命令,然后退出或持续运行。
  • 可通过各种参数控制网络、挂载卷、环境变量等。

别名/全名

  • 官方全称 docker container run

docker run 命令深度解析:不仅仅是启动一个容器

docker run 是 Docker 使用频率最高的命令之一,但它同时也是最“复杂”的命令之一。大多数初学者只用它来“跑一个镜像”,但在实际生产中,我们更关注的是:

  • 容器如何命名与管理?
  • 是否具备正确的数据持久化策略(卷挂载)?
  • 网络是否暴露在安全范围内(端口映射)?
  • 是否通过环境变量传递了敏感配置?
  • 容器是否最小权限运行?

下面我们从这些维度逐一深入解析。


一、容器命名与生命周期控制

docker run --name myapp --rm nginx
  • --name myapp:为容器设置可读性强的名称,便于后续使用 docker start myapp 管理容器。
  • --rm:容器退出后自动删除,适合一次性任务;注意不适用于持久服务

🔍 生产推荐:

  • 后台服务容器不建议 --rm,避免数据丢失。
  • 命名采用结构化格式,如:appname-env-role-1

二、端口映射与安全边界

docker run -d -p 8080:80 nginx
  • -p 主机端口:容器端口:映射容器端口到宿主机,访问服务变得可能。
  • -P:自动分配所有 EXPOSE 的端口,不推荐用于生产,不可控。

🔐 安全提示:

  • 只映射必要端口,最好加 --network bridge 限制暴露范围。
  • 不建议直接暴露数据库端口(如 3306, 6379),应通过网关或 VPN 限制访问。

三、数据卷挂载与持久化

docker run -v /data/nginx/html:/usr/share/nginx/html nginx
  • -v <宿主路径>:<容器路径>:绑定挂载(bind mount),适合开发调试。
  • -v myvolume:/data:使用命名卷,Docker 自动管理,适合生产持久化。

📦 示例:挂载配置目录与日志目录

docker run \
  -v /etc/myapp/conf:/app/conf \
  -v myapp_logs:/var/log/myapp \
  myapp:latest

🧱 推荐策略:

  • 配置用 bind mount,便于热更新;
  • 日志与数据目录使用 volume,便于备份与迁移。

四、环境变量与敏感信息注入

docker run -e MYSQL_ROOT_PASSWORD=secret mysql
  • -e 设置环境变量,是配置密码、用户名等的标准方式。

🌱 安全建议:

  • 不将密码写死在命令中;可用 .env 文件配合 --env-file 使用:

    docker run --env-file ./myenv.list myapp
    
  • 敏感信息也可以结合 docker secret(Swarm)或 Kubernetes Secret 管理。


五、用户权限控制与最小权限原则

docker run -u 1001:1001 myapp
  • -u <UID>:<GID>:以指定的非 root 用户运行容器,避免容器被入侵后获取宿主机 root 权限。

🔐 安全建议:

  • 永远不要在生产环境以 root 用户运行容器,除非必须。
  • 最好自定义镜像时已切换到非 root 用户(USER 指令)。

六、综合实例:一个“生产级”运行命令

docker run -d \
  --name webapp-prod \
  -p 443:443 \
  -v /etc/webapp/conf:/app/conf:ro \
  -v webapp_data:/app/data \
  --env-file ./secrets.env \
  --restart=always \
  --user 1001:1001 \
  myorg/webapp:1.0.2

功能说明:

功能参数
服务端口映射-p 443:443
配置文件挂载(只读)-v ...:ro
数据卷持久化-v webapp_data:...
环境变量注入--env-file
非 root 运行--user
自动重启策略--restart=always

七、总结:docker run 是“镜像->服务”的桥梁

一个优秀的 docker run 命令,不仅仅能“跑起来”,更要具备以下特性:

  • 命名规范:便于管理;
  • 卷挂载清晰:数据安全;
  • 网络控制:接口收敛;
  • 权限配置:最小授权;
  • 配置解耦:环境变量注入;
  • 自动恢复:加上 --restart 策略。

真正用好 docker run,就能构建起一个“结构化、可控、安全”的容器服务基础架构。


🛠️ Dockerfile 构建相关命令回顾

Dockerfile 是构建 Docker 镜像的脚本文件,定义了镜像内应该包含的内容和构建步骤。掌握它,就等于掌握了容器化应用的核心生产力工具。

参考文档


🧱 Dockerfile 是什么?

Dockerfile 是一个文本文件,包含了一系列用于构建镜像的指令(Instructions)。这些指令会被 docker build 命令顺序执行,最终生成一个可运行的容器镜像。


🧩 Dockerfile 核心指令全览

一个标准的 Dockerfile 通常包括以下几个核心部分:

指令作用
FROM指定基础镜像(如 ubuntu, alpine, python
RUN在构建镜像时运行命令(如安装依赖)
COPY / ADD将本地文件复制到镜像中
WORKDIR设置工作目录
CMD / ENTRYPOINT设置容器启动时执行的命令
EXPOSE声明容器监听的端口(文档用途)
ENV设置环境变量
ARG定义构建时变量
VOLUME定义挂载卷位置(持久化数据)
LABEL添加元数据信息(如作者、版本)

以下是构建镜像最常用的 Dockerfile 指令:

1. FROM(基础镜像)

定义构建镜像所基于的父镜像。必须是第一条非注释指令。

FROM node:20-alpine

2. RUN(执行命令)

在镜像构建时执行 shell 命令,常用于安装依赖、修改配置。

RUN apk add --no-cache python3

3. COPY / ADD(复制文件)

将宿主机上的文件复制到镜像中。

  • COPY:基础复制
  • ADD:支持远程 URL、自动解压 tar 文件
COPY . /app
ADD https://example.com/data.tar.gz /data/

4. WORKDIR(设置工作目录)

设置后续指令的默认工作路径。

WORKDIR /app

5. CMD / ENTRYPOINT(定义启动命令)

  • CMD:容器默认启动命令,可被覆盖
  • ENTRYPOINT:更强制的启动命令(不容易被替换)
CMD ["node", "index.js"]
ENTRYPOINT ["python3", "main.py"]
🔎 CMD vs ENTRYPOINT 有啥区别?
项目CMDENTRYPOINT
默认命令
可被 docker run 覆盖❌(除非加 --entrypoint
最常用途提供默认命令参数设置主命令(如 nginx

结合使用:

ENTRYPOINT ["python"]
CMD ["app.py"]


6. EXPOSE(声明端口)

声明容器运行时监听的端口(仅声明,不会自动映射主机端口)。

EXPOSE 8080

7. ENV(设置环境变量)

ENV NODE_ENV=production

8. ARG(构建参数)

在构建阶段可传递变量,通常与 --build-arg 配合使用。

ARG VERSION=1.0
RUN echo "Build version: $VERSION"

🧠 Dockerfile 编写建议

  1. 选择轻量镜像:如 alpine,减小体积、提升构建速度。

  2. 减少层数:将多个 RUN 命令合并。

    RUN apt update && apt install -y curl && rm -rf /var/lib/apt/lists/*
    
  3. 使用 .dockerignore:避免将无关文件复制进镜像。

  4. 固定版本号:确保构建的可重复性。

  5. 使用 ENTRYPOINT + CMD 组合:提高灵活性。

  6. 利用缓存优化构建顺序:常变的文件放后面。

  7. 多阶段构建(Multi-stage build): 只保留运行时必要内容,精简镜像体积。


🧪 示例:打包一个 Python Flask 应用

# 使用官方 Python 基础镜像
FROM python:3.10-slim

# 设置工作目录
WORKDIR /app

# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install -r requirements.txt

# 复制源代码
COPY . .

# 暴露端口
EXPOSE 5000

# 启动应用
CMD ["python", "app.py"]

构建镜像:

docker build -t flask-demo .

运行容器:

docker run -p 5000:5000 flask-demo

🚫 常见坑点

  • COPY 顺序错 → 构建缓存失效
  • RUN 安装完没清理缓存 → 镜像超大
  • WORKDIR 未设置 → 程序路径混乱
  • EXPOSE 没映射 → 容器内部服务无法访问
  • ENTRYPOINT 写死 → 无法调试或扩展

🚀 总结

Dockerfile 是构建镜像的描述性语言,掌握它可以:

  • 标准化部署流程
  • 避免“在我电脑上可以跑”
  • 与 CI/CD 高效集成


🧹 系统清理与管理

命令说明
docker system df查看资源占用
docker system prune清理未使用的资源(危险操作)
docker image prune清理未使用的镜像
docker container prune清理已停止的容器
docker volume prune清理无用的卷

⚙️ docker system df

说明 显示 Docker 守护进程当前各类对象(镜像、容器、本地卷、构建缓存等)所占用的磁盘空间总量和可回收量。网络信息不在此统计中,因为其并不占用磁盘空间。

常用选项

  • -v, --verbose:显示更详细的使用情况,包括每个镜像、容器和卷的具体大小。

示例

# 仅显示概要
docker system df

# 显示详细信息
docker system df --verbose

🧹 docker system prune

说明 一次性移除所有未被使用的容器、网络、(悬挂和未被任何容器引用的)镜像,以及可选地移除未使用的卷。属于危险操作,执行前会有确认提示。

常用选项

  • -a, --all:除了移除“悬挂”镜像,也移除所有未被任何容器使用的镜像。
  • --volumes:同时移除所有未被任何容器使用的卷。
  • -f, --force:跳过确认提示,直接执行。
  • --filter <表达式>:根据条件过滤要移除的对象(如 until=24h 表示仅移除 24 小时前未使用的资源)。

示例

# 移除悬挂镜像、停止容器、未用网络及构建缓存
docker system prune

# 加上 -a,移除所有未被容器使用的镜像
docker system prune --all

# 同时移除未使用的卷
docker system prune --volumes

# 跳过确认
docker system prune --force

# 仅移除 48 小时前未使用的资源
docker system prune --filter "until=48h"

📀 docker image prune

说明 清理“悬挂”(dangling)镜像:即没有标签且未被任何容器引用的镜像。加上 -a 则移除所有未被任何容器使用的镜像。

常用选项

  • -a, --all:移除所有未被容器使用的镜像,而不仅限于悬挂镜像。
  • -f, --force:跳过确认提示。
  • --filter <表达式>:例如 until=24h 仅移除 24 小时前创建的镜像。

示例

# 移除悬挂镜像
docker image prune

# 移除所有未被使用的镜像
docker image prune --all

# 跳过确认
docker image prune --force

# 仅移除 24 小时前的镜像
docker image prune --all --filter "until=24h"

🫙 docker container prune

说明 清理所有已停止的容器。已停止容器的可写层会继续占用磁盘空间,使用此命令可统一释放。

常用选项

  • -f, --force:无确认直接执行。
  • --filter <表达式>:如 until=24h 仅移除 24 小时前停止的容器。

示例

# 移除所有已停止的容器
docker container prune

# 跳过确认
docker container prune --force

# 仅移除 48 小时前停止的容器
docker container prune --filter "until=48h"

🗂️ docker volume prune

说明 清理所有未被任何容器使用的卷。因卷可能包含重要数据,默认会提示确认,且需谨慎操作。

常用选项

  • -f, --force:无确认直接执行。
  • --filter <表达式>:如 label!=keep 仅保留带有 keep 标签的卷。

示例

# 移除所有未使用的卷
docker volume prune

# 跳过确认
docker volume prune --force

# 仅移除未标记为 keep 的卷
docker volume prune --filter "label!=keep"

Docker 容器系统清理机制深入剖析

在容器开发与持续集成的日常实践中,磁盘空间的异常膨胀往往源自未管理的镜像、悬挂卷或停止的容器。这时,Docker 的一组 “prune” 系列命令便成为 DevOps 工程师清理系统资源的“清道夫”。然而,很多用户在使用这些命令时存在误解:prune 是“万能清理剂”吗?是否安全?为什么执行后镜像丢了?本文将从工作原理、使用边界、典型用例三方面进行深入分析。


1. docker system prune 背后的机制

docker system prune 并非简单地“强删”资源,而是 Docker 守护进程根据资源依赖关系和使用状态,递归扫描无引用资源的对象图,判断哪些资源已经“脱钩”,并进行删除。

它默认移除以下内容:

  • 已停止的容器Exited 状态)
  • 未使用的网络
  • dangling 镜像(无 tag 且无容器引用的中间层镜像)
  • 构建缓存(Docker BuildKit 所产生的中间产物)

使用 --volumes 时才会加入 无挂载的匿名卷docker volume create 创建却未绑定容器的卷)。

📌 深度机制点:

docker system prune --volumes

相当于调用了:

docker container prune &&
docker image prune &&
docker network prune &&
docker volume prune

这意味着,system prune 是其他子命令的聚合调用,可通过组合参数决定“波及范围”。


2. 风险评估与安全边界

许多初学者在执行 docker system prune -a --volumes 后懊悔不已,因为发现自己常用的镜像和数据卷都被删除了。

关键点解释:
  • -a 会删除所有未被容器使用的镜像,不区分是否有 tag。
  • --volumes 会删除所有未挂载的卷,包括数据卷,可能导致持久数据丢失。
  • 删除是不可恢复的,Docker 不提供回收站机制。

🔐 最佳实践:

  • 使用 --filter 加时间戳限制:

    docker system prune --filter "until=72h"
    
  • 针对镜像和数据卷,使用 label 管理保留策略:

    docker volume prune --filter "label!=keep"
    

3. CI/CD 场景的优化用法

在 GitLab CI 或 GitHub Actions 中,Docker 层的持续构建会堆积大量 dangling 镜像和 build cache。如果不清理,Runner 容器可能在短时间内耗尽磁盘。

一个推荐做法是在每次构建前后使用定制化清理:

docker builder prune -f --filter "until=24h"
docker image prune -a -f --filter "until=24h"

这样可以定期清理 24 小时前的构建缓存与临时镜像,保留近期产物,提高构建速度并释放磁盘空间。


4. 总结:系统不是越干净越好,而是越“可控”越好

Docker 提供了强大且细粒度的资源清理命令,不同 prune 子命令各司其职。正确理解它们之间的范围区别执行优先级,配合标签与时间过滤器,就可以构建出一个可预测、可恢复、可优化的容器资源生命周期体系。