【Docker#6】Docker 容器常用命令

🌈 个人主页:Zfox_

🔥 系列专栏:Docker

目录

  • [一:🔥 容器概述](#一:🔥 容器概述)
    • [🦋 什么是容器](#🦋 什么是容器)
    • [🦋 类比理解](#🦋 类比理解)
    • [🦋 为什么需要容器](#🦋 为什么需要容器)
      • [🎀 环境一致性:"一次构建,到处运行"](#🎀 环境一致性:“一次构建,到处运行”)
      • [🎀 资源高效利用:"榨干" 硬件性能](#🎀 资源高效利用:“榨干” 硬件性能)
      • [🎀 部署与扩展:简化流程,提升效率](#🎀 部署与扩展:简化流程,提升效率)
      • [🎀 隔离与安全:保障应用独立运行](#🎀 隔离与安全:保障应用独立运行)
    • [🦋 容器生命周期](#🦋 容器生命周期)
    • [🦋 容器的特殊情况](#🦋 容器的特殊情况)
        • [容器 OOM(Out-of-Memory)事件 ------ 资源超限类异常](#容器 OOM(Out-of-Memory)事件 —— 资源超限类异常)
        • [容器异常退出(Init 进程退出)------ 生命周期异常](#容器异常退出(Init 进程退出)—— 生命周期异常)
        • 与其他特殊情况的关联
        • [工程最佳实践 -- 解决方法](#工程最佳实践 -- 解决方法)
  • [二:🔥 容器常用命令](#二:🔥 容器常用命令)
      • [1. docker create](#1. docker create)
      • [2. docker logs](#2. docker logs)
      • [3. docker attach](#3. docker attach)
      • [4. docker exec](#4. docker exec)
      • [5. docker start](#5. docker start)
      • [6. docker stop](#6. docker stop)
      • [7. docker restart](#7. docker restart)
      • [8. docker kill](#8. docker kill)
      • [9. docker top](#9. docker top)
      • [10. docker stats](#10. docker stats)
      • [11. docker container inspect](#11. docker container inspect)
      • [12. docker cp](#12. docker cp)
      • [13. docker diff](#13. docker diff)
      • [14. docker commit](#14. docker commit)
      • [15. docker pause](#15. docker pause)
      • [16. docker unpause](#16. docker unpause)
      • [17. docker rm](#17. docker rm)
      • [18. docker export](#18. docker export)
      • [19. docker import](#19. docker import)
      • [19. docker wait](#19. docker wait)
      • [20. docker rename](#20. docker rename)
      • [21. docker container prune](#21. docker container prune)
      • [22. docker update](#22. docker update)
      • [23. docker run](#23. docker run)
      • [24. docker ps](#24. docker ps)
      • [25. 容器指令的区别](#25. 容器指令的区别)
        • [25.1 docker create、docker start和docker run之间的区别](#25.1 docker create、docker start和docker run之间的区别)
        • [25.2 docker import和dokcer load之间的区别](#25.2 docker import和dokcer load之间的区别)
        • [25.3 docker rm &docker rmi&docker prune之间的区别](#25.3 docker rm &docker rmi&docker prune之间的区别)
  • [三:🔥 容器操作](#三:🔥 容器操作)
      • [1. 容器基本操作](#1. 容器基本操作)
      • [2. 容器状态迁移](#2. 容器状态迁移)
      • [3. 容器的批量搜索技巧](#3. 容器的批量搜索技巧)
      • [4. 容器的批量操作](#4. 容器的批量操作)
      • [5. 容器的交互模式](#5. 容器的交互模式)
        • [5.1 attached 模式](#5.1 attached 模式)
        • [5.2 Detached模式](#5.2 Detached模式)
        • [5.3 Interactive模式](#5.3 Interactive模式)
      • [6. 容器与宿主机内容复制](#6. 容器与宿主机内容复制)
      • [7. 容器自动删除](#7. 容器自动删除)
      • [8. 容器的自动重启](#8. 容器的自动重启)
      • [9. 容器环境变量的设置](#9. 容器环境变量的设置)
      • [10. 容器快速诊断](#10. 容器快速诊断)
      • [11. 容器导入导出](#11. 容器导入导出)
  • [四:🔥 容器实战案例](#四:🔥 容器实战案例)
      • [1. Mysql容器化安装](#1. Mysql容器化安装)
        • [1.1 下载安装](#1.1 下载安装)
        • [1.2 测试](#1.2 测试)
      • [2. Redis安装](#2. Redis安装)
        • [2.1 Redis 简历](#2.1 Redis 简历)
        • [2.2 实际操作](#2.2 实际操作)
      • [3. C++容器的制作](#3. C++容器的制作)
        • [3.1 制作 Centos 镜像](#3.1 制作 Centos 镜像)
        • [3.2 制作 Ubuntu 镜像](#3.2 制作 Ubuntu 镜像)
        • [3.3 一些问题](#3.3 一些问题)
      • [4. 容器资源更新](#4. 容器资源更新)
  • [五:🔥 共勉](#五:🔥 共勉)

一:🔥 容器概述

🦋 什么是容器

  • 容器是镜像的运行实体。
  • 镜像是静态的只读文件,而容器带有运行时需要的可写文件层,并且容器中的进程属于运行状态。
  • 容器有初建、运行、停止、暂停和删除五种状态。

容器与直接运行在主机上进程的本质区别

  • 虽然容器的本质是主机上运行的一个进程,但是容器有自己独立的命名空间隔离和资源限制。
  • 也就是说,在容器内部,无法看到主机上的进程、环境变量、网络等信息,

镜像与容器的关系

  • 容器是基于镜像创建的可运行实例,并且单独存在,一个镜像可以创建出多个容器。
  • 运行容器化环境时,实际上是在容器内部创建该文件系统的读写副本。 这将添加一个 容器层 ,该层允许修改镜像的整个副本。

🦋 类比理解

核心:镜像如同 App 安装包,容器如同正在运行的 App 进程"

生活案例:"镜像 = 毛坯房图纸 + 装修模板",容器 = 实际入住的装修房

1. 镜像(Image)------标准化的"装修方案包"

  • 想象你有一套标准化的毛坯房装修方案:包含水电布局图、墙面涂料品牌、地板型号、厨房橱柜样式、甚至预装的智能家电清单。
  • 这个方案是静态的、只读的、可复制的。你可以把它发给100个客户,每个人都按这个方案装修出几乎一模一样的房子。
  • 在 Docker 世界中,镜像就是这样一个"可执行的软件包" :包含运行应用所需的所有代码、运行时、库、环境变量和配置文件------但不运行、不占用内存、只是存储在磁盘上

特点

  • 不可变(immutable)
  • 可版本化(如 nginx:1.23.4
  • 可共享(通过 Docker Hub、Harbor 等镜像仓库)

2. 容器(Container)------按方案装修并入住的房子*

  • 当你用这个装修方案在某个毛坯房里实际施工并入住,就得到了一个"容器"。
  • 这个房子现在通电、通水、有人居住、状态可变(比如你今天把沙发挪位置,明天装个新灯)。
  • 但注意:改动通常只存在于这一套房子。如果你再用同一套方案装修第二套房子,新房子还是原始状态(除非你把改动"固化"成新方案------即提交为新镜像)。

特点

  • 是镜像的运行实例(instance)
  • 有独立的文件系统层(可写层)
  • 有独立的网络、进程空间、资源限制
  • 生命周期短暂,可随时销毁重建

扩展理解:关键特性类比

概念 技术含义 生活类比
镜像分层(Layer) 镜像由只读层堆叠而成(如基础 OS + Nginx + 配置) 装修方案分"基础装修包"+"软装包"+"智能家居包",可组合复用
容器可写层(Writeable Layer) 容器运行时所有修改都发生在此层 入住后你贴的墙贴、移动的家具,只影响这一户
多个容器来自同一镜像 docker run -d nginx 多次 → 多个独立 Nginx 服务 多个小区用同一套装修方案,每户独立生活,互不干扰
删除容器 ≠ 删除镜像 容器删了,镜像还在,可随时再启 拆掉一套装修房,装修方案图纸还在,可再造
提交容器为新镜像 docker commit 把容器当前状态保存为新镜像 把你改造后的房子拍照做成"升级版装修方案",供他人使用

🦋 为什么需要容器

镜像是静态的文件,并不能提供服务,就像我拿了个 Linux 或者 Windows 的光盘一样,只有安装到主机里面运行起来才能对外提供服务,我们才能使用。

  • 问题:开发者在本地写好代码,测试通过,但部署到测试/生产环境时,因操作系统、依赖库(如 glibc、Protobuf 版本)、环境变量等不同,程序崩溃。
  • 容器方案 :把代码 + 运行时 + 依赖库 + 配置 打包成一个镜像。
    → "Build once, run anywhere"(一次构建,到处运行)。

容器带来哪些收益呢,参考我们之前讲解的为什么要虚拟化、容器化。

容器的本质是 "轻量级虚拟化"它不虚拟完整的操作系统,而是基于宿主机的 OS 内核,通过 "容器引擎"(如 Docker Engine)为应用提供独立的运行环境(文件系统、网络、进程空间),同时共享宿主机的内核和硬件资源。这种特性使其具备四大核心优势,直接对应传统架构的痛点:

🎀 环境一致性:"一次构建,到处运行"

这是容器最核心的价值之一,解决了 "开发 - 测试 - 生产" 环境不一致的问题。

  • 原理:容器将应用及其所有依赖(代码、运行时、库、环境变量、配置文件)打包成一个标准化的 "容器镜像"(Image)。镜像就像一个 "可移植的盒子",包含了应用运行所需的全部条件。
  • 效果:开发人员在本地构建镜像后,测试团队可直接使用相同镜像在测试环境运行,运维团队也无需修改配置即可将同一镜像部署到生产环境。从根本上消除了 "环境差异导致的兼容性问题",实现 "Build once, Run anywhere"。

🎀 资源高效利用:"榨干" 硬件性能

相比虚拟机,容器对资源的消耗极低,大幅提升了服务器利用率。

虚拟机 容器(Docker) 容器(Docker)
启动时间 秒~分钟级 毫秒~秒级
资源开销 需完整 OS + Hypervisor 共享宿主机内核
密度 一台物理机跑几十个 VM 一台物理机跑几百个容器
  • 轻量级隔离:容器共享宿主机的 OS 内核,无需为每个容器分配独立的操作系统,因此单个容器的体积通常只有 "MB 级"(如一个 Nginx 容器仅 20MB 左右),而虚拟机的体积多为 "GB 级"。
  • 高密度部署:一台普通服务器可同时运行数十甚至上百个容器,而若运行虚拟机,通常只能承载 5-10 个(因每个 VM 需占用 1-2GB 内存)。
  • 快速启停:容器启动时间仅需 "秒级"(如 Docker 容器启动耗时 < 1 秒),而虚拟机启动需 "分钟级"(如 VMware 启动一个 Linux 虚拟机需 3-5 分钟),适合高频次的弹性伸缩场景。

🎀 部署与扩展:简化流程,提升效率

容器的标准化和轻量级特性,让应用的部署、更新、回滚和扩展变得异常简单。

  • 标准化部署 :容器镜像的格式统一(如 Docker 镜像遵循 OCI 标准),可通过简单命令(如docker run)快速启动,无需关注底层环境配置,大幅降低运维门槛。

  • 标准化交付与不可变基础设施(Immutable Infrastructure)

    • 传统方式:运维 SSH 到服务器,手动安装、配置、启动服务 → 容易出错、难以回滚。

    • 容器方式

      • 交付物是镜像(一个文件)
      • 部署 = docker runkubectl apply
      • 出问题?直接销毁旧容器,启动新版本容器(不可变,不修旧实例)
  • 无缝更新与回滚:更新应用时,只需构建新的容器镜像并替换旧容器,过程中可通过 "滚动更新"(如 Kubernetes 的 RollingUpdate)实现零停机;若出现问题,回滚到旧镜像仅需秒级,风险极低。

  • 弹性伸缩:结合容器编排工具(如 Kubernetes、Swarm),可根据业务流量(如 CPU 使用率、请求量)自动增加或减少容器数量,实现 "按需分配资源",避免资源浪费(如电商大促时临时扩容,结束后自动缩容)。

🎀 隔离与安全:保障应用独立运行

容器通过内核级别的隔离机制( Linux Namespace + Cgroups 实现),确保不同应用之间互不干扰,同时降低安全风险。

  • 进程与资源隔离 :每个容器拥有独立的进程空间、网络栈、文件系统和用户权限,一个容器内的进程无法直接访问其他容器的资源(如 A 容器的应用崩溃不会影响 B 容器),并且CPU、内存、磁盘 I/O 可设上限(避免一个服务拖垮整机
  • 最小权限原则:容器镜像可仅包含应用运行必需的组件(如仅安装 Java 运行时,而非完整的 Linux 发行版),减少了攻击面(相比虚拟机中冗余的系统组件,容器被黑客利用漏洞的概率更低)。

🦋 容器生命周期

容器的生命周期(Container Lifecycle)描述了一个容器从创建到销毁 所经历的各个状态和关键阶段。理解生命周期对调试、运维、自动化部署和资源管理至关重要,尤其在微服务和云原生场景中(比如你用 brpc + Docker 构建的 IM 系统)。

阶段 是否占用 CPU/内存 文件系统是否保留 可否重启 典型操作
Created docker start
Running --- docker exec, logs
Paused 否(冻结) ✅(unpause) 调试
Exited docker start, logs
Deleted ❌(永久删除) docker run 重新创建

💡 记住 :容器是短暂的(ephemeral),设计系统时应假设它随时可能被销毁重建。

各生命周期之间的转换关系如图所示:

  • docker create : 创建容器后,不立即启动运行,容器进入初建状态;

  • docker run : 创建容器,并立即启动运行,进入运行状态;

  • docker start : 容器转为运行状态;

  • docker stop : 容器将转入停止状态;

  • docker kill : 容器在故障(死机)时,执行 kill(断电),容器转入停止状态,这种操作容易丢失数据,除非必要,否则不建议使用;

  • docker restart : 重启容器,容器转入运行状态;

  • docker pause : 容器进入暂停状态;

  • docker unpause : 取消暂停状态,容器进入运行状态;

  • docker rm : 删除容器,容器转入删除状态。

  • killed by out-of-memory(因内存不足被终止) :宿主机内存被耗尽,也被称为 OOM:非计划终止,这时需要杀死最吃内存的容器

  • container process exitde(异常终止):出现容器被终止后,将进入 Should restart? 选择操作:

    • yes 需要重启,容器执行 start 命令,转为运行状态。

    • no 不需要重启,容器转为停止状态。

创建(Created)
  • 触发方式docker createdocker run(run = create + start)
  • 状态特点
    • 容器文件系统已基于镜像创建(叠加可写层)
    • 网络、卷、环境变量等配置已初始化
    • 但进程未启动,处于"就绪但未运行"状态
  • ✅ 可通过 docker ps -a 查看状态为 Created

📌 类比:房子装修完毕、水电接通,但还没人入住。

运行中(Running)
  • 触发方式docker startdocker run

  • 关键行为

    • 容器主进程(PID 1)启动(如 nginx./my_brpc_server
    • 网络端口监听、日志输出、接受请求
    • 可通过 docker exec 进入容器执行命令
  • 状态检查

    bash 复制代码
    docker ps          # 只显示 running 容器
    docker inspect myweb1 | grep -i status

⚠️ 注意:只要主进程未退出 ,容器就保持 running(即使你 docker exec 退出了)。

停止(Stopped / Exited)
  • 触发方式
    • 主进程正常退出 (如 exit 0
    • 手动 docker stop(发送 SIGTERM → 优雅退出 → SIGKILL)
    • 主进程崩溃(如段错误)
  • 状态特点
    • 进程终止,但容器文件系统和日志仍保留
    • 可通过 docker start 重启(但注意:某些应用状态可能丢失,若未持久化)
    • 状态显示为 Exited (code) X seconds ago
  • ✅ 资源(CPU/内存)已释放,但磁盘占用仍在

📌 类比:人搬出房子,但家具还在屋内(可重新入住或清空)。

销毁(Deleted / Removed)
  • 触发方式docker rm <container>docker rm -f(强制删除 running 容器)
  • 结果
    • 可写层(所有运行时修改)永久删除
    • 挂载的匿名卷(anonymous volumes)默认也删除(除非加 -v 保留)
    • 镜像不受影响(镜像独立存在)
  • 🔒 不可逆!删除后无法恢复容器状态。

✅ 建议:定期清理 Exited 容器,避免磁盘堆积:

bash 复制代码
docker container prune
暂停(Paused)【可选状态】
  • 触发方式docker pause
  • 特点
    • 其他资源保留,CPU 资源剥夺 : 内存、网络连接保留,但Docker 会 "剥夺" 该容器的 CPU 资源
    • 状态 : 由于失去了 CPU 资源,容器中的进程不会被主机内核系统调度(此时相当于 容器内所有进程被冻结),因此容器处于 "冰封"(Linux cgroups freezer) 状态。
    • docker unpause 恢复
  • 用途:调试、临时冻结高负载容器

💡 此状态使用较少,多数场景直接 stop/start。

小结 :"容器的生命周期从 create 到 remove,核心是 running 和 exited 两态。我们应围绕 '不可变基础设施' 理念,将状态外置,让容器无状态、可快速重建------这正是微服务和云原生的基石。"

🦋 容器的特殊情况

在容器化(如 Docker)应用中,"特殊情况" 指的是偏离正常生命周期或行为异常的场景,若未妥善处理,可能导致服务中断、数据丢失、节点故障等严重后果。两类最典型、最危险的场景是:

  • OOM(Out-of-Memory)事件:资源边界被突破,由宿主机内核强制干预;
  • Init 进程异常退出:主进程崩溃或主动退出,导致容器终止。

应对原则:设限 + 监控 + 优雅退出 + 合理重启策略 + 状态外置

容器 OOM(Out-of-Memory)事件 ------ 资源超限类异常

Docker 通过 Linux cgroups 对容器内存进行限制,当超过限制时,触发宿主机内核的 OOM 机制。根据配置不同,分为三种典型情况:

1️⃣ 内存限额耗尽(默认行为)→ OOM Killer 触发

  • 触发条件 :容器设置了内存上限(如 -m 512m),应用内存使用超过该值。

  • 底层机制

    • 宿主机内核的 OOM Killer 会被激活;
    • OOM Killer 会选择容器内"内存占用高、优先级低"的进程(通常是主进程)直接 SIGKILL 杀死
    • 由于主进程(Init 进程)被杀死,整个容器退出 ,状态变为 Exited (137)(137 = 128 + 9,SIGKILL 编号为 9)。
  • 关键特性

    • 不是 Docker Daemon 杀死的 ,而是宿主机内核
    • Docker 无法拦截或优雅处理,进程是被强制终止的
    • 无法执行清理逻辑(如关闭 etcd 连接、回滚事务、保存状态)。
    • 无退出日志(因进程被 SIGKILL)。
  • 验证方法

    bash 复制代码
    docker inspect myweb1 | grep -A5 OOMKilled  # 查看是否因 OOM 被杀
    docker logs myweb1                          # 通常无退出日志(被 SIGKILL)
    dmesg | tail -20                            # 查看内核日志中的 OOM 记录

📌 建议

  • 为 brpc 服务设置合理的 -m 限制(如 1G),避免吃光宿主机内存;
  • 监控内存使用(docker stats 或 Prometheus + cAdvisor);
  • 在代码中添加内存使用告警(如定期检查 getrusage());
  • 避免依赖 OOM 前的"优雅退出",因为根本没机会执行。

2️⃣ 禁用 OOM-Killer + 设置内存上限(危险组合)

  • 启动参数

    bash 复制代码
    docker run -m 512m --oom-kill-disable myapp
  • 行为 :内存达到上限后,不再分配新内存malloc()永久阻塞(hang)

    • 当内存达到 512MB 时,内核不会杀死进程
    • 不再分配新内存 ,任何 malloc()new 操作会永久阻塞(hang)
    • 容器看起来"还在运行"(docker ps 显示 Up),但完全无响应
    • 整个系统可能因内存碎片或全局内存压力而变慢。
  • 风险 :比直接 OOM 更危险!因为容器 "假活"(up),健康检查可能无法发现,导致流量持续打入"僵尸实例"。

  • 用途 :仅用于调试绝不用于生产环境

3️⃣ 禁用 OOM-Killer + 无内存上限(极度危险)

  • 启动参数

    bash 复制代码
    docker run --oom-kill-disable myapp   # 未设 -m
  • 行为:容器可无限使用宿主机内存;

  • 后果

    • 一旦内存耗尽,整个宿主机可能卡死、SSH 无法登录、其他容器全部瘫痪
    • 最终触发宿主机全局 OOM,随机杀死系统关键进程(如 systemd、sshd)
    • 节点级故障,远比单个容器崩溃严重。
  • 结论永远不要在生产环境使用 --oom-kill-disable 而不设 -m


容器异常退出(Init 进程退出)------ 生命周期异常

核心机制

  • 每个容器有且仅有一个 Init 进程(PID 1)
  • 该进程由 CMDENTRYPOINT 指定;
  • 只要 PID 1 退出(无论正常或异常),Docker 就认为容器任务完成,立即终止整个容器
  • 容器内所有子进程(包括后台线程、fork 出的进程)全部被 SIGKILL 清理

常见异常退出原因

原因 表现 Exit Code 说明
主进程崩溃(段错误,空指针) Exited (139) 139 C++ 程序空指针解引用等
主进程 OOM 被杀 Exited (137) 137 如上所述
主进程抛出未捕获异常 Exited (1) 1 C++ throwcatch
依赖服务不可达(如 etcd 连不上) Exited (1) 1 应用主动 exit(1)
脚本执行完毕 Exited (0) 0 CMD ["echo", "hello"]

Docker Daemon 的行为

  • 默认 :容器退出后,保持 Stopped 状态,不再自动重启;

  • 若设置了 --restart 策略

    bash 复制代码
    docker run --restart=on-failure:3 ...   # 失败时最多重启 3 次
    docker run --restart=always ...         # 总是重启(慎用!)
  • 重要限制

    • --restart 无法区分正常退出 vs 异常退出
    • 如果应用因配置错误每次启动都 crash--restart=always 会导致无限重启循环(CrashLoop),浪费资源;
    • 生产环境推荐 on-failure + 有限次数,并配合监控告警。
与其他特殊情况的关联
特殊情况 与 OOM/异常退出的关系
僵尸容器 OOM 被杀后若未清理,会留下 Exited (137) 容器
容器假死 --oom-kill-disable 导致的 hang 状态就是典型假死
数据丢失 OOM 或异常退出时,若未持久化 RabbitMQ 消息或用户状态,会丢数据
启动即退出 主进程因 etcd 连接失败主动退出,属于异常退出

① 僵尸容器(Zombie Container)

  • 现象 :容器状态显示为 Up,但主进程其实已退出或卡死,无法响应请求。

  • 原因

    • 主进程未正确处理信号(如忽略 SIGTERM
    • 多进程容器中,主进程(PID 1)退出,但子进程仍在运行(Docker 无法感知)
    • 应用死锁、无限阻塞(如 brpc 等待 etcd 响应但超时不设)
  • 检测

    bash 复制代码
    docker top myweb1       # 查看内部进程
    docker inspect myweb1 | grep -A5 State
  • 解决

    • 确保主进程是真正的入口进程 (不要用 bash -c 启动多进程)
    • 使用 tini 作为 init 进程(Docker 官方推荐):

② 容器退出但状态不清理(Exited 但未删除)

  • 现象Exited 容器占用磁盘(日志、可写层)→ 磁盘爆满 → 节点宕机。

  • 解决

    • 启动时加 --rm(临时容器):

      bash 复制代码
      docker run --rm -p 8080:80 nginx  # 退出后自动删除
    • 定期清理:

      bash 复制代码
      docker container prune -f
    • 限制日志大小(/etc/docker/daemon.json):

③ 端口冲突但容器仍启动成功

  • 现象docker run -p 80:80 成功启动,但外部无法访问。

  • 原因

    • 宿主机防火墙(如 ufw)未开放端口
    • 容器内服务监听 127.0.0.1 而非 0.0.0.0
    • 使用了 host 网络模式但未处理端口独占
  • 排查

    bash 复制代码
    # 检查容器内监听地址
    docker exec myweb1 netstat -tuln | grep 80
    
    # 检查宿主机是否监听
    ss -tuln | grep 80
    
    # 检查防火墙
    sudo ufw status

④ 容器"假死"------CPU 或内存爆满

  • 现象:容器运行中,但响应极慢或无响应。
  • 原因
    • 内存泄漏(C++ 服务未释放内存)
    • 死循环或高 CPU 计算
    • 未设资源限制,吃光宿主机资源
  • 应对
    • 启动时限制资源:docker run -m 512m --cpus=1.5 ...
    • 监控:docker stats myweb1
    • 在代码中加入健康检查(如 brpc 提供 /healthz 接口)

⑤ 文件系统未持久化导致数据丢失

  • 现象:容器重启后,配置文件、上传文件、数据库数据全没了。

  • 原因:将数据写入容器可写层(ephemeral layer),而非 Volume。

  • 正确做法

    bash 复制代码
    # 使用命名卷
    docker run -v mydata:/var/lib/mysql mysql
    
    # 或绑定宿主机目录
    docker run -v /host/conf:/app/conf myapp

⑥ DNS 或网络解析失败(尤其在私有网络)

  • 现象 :容器内 ping etcd 失败,但 ping 10.0.0.5 成功。

  • 原因

    • Docker 默认 DNS 配置可能不兼容企业内网
    • 未正确设置 --dnsextra_hosts
  • 解决

    bash 复制代码
    docker run --dns 10.0.0.10 --add-host etcd:10.0.0.5 ...

    或在 docker-compose.yml 中配置 extra_hosts


⑦ 时区/时间不同步

  • 现象:容器内日志时间比宿主机慢 8 小时(UTC vs CST)。

  • 解决(任选其一):

    Dockerfile 复制代码
    # 方法1:复制宿主机时区
    RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    
    # 方法2:挂载宿主机时区文件
    docker run -v /etc/localtime:/etc/localtime:ro ...

⑧ 容器启动后立即退出(CrashLoop)

  • 常见原因

    • 主进程启动失败(如配置文件错误、端口被占)
    • 依赖服务不可达(如 RabbitMQ 未启动)
    • 权限问题(如写日志目录无权限)
  • 排查步骤

    bash 复制代码
    docker logs myweb1          # 查看退出原因
    docker run --entrypoint sh -it myimage  # 进入调试
工程最佳实践 -- 解决方法
  1. 内存限制明确

    bash 复制代码
    docker run -m 1g --cpus=1.0 --name im-gateway your-brpc-image
  2. 主进程信号处理

    • 捕获 SIGTERM(Docker 停止时发送);
    • 执行优雅关闭:停止接收请求 → 处理完队列 → 关闭 etcd/Redis/RabbitMQ 连接 → exit(0)
  3. 禁止 --oom-kill-disable(除非调试);

  4. 使用 tini 作为 Init 进程

    Dockerfile 复制代码
    ENTRYPOINT ["/sbin/tini", "--", "./im_server"]

    → 避免子进程变僵尸,确保信号正确传递;

  5. 合理配置重启策略

    bash 复制代码
    # docker-compose.yml
    restart: on-failure:5
  6. 状态外置

    • 配置、数据、日志 → 使用 Volume 或绑定挂载;
    • 消息队列(如 RabbitMQ)开启持久化。
  7. 全面监控与告警

    • 监控指标:container_exited_reasonoom_kill、CPU/内存使用率;
    • 告警规则:Exited(137)、高频重启、健康检查失败。
  8. 日志与磁盘管理

    • 限制日志大小;
    • 定期清理 Exited 容器。

二:🔥 容器常用命令

命令 别名 功能
docker create docker container create 创建容器
docker run docker container run 运行容器
docker attach docker container attach 连接到正在运行中的容器
docker commit docker container commit 将镜像提交为容器
docker cp docker container cp 在容器和宿主机之间拷贝
docker diff docker container diff 检查容器里文件结构的更改
docker exec docker container exec 在运行的容器中执行命令
docker export docker container export 将容器导出为 tar
docker container inspect 查看容器详细信息
docker kill docker container kill 杀死容器
docker logs docker container logs 查看日志
docker ps docker container ls, docker container list, docker container ps 查看正在运行的进程
docker pause docker container pause 暂停进程
docker port docker container port 查看容器的端口映射
docker container prune 删除停止的容器
docker rename docker container rename 重命名容器
docker restart docker container restart 重启容器
docker rm docker container rm, docker container remove 删除容器
docker start docker container start 启动容器
docker stats docker container stats 查看资源占用信息
docker stop docker container stop 停止容器
docker top docker container top 查看某个容器的资源占用
docker unpause docker container unpause 继续运行容器
docker update docker container update 更新容器配置
docker wait docker container wait 阻止一个或多个容器停止,然后打印退出代码

1. docker create

创建一个新的容器但不启动它

bash 复制代码
docker create [OPTIONS] IMAGE [COMMAND] [ARG...]

关键参数

  • -i: 以交互模式运行容器,通常与 -t 同时使用;
  • -P: 随机端口映射,容器内部端口随机映射到主机的端口
  • -p: 指定端口映射,格式为:主机(宿主)端口:容器端口
  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用;
  • --name="nginx-lb": 为容器指定一个名称;
  • -h "mars": 指定容器的 hostname;
  • -e username="ritchie": 设置环境变量;
  • --cpuset-cpus="0-2" or --cpuset-cpus="0,1,2": 绑定容器到指定 CPU 运行;
  • -m:设置容器使用内存最大值;
  • --network="bridge":指定容器的网络连接类型;
  • --link=[]:添加链接到另一个容器;
  • --volume , -v:绑定一个卷
  • --rm:shell 退出的时候自动删除容器
  • --restart:自动重启

其实这个我在第二章关于查看 Nginx 内容是显示过的

bash 复制代码
docker create --name myweb -p 80:80 nginx:1.23.3

我们在输入这串命令之前80端口是已经被占用了的

这个create并没实际占用这个端口。所以创建成功了

使用docker ps是看不到我们创建的容器的,因为我们的容器是没有运行的,使用下方命令进行查看操作

bash 复制代码
docker ps -a #加上-a参数查看所有容器的数据

可以发现这个状态是Created的,接下来我们进行启动这个容器

bash 复制代码
docker start myweb

这里出现报错,因为我们的80端口被占用了

打开我们的站点可以发现我们的nginx仍然是在运行的

所以我们在使用 create 的时候,我们换一个端口就行了

bash 复制代码
docker create --name myweb1 -p 8050:80 nginx:1.23.3

将宿主机的8050端口映射到容器的80端口上了

2. docker logs

作用:查看容器日志

语法

bash 复制代码
docker logs [OPTIONS] CONTAINER
  • 参数

    • -f ,--follow:跟踪日志输出

    • --since:显示某个开始时间的所有日志

    • -t,--timestamps : 显示时间戳

    • -n,--tail :仅列出最新 N 条容器日志

bash 复制代码
docker logs myweb1

我们输入 exit 这个命令就直接退出了,我们再加上一个 -f 参数,跟踪日志输出,同时再加上 -n 可以查看前n条日志信息

bash 复制代码
lighthouse@VM-8-10-ubuntu:~$ docker logs myweb1 -f -n 5
2025/12/18 14:06:54 [notice] 29#29: exit
2025/12/18 14:06:54 [notice] 1#1: signal 17 (SIGCHLD) received from 28
2025/12/18 14:06:54 [notice] 1#1: worker process 28 exited with code 0
2025/12/18 14:06:54 [notice] 1#1: worker process 29 exited with code 0
2025/12/18 14:06:54 [notice] 1#1: exit

3. docker attach

作用:连接到正在运行中的容器。

bash 复制代码
docker attach [OPTIONS] CONTAINER
  • 参数
    • --sig-proxy:是否将所有信号代理,默认是 true,如果设置为 false,退出的话不会影响容器,否则退出会导致容器退出。
bash 复制代码
docker attach myweb2

这里可以看到我们 ctrl c就会让nginx接受到退出信号,会将容器直接杀死的

加上这个参数--sig-proxy:是否将所有信号代理,默认是 true,如果设置为 false,退出的话不会影响容器,否则退出会导致容器退出。

bash 复制代码
docker attach --sig-proxy=false myweb2

这里不会将容器杀死的

4. docker exec

作用:在容器中执行命令

bash 复制代码
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
#COMMAND就是我们要执行的命令
  • 参数

  • -d:分离模式: 在后台运行

  • -i:即使没有附加也保持 STDIN 打开

  • -t:分配一个伪终端

  • -e:设置环境变量

  • -u,--user:指定用户 "<name|uid>[:<group|gid>]"

  • -w,--workdir:指定工作目录

bash 复制代码
docker start myweb2 # 启动容器
docker exec -it  myweb2 bash #在容器中执行命令

查看nginx的详细版本

bash 复制代码
docker exec -it  myweb2 nginx -v

通过-e参数进行环境变量的设置操作

bash 复制代码
docker exec -it -e mynginx=kk myweb2 bash

指定某个用户,我们先查看有哪些用户

bash 复制代码
docker exec -it  myweb2 cat /etc/passwd

我们以nginx用户进行运行nginx的一个版本

bash 复制代码
docker exec -it  -u nginx myweb2 nginx -v

-w指定一个目录

bash 复制代码
docker exec -it   -w /etc  myweb2 bash

进入到容器中就可以发现是处在etc路径下的

如果不指定的话就是在根目录下

5. docker start

作用:启动停止的容器

bash 复制代码
docker start [OPTIONS] CONTAINER [CONTAINER...]

举例子

bash 复制代码
docker start mynginx

将停止的容器启动起来

6. docker stop

作用:停止正在运行的容器

bash 复制代码
docker stop [OPTIONS] CONTAINER [CONTAINER...]

参数

  • -s :发送的信号
bash 复制代码
docker stop myweb2

停止后进行查询可以发现我们的容器已经停止了

bash 复制代码
docker ps -a |grep myweb2

7. docker restart

作用:重启容器

bash 复制代码
docker restart [OPTIONS] CONTAINER [CONTAINER...]

参数

  • -s :发送信号

我们先在另一个终端上进行获取这个容器的日志信息

bash 复制代码
docker logs -f -n myweb2

再在另一个终端上进行重启操作

bash 复制代码
docker restart myweb2

查看相关的日志信息

8. docker kill

作用:强制退出容器

bash 复制代码
docker kill [OPTIONS] CONTAINER [CONTAINER...]

参数

  • -s:发送的信号

Docker stop 发送的是 SIGTERM 信号,docker kill 发送的是 SIGKILL 信号

bash 复制代码
docker kill myweb2

9. docker top

作用:查看容器中运行的进程信息,支持 ps 命令参数。

bash 复制代码
docker top CONTAINER [ps OPTIONS]

容器运行时不一定有/bin/bash 终端来交互执行 top 命令,而且容器还不一定有top 命令,可以使用 docker top 来实现查看 container 中正在运行的进程。

先启动一个容器

再查看容器内相关的进程信息

bash 复制代码
docker top 74a1273c093d

10. docker stats

作用:显示容器资源的使用情况,包括:CPU、内存、网络 I/O 等。

bash 复制代码
docker stats [OPTIONS] [CONTAINER...]

参数

  • --all , -a:显示所有的容器,包括未运行的。
  • --format:指定返回值的模板文件。如 table,json
  • --no-stream:展示当前状态就直接退出了,不再实时更新。
  • --no-trunc:不截断输出。

返回报文

  • CONTAINER ID 与 NAME: 容器 ID 与名称。
  • CPU % 与 MEM %: 容器使用的 CPU 和内存的百分比。
  • MEM USAGE / LIMIT: 容器正在使用的总内存,以及允许使用的内存总量。
  • NET I/O: 容器通过其网络接口发送和接收的数据量。
  • BLOCK I/O: 容器从主机上的块设备读取和写入的数据量。
  • PIDs: 容器创建的进程或线程数。

不带参数的情况下

bash 复制代码
docker stats

实时进行刷新操作

加上-a选项,会将所有容器都打印出来

bash 复制代码
docker stats -a

指定json格式进行数据的输出操作

bash 复制代码
docker stats --format json

展示当前状态就直接退出了,不再实时更新。

bash 复制代码
docker stats --no-stream

--no-trunc :不截断输出。

其实就是不截断我们的容器ID

bash 复制代码
docker stats --no-trunc

11. docker container inspect

作用:查看容器详细信息

bash 复制代码
docker container inspect [OPTIONS] CONTAINER [CONTAINER...]

参数

  • -f:指定返回值的模板文件。如 table、json
  • -s:显示总的文件大小。

注意事项:docker inspect 会自动检查是镜像还是容器然后显示相信信息

bash 复制代码
docker container inspect myweb2

将数据以json格式进行返回操作

bash 复制代码
docker container inspect -f json myweb2

如果加上-s的话是会将文件大小打印出来的

bash 复制代码
docker port

用于列出指定的容器的端口映射,或者查找将 PRIVATE_PORT NAT 到面向公众的端口。

bash 复制代码
docker port CONTAINER [PRIVATE_PORT[/PROTO]]
bash 复制代码
docker port myweb2

12. docker cp

作用:在容器和宿主机之间拷贝文件

bash 复制代码
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

我们先进入到容器中

bash 复制代码
docker exec -it myweb2 bash

进入到下面的路径中,可以发现这个index.html文件

bash 复制代码
cd /usr/share/nginx/html/

退出容器

bash 复制代码
exit

我们现在想将我们的容器中的index.html拷贝出来

bash 复制代码
docker cp myweb2:/usr/share/nginx/html/index.html .
#将指定容器下的这个目录下的这个文件拷贝到当前文件路径中

将文件内容进行修改,并且将本目录下的这个文件拷贝回容器

bash 复制代码
docker cp ./index.html myweb2:/usr/share/nginx/html/

进入到容器中进行文件内容查看,可以发现已经改变了

13. docker diff

作用:检查容器里文件结构的更改。

bash 复制代码
docker diff CONTAINER

示例

bash 复制代码
docker diff myweb2

我们进入到容器中增加一个文件,我们再查看具体的效果

bash 复制代码
docker exec -it myweb2 bash  #进入容器

docker diff myweb2

A就表示新增的

14. docker commit

作用:从容器创建一个新的镜像。

bash 复制代码
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

参数

  • -a:提交的镜像作者;
  • -c:使用 Dockerfile 指令来创建镜像;可以修改启动指令
  • -m:提交时的说明文字;
  • -p:在 commit 时,将容器暂停。
bash 复制代码
docker run -d --name myweb4forcommit nginx:1.23.3

检查是否正常运行

bash 复制代码
docker ps |grep myweb4forcommit
bash 复制代码
docker images myweb4  #一开始是没有信息的
docker commit myweb4forcommit myweb4:v1.0  # 从容器创建一个新的镜像。
docker images myweb4  # 就可以查看到我们的指定的myweb4的信息了

增加相关的参数

bash 复制代码
docker commit -a 'bit' -m 'create' -p myweb4forcommit myweb4:

可以查看到相关的信息

bash 复制代码
docker image inspect myweb4:v2.0 |grep bit

修改启动命令

查看相关信息

docker commit 就是使用容器创建一个新的镜像

15. docker pause

作用:暂停容器中所有的进程。

bash 复制代码
docker pause CONTAINER [CONTAINER...]

示例

bash 复制代码
docker pause 

先启动一个容器

容器正在运行中

将这个容器进行暂停操作

bash 复制代码
docker pause myweb5
docker ps |grep myweb5 #查看容器状态,发现变成了Paused暂停状态

将这个容器进行恢复的操作

bash 复制代码
docker unpause myweb5

16. docker unpause

作用:恢复容器中所有的进程。

bash 复制代码
docker unpause CONTAINER [CONTAINER...]

17. docker rm

作用:删除停止的容器

bash 复制代码
docker rm [OPTIONS] CONTAINER [CONTAINER...]

参数

  • -f:通过 SIGKILL 信号强制删除一个运行中的容器。

注意:不能 。在 Docker 中,无法直接 docker rm 一个正在运行的容器,除非使用强制删除选项。

如果 myweb1 正在运行,Docker 会报错:

复制代码
Error: Cannot remove a running container ...

正确做法(二选一):

方法 1:先 stop 再 rm(推荐)

bash 复制代码
docker stop myweb1
docker rm myweb1
  • stop 会发送 SIGTERM 信号,给容器机会优雅退出(如关闭连接、保存状态);
  • 若 10 秒内未退出,Docker 会发送 SIGKILL 强制终止;
  • 这是生产环境推荐做法,避免数据丢失或状态不一致。

方法 2:强制删除(等效于先 kill 再 rm)

bash 复制代码
docker rm -f myweb1
  • -f--force)会先发送 SIGKILL 强制杀死容器,再删除
  • 不会触发优雅退出逻辑 ,等同于 docker kill + docker rm
  • 适用于调试或容器已"假死"无法正常停止的场景;
  • 慎用于生产环境,尤其当容器内有未持久化的状态(如内存中的消息、临时文件)。

总结

方式 命令 是否优雅退出 适用场景
分步操作 docker stop + docker rm ✅ 是 生产环境、有状态服务
强制删除 docker rm -f ❌ 否 调试、卡死容器、无状态临时容器

💡 小技巧:若你经常需要"运行后自动清理"(如测试),启动时可加 --rm

bash 复制代码
docker run --rm -d --name myweb1 your-image

容器退出后会自动删除 ,无需手动 rm

18. docker export

作用:导出容器内容为 tar 文件,容器到镜像

bash 复制代码
docker export [OPTIONS] CONTAINER

参数

  • -o:写入到文件。

先运行一个容器

bash 复制代码
docker run -d --name myweb -p 8081:80  nginx:1.23.3

从容器转换为一个tar命令

bash 复制代码
docker export -o mweb.tar myweb

19. docker import

作用:从文档文件中创建镜像

bash 复制代码
docker import [OPTIONS] file|URL| - [REPOSITORY[:TAG]]

参数

  • -c :应用docker指令创建镜像
    -m:提交时的说明文字

当前文件夹是存在一个tar文件的

bash 复制代码
docker import mweb.tar myweb1:v1.0
docker images

这里就可以发现创建了一个镜像了,但是Docker import会丢失我们镜像源数据的信息

bash 复制代码
docker image inspect myweb1:v1.0
bash 复制代码
docker import  -c 'CMD ["nginx","-g","daemon off;"]' -m "creat by bit"  mweb.tar myweb7:v1.0
#将启动命令进行一个修改操作
bash 复制代码
docker image inspect myweb7:v1.0

这里就看到了我们指定的command了

这个docker import还是会出现镜像的数据的丢失操作

如果需要进行镜像迁移操作的话还是使用docker save和docker load即可

19. docker wait

作用:阻塞运行直到容器停止,然后打印出它的退出代码。

bash 复制代码
docker wait CONTAINER [CONTAINER...]

我们先在第一个终端启动上我们的容器,并且输入命令阻塞运行直到容器停止

bash 复制代码
docker wait myweb

在另一个终端强制杀死容器

bash 复制代码
docker kill myweb

在第一个终端就能看到我们容器的退出码了

20. docker rename

作用:重命名容器

bash 复制代码
docker rename CONTAINER NEW_NAME

创建一个相关的容器

bash 复制代码
docker run -d --name myweb9 nginx:1.23.3
bash 复制代码
docker rename myweb9 myweb8

21. docker container prune

作用:删除所有停止的容器

bash 复制代码
docker container prune [OPTIONS]

参数

  • -f, --force:不提示是否进行确认

当前存在很多停止的容器

输入下面命令

bash 复制代码
docker container prune

最后结果如下

22. docker update

作用:更新容器配置

bash 复制代码
docker update [OPTIONS] CONTAINER [CONTAINER...]

参数

  • --cpus:cpu 数量
  • --cpuset-cpus:使用哪些 cpu
  • --memory:内存限制
  • --memory-swap:交换内存
  • --cpu-period:是用来指定容器对 CPU 的使用要在多长时间内做一次重新分配
  • --cpu-quota:是用来指定在这个周期内,最多可以有多少时间用来跑这个容器
bash 复制代码
docker update -m 500m myweb

23. docker run

  • 功能: 创建一个新的容器并运行一个命令
  • 语法 : docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

参数

  • -d: 后台运行容器,并返回容器 ID;比 create 多了这个参数。

  • -i: 以交互模式运行容器,通常与 -t 同时使用。

  • -P: 随机端口映射,容器内部端口随机映射到主机的端口。

  • -p: 指定端口映射,格式为:主机(宿主)端口:容器端口。

  • -t: 为容器重新分配一个伪输入终端,通常与 -i 同时使用。

  • --name="nginx-lb": 为容器指定一个名称。

  • -h "mars": 指定容器的 hostname。

  • -e username="ritchie": 设置环境变量。

  • --cpuset-cpus="0-2" or --cpuset-cpus="0,1,2": 绑定容器到指定 CPU 运行。

  • -m: 设置容器使用内存最大值。

  • --network="bridge": 指定容器的网络连接类型。

  • --link=[]: 添加链接到另一个容器。

  • --volume , -v: 绑定一个卷。

  • --rm: shell 退出的时候自动删除容器。

  • --restart: 自动重启。

  • 样例 : docker run --name mynginx -d nginx:latest

24. docker ps

  • 功能: 列出容器
  • 语法 : docker ps [OPTIONS]

参数:

  • -a: 显示所有容器
  • -f: 根据条件过滤
  • --format: 指定返回值的模板文件
  • -l: 显示最新的容器
  • -n: 列出最近创建的 n 个容器
  • --no-trunc: 不截断输出
  • -q: 只显示容器编号
  • -s: 显示总的文件大小

25. 容器指令的区别

25.1 docker create、docker start和docker run之间的区别
  • docker create:从 Docker 镜像创建一个全新的容器,但不会立即运行。
  • docker start:启动任何已停止的容器。如果使用 docker create ,可以使用此命令启动。
  • docker run:(=create+start) 创建并立即启动一个新的容器。如果在系统上找不到所需镜像,会从 Docker Hub 中拉取。

详细分析

1. docker create [IMAGE]

  • 作用 :仅仅创建容器,但不启动它。

  • 过程

    • Docker 根据指定的镜像(IMAGE)创建一个新的、可写的容器层。
    • 为容器分配一个文件系统、网络配置和唯一的 ID。
    • 容器处于"已创建"(Created)状态。你可以通过 docker ps -a 命令看到它。
  • 使用场景

    • 当你想要在启动容器之前,对其进行详细配置时(例如,挂载卷、设置网络等)。
    • 可以预先创建好容器,然后在需要的时候再启动它,这有助于将配置和运行分离。
  • 示例

    bash 复制代码
    # 创建一个名为 my-nginx 的容器,但它不会运行
    docker create --name my-nginx nginx

    执行后,你看不到任何正在运行的 Nginx 服务,但 docker ps -a 会列出这个处于 Created 状态的容器。

2. docker start [CONTAINER]

  • 作用 :启动一个已经存在的、处于"已停止"(Exited)或"已创建"(Created)状态的容器。

  • 过程

    • 找到指定的容器(CONTAINER)。
    • 将容器的状态从 CreatedExited 变为 Up(运行中)。
    • 容器内的主进程开始执行。
  • 使用场景

    • 重新启动一个之前已经停止的容器。
    • 启动一个由 docker create 命令创建好的容器。
  • 示例

    bash 复制代码
    # 启动上面创建的 my-nginx 容器
    docker start my-nginx

    现在,Nginx 服务就在后台开始运行了。你可以通过 docker ps 命令看到它的状态是 Up

3. docker run [IMAGE]

  • 作用 :这是一个复合命令,它创建并立即启动一个新容器。它是最常用的容器启动命令。

  • 过程

    1. 检查镜像:检查本地是否存在指定的镜像。如果不存在,会尝试从 Docker Hub(或配置的其他镜像仓库)拉取。
    2. 创建容器 (等于 docker create):基于该镜像创建一个新的容器。
    3. 启动容器 (等于 docker start):立即启动这个刚刚创建的容器。
    4. 附加到主进程(可选) :默认情况下,docker run 会将你的终端附加(attach)到容器的主进程的标准输入、输出和错误流上。这就是为什么你运行 docker run ubuntu bash 后会直接进入容器的 shell。
  • 使用场景

    • 绝大多数情况下,当你需要快速启动一个新容器时,都会使用 docker run
  • 示例

    bash 复制代码
    # 一步完成创建并启动一个名为 my-nginx-2 的 Nginx 容器
    # -d 参数表示在后台(detached mode)运行
    docker run --name my-nginx-2 -d nginx

    这个命令执行后,会直接创建一个名为 my-nginx-2 的容器,并在后台启动它。docker ps 会立即显示这个正在运行的容器。

总结与对比

命令 检查镜像 创建容器 启动容器 主要特点
docker create 只创建,不运行,返回容器 ID。
docker start 启动一个已存在的容器。
docker run 创建并立即启动,是 create + start 的组合。

简单记就是:docker run = docker create + docker start

25.2 docker import和dokcer load之间的区别

它们都用于从 tar 归档文件中创建镜像,但它们的来源、目的和结果完全不同。

  • docker save 将一个镜像导出为文件,使用 docker load 导入为镜像,保存所有完整元数据和历史记录(迁移时建议使用这个)
  • docker export将一个容器导出为文件,使用 docker import 导入为新的镜像,丢失所有元数据和历史记录。

区别对比

1. docker load

  • 输入源 :只能是 docker save 命令创建的 tar 归档文件。
  • 输入内容 :这个 tar 文件是一个完整的镜像仓库,包含了镜像的所有层(layers)、标签(tags)、历史记录以及元数据(如 Dockerfile 中的 CMD, ENTRYPOINT 指令等)。 docker save 可以将多个镜像打包到同一个 tar 文件中。
  • 输出结果 :在 Docker 主机中恢复一个或多个与保存时一模一样的镜像。 镜像的 ID、层级结构、历史记录和标签都会被完整保留。
  • 主要用途
    • 离线传输镜像:在没有 Docker Registry 的环境中(如气密网络或内网),将一台机器上的镜像完整地迁移到另一台机器上。
    • 备份和恢复:对重要的镜像进行完整备份,以便将来可以精确恢复。
  • 工作流程
    1. 在源机器上: docker save my-image:latest > my-image.tar
    2. my-image.tar 文件拷贝到目标机器
    3. 在目标机器上: docker load < my-image.tardocker load -i my-image.tar

2. docker import

  • 输入源 :可以是由 docker export 命令创建的容器文件系统快照的 tar 文件,也可以是任何包含文件系统的 tar 归档(例如,一个全新操作系统的根文件系统)。
  • 输入内容 :这个 tar 文件仅仅是文件和目录的集合,它不包含任何 Docker 镜像的层级信息、历史记录或元数据。 docker export 会将一个正在运行或已停止的容器的文件系统打包,但会丢失所有与镜像历史相关的信息。
  • 输出结果 :创建一个全新的扁平化的 (只有一个层)Docker 镜像。 这个新镜像没有任何历史记录。你可以为它指定一个新的仓库名和标签。由于元数据丢失,像 CMDEXPOSE 这样的指令需要在使用 docker import 时通过 -c (--change) 参数重新指定。
  • 主要用途
    • 创建基础镜像:从头开始创建一个新的基础镜像。例如,你可以通过一个最小化的 Linux 文件系统 tar 包来创建一个自定义的基础镜像。
    • "扁平化"镜像:将一个现有的多层镜像转换成一个只有单层的镜像,以减小体积或隐藏构建历史。
    • 迁移虚拟机或物理机:将现有系统的文件系统打包,然后导入到 Docker 中作为一个镜像来运行。
  • 工作流程
    1. (可选)从一个容器创建快照: docker export my-container > my-container.tar
    2. 导入文件系统创建新镜像: cat my-container.tar | docker import - my-new-image:latest

总结对比

特性 docker load docker import
对应命令 docker save docker export (或任何文件系统 tar 包)
输入文件 完整的镜像归档 文件系统快照归档
保留镜像历史/层 ,完全保留 ,创建一个新的单层镜像
保留元数据 (标签, CMD, ENTRYPOINT 等) (会丢失,但可通过 --change 参数添加)
主要场景 镜像的迁移、备份和恢复 创建新的基础镜像、扁平化镜像
25.3 docker rm &docker rmi&docker prune之间的区别

简单来说:

  • docker rm :删除容器 (Container)。
  • docker rmi :删除镜像 (Image)。
  • docker prune :批量清理无用的资源(容器、镜像、卷、网络等)。

核心对比

1. docker rm - 删除容器

  • 目标对象:容器 (Container)。

  • 作用 :从 Docker 主机中删除一个或多个已经停止的容器。

  • 关键点

    • 默认情况下,你不能删除一个正在运行的容器。如果尝试这样做,Docker 会报错。
    • 要强制删除一个正在运行的容器,可以使用 -f--force 标志。这会先向容器发送 SIGKILL 信号停止它,然后再删除。
    • 删除容器会移除容器的可写层,但默认不会 删除与之关联的卷 (Volume)。如果要同时删除匿名卷,需要加上 -v--volumes 标志。
  • 使用场景

    • 当你明确知道要删除哪个容器时。
    • 清理那些已经完成任务并停止的容器,以释放它们占用的少量磁盘空间和避免容器列表混乱。
  • 示例

    bash 复制代码
    # 删除一个名为 my-container 的已停止容器
    docker rm my-container
    
    # 强制删除一个正在运行的容器
    docker rm -f my-running-container
    
    # 删除一个容器并移除其关联的匿名卷
    docker rm -v my-container-with-volume

2. docker rmi - 删除镜像

  • 目标对象 :镜像 (Image)。i 就代表 "image"。

  • 作用:从 Docker 主机中删除一个或多个本地镜像。

  • 关键点

    • 默认情况下,你不能删除一个被任何容器(即使是已停止的容器)引用的镜像。必须先用 docker rm 删除所有依赖该镜像的容器,然后才能删除镜像。
    • 可以使用 -f--force 标志来强制删除镜像,即使有容器依赖它。这是一个危险操作,不推荐常规使用,因为它会产生"悬空"的容器(dangling containers)。
    • 如果一个镜像有多个标签(例如 my-image:latestmy-image:v1.0 指向同一个镜像 ID),删除其中一个标签不会删除镜像本身,只会移除那个标签。只有当最后一个指向该镜像的标签被移除后,镜像才会被真正删除。
  • 使用场景

    • 清理不再需要的、过时的或者下载错误的镜像,以释放大量的磁盘空间。
  • 示例

    bash 复制代码
    # 删除一个名为 my-image:latest 的镜像
    docker rmi my-image:latest
    
    # 通过镜像 ID 删除镜像
    docker rmi 2a4d8108420f

3. docker prune - 清理无用资源

  • 目标对象:所有类型的无用 Docker 资源。它是一系列清理命令的统称。

  • 作用:这是一个"清道夫"命令,用于批量、自动地查找并删除不再使用的资源。

  • 关键点

    • 这是一个命令族,最常用的是 docker system prune
    • 它只会删除无用(dangling 或 unused)的资源,不会影响任何正在运行或被引用的资源,因此相对安全。
  • 常见的 prune 命令

    • docker container prune: 删除所有已停止 的容器。相当于对所有停止的容器执行 docker rm
    • docker image prune: 默认只删除悬空镜像 (dangling images),即那些没有标签且不被任何容器引用的镜像。使用 -a 标志 (docker image prune -a) 会删除所有未使用的镜像(即没有任何容器引用的镜像,无论有无标签)。
    • docker volume prune: 删除所有未使用的本地卷。
    • docker network prune: 删除所有未使用的自定义网络。
    • docker system prune: 最常用的清理命令 。它会一次性执行:
      • docker container prune
      • docker network prune
      • docker image prune (只清理悬空镜像)
      • 清理构建缓存。
    • docker system prune -a: 终极清理命令 。它会执行 docker system prune 的所有操作,并且还会删除所有未使用 的镜像(等同于 docker image prune -a),而不仅仅是悬空镜像。
  • 使用场景

    • 当你想要快速释放磁盘空间,而不想手动一个个去查找和删除无用资源时。
    • 定期对开发环境进行维护和清理。

总结与对比

命令 操作对象 粒度 核心功能
docker rm [name/id] 容器 精确 删除一个或多个指定的容器。
docker rmi [name/id] 镜像 精确 删除一个或多个指定的镜像。
docker ... prune 容器、镜像、卷、网络 批量 自动清理所有符合"无用"条件的资源。

简单记忆

  • 想删某个容器 ,用 docker rm
  • 想删某个镜像 ,用 docker rmi
  • 大扫除 ,清理所有没用的东西,用 docker system prune

三:🔥 容器操作

1. 容器基本操作

① 查看本地nginx镜像

bash 复制代码
docker images nginx

② 创建并且启动一个容器

bash 复制代码
lighthouse@VM-8-10-ubuntu:~$ docker run -d --name myweb1 -p 8090:80 nginx:1.23.3
Unable to find image 'nginx:1.23.3' locally
1.23.3: Pulling from library/nginx
f1f26f570256: Pull complete 
84181e80d10e: Pull complete 
1ff0f94a8007: Pull complete 
d776269cad10: Pull complete 
e9427fcfa864: Pull complete 
d4ceccbfc269: Pull complete 
Digest: sha256:f4e3b6489888647ce1834b601c6c06b9f8c03dee6e097e13ed3e28c01ea3ac8c
Status: Downloaded newer image for nginx:1.23.3
b7646a55455d0a273f306d7e66d9c2458ecc6304b0b5400af65e3c3d3e464cce

因为我们本地是没有这个版本的,所以进行了一个镜像拉取的操作

③ 查看容器相关信息

bash 复制代码
docker ps	 					# 1. 查看容器正常运行
docker container inspect myweb2 # 2. 查看容器具体详情
docker logs -f myweb2			# 3. 查看相关的日志

④ 容器资源的查看

bash 复制代码
docker stats myweb2
docker top myweb2 aux # 注意: 这个只能查看 running 下的容器

⑤ 停止并且清理这个容器

bash 复制代码
docker stop myweb1 
docker rm  myweb1

2. 容器状态迁移

① 创建容器

bash 复制代码
docker create --name myweb2 -p 8079:80 nginx:1.23.3
  • 此时我们的容器还是没有运行的,仅仅是被创建了的

② 查看容器状态(已创建)

bash 复制代码
lighthouse@VM-8-10-ubuntu:~$ docker ps -a | grep myweb2
b7646a55455d   nginx:1.23.3   "/docker-entrypoint...."   About an hour ago   Exited (0) 11 seconds ago                                                                                                  myweb2

③ 启动容器

bash 复制代码
docker start myweb2

④ 杀掉正在运行的容器

bash 复制代码
docker kill myweb2

⑤ 启动容器,然后暂停容器

bash 复制代码
docker start myweb2
docker stop myweb2

⑥ 让容器重启,让容器先stop在start

bash 复制代码
docker restart myweb2

可以发现运行时长重新刷新了

⑦ 启动容器,然后暂停容器

bash 复制代码
docker start mynginx1
docker pause mynginx1
docker ps

解除暂停状态

bash 复制代码
docker unpause myweb2

lighthouse@VM-8-10-ubuntu:~$ docker ps -a | grep myweb2
b7646a55455d   nginx:1.23.3   "/docker-entrypoint...."   About an hour ago   Up About an hour   0.0.0.0:8090->80/tcp, [::]:8090->80/tcp                                                        myweb2                     

⑧ 删除容器

bash 复制代码
docker stop mynginx1
docker rm mynginx1
docker ps -a | grep mynginx1
容器批量处理技巧

3. 容器的批量搜索技巧

命令 解释
docker container ls -qf name=xxx 根据名称过滤得到容器编号
docker container ls --filter status=running 根据状态过滤容器信息
docker container ls -aq 静默获取全部容器 id
docker container ls --filter ancestor=xxx 过滤镜像名为 xxx 的容器信息
docker container ls --filter ancestor=xxx 过滤镜像 id 为 xxx 的容器信息
  • -a: 表示打印所有的容器信息,包括正在运行和已经退出的
  • -q: 表示只返回容器 ID
  • -f: 表示基于给的条件过滤 等价于 --filter 选项

当前存在如下几个容器:

bash 复制代码
lighthouse@VM-8-10-ubuntu:~$ docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED        STATUS                       PORTS                                                                                          NAMES
b7646a55455d   nginx:1.23.3   "/docker-entrypoint...."   2 hours ago    Exited (137) 2 seconds ago                                                                                                  myweb2
e0015885d20f   nginx:1.23.4   "/docker-entrypoint...."   3 hours ago    Created                                                                                                                     myweb1
51c634e94f68   redis:5.0.9    "docker-entrypoint.s..."   5 months ago   Up 3 months                  0.0.0.0:6381->6379/tcp, [::]:6381->6379/tcp, 0.0.0.0:16381->16379/tcp, [::]:16381->16379/tcp   redis11
42a5fddc884e   redis:5.0.9    "docker-entrypoint.s..."   5 months ago   Up 3 months                  0.0.0.0:6376->6379/tcp, [::]:6376->6379/tcp, 0.0.0.0:16376->16379/tcp, [::]:16376->16379/tcp   redis6
5fd2380f7035   redis:5.0.9    "docker-entrypoint.s..."   5 months ago   Up 3 months                  0.0.0.0:6377->6379/tcp, [::]:6377->6379/tcp, 0.0.0.0:16377->16379/tcp, [::]:16377->16379/tcp   redis7
c882807c8a1e   redis:5.0.9    "docker-entrypoint.s..."   5 months ago   Up 3 months                  0.0.0.0:6380->6379/tcp, [::]:6380->6379/tcp, 0.0.0.0:16380->16379/tcp, [::]:16380->16379/tcp   redis10
9e0c289185f2   redis:5.0.9    "docker-entrypoint.s..."   5 months ago   Up 3 months                  0.0.0.0:6371->6379/tcp, [::]:6371->6379/tcp, 0.0.0.0:16371->16379/tcp, [::]:16371->16379/tcp   redis1
dca3a197567b   redis:5.0.9    "docker-entrypoint.s..."   5 months ago   Up 3 months                  0.0.0.0:6375->6379/tcp, [::]:6375->6379/tcp, 0.0.0.0:16375->16379/tcp, [::]:16375->16379/tcp   redis5
ed3864c22dcd   redis:5.0.9    "docker-entrypoint.s..."   5 months ago   Up 3 months                  0.0.0.0:6374->6379/tcp, [::]:6374->6379/tcp, 0.0.0.0:16374->16379/tcp, [::]:16374->16379/tcp   redis4
8356fd4d661a   redis:5.0.9    "docker-entrypoint.s..."   5 months ago   Up 3 months                  0.0.0.0:6372->6379/tcp, [::]:6372->6379/tcp, 0.0.0.0:16372->16379/tcp, [::]:16372->16379/tcp   redis2
bf999dd1a29b   redis:5.0.9    "docker-entrypoint.s..."   5 months ago   Up 3 months                  0.0.0.0:6378->6379/tcp, [::]:6378->6379/tcp, 0.0.0.0:16378->16379/tcp, [::]:16378->16379/tcp   redis8
2fc644e0143d   redis:5.0.9    "docker-entrypoint.s..."   5 months ago   Up 3 months                  0.0.0.0:6373->6379/tcp, [::]:6373->6379/tcp, 0.0.0.0:16373->16379/tcp, [::]:16373->16379/tcp   redis3

① 通过名字进行过滤操作

bash 复制代码
docker ps -f name=redis #示例

lighthouse@VM-8-10-ubuntu:~$ docker ps -f name=redis
CONTAINER ID   IMAGE         COMMAND                  CREATED        STATUS        PORTS                                                                                          NAMES
51c634e94f68   redis:5.0.9   "docker-entrypoint.s..."   5 months ago   Up 3 months   0.0.0.0:6381->6379/tcp, [::]:6381->6379/tcp, 0.0.0.0:16381->16379/tcp, [::]:16381->16379/tcp   redis11
42a5fddc884e   redis:5.0.9   "docker-entrypoint.s..."   5 months ago   Up 3 months   0.0.0.0:6376->6379/tcp, [::]:6376->6379/tcp, 0.0.0.0:16376->16379/tcp, [::]:16376->16379/tcp   redis6
5fd2380f7035   redis:5.0.9   "docker-entrypoint.s..."   5 months ago   Up 3 months   0.0.0.0:6377->6379/tcp, [::]:6377->6379/tcp, 0.0.0.0:16377->16379/tcp, [::]:16377->16379/tcp   redis7
c882807c8a1e   redis:5.0.9   "docker-entrypoint.s..."   5 months ago   Up 3 months   0.0.0.0:6380->6379/tcp, [::]:6380->6379/tcp, 0.0.0.0:16380->16379/tcp, [::]:16380->16379/tcp   redis10
9e0c289185f2   redis:5.0.9   "docker-entrypoint.s..."   5 months ago   Up 3 months   0.0.0.0:6371->6379/tcp, [::]:6371->6379/tcp, 0.0.0.0:16371->16379/tcp, [::]:16371->16379/tcp   redis1
dca3a197567b   redis:5.0.9   "docker-entrypoint.s..."   5 months ago   Up 3 months   0.0.0.0:6375->6379/tcp, [::]:6375->6379/tcp, 0.0.0.0:16375->16379/tcp, [::]:16375->16379/tcp   redis5
ed3864c22dcd   redis:5.0.9   "docker-entrypoint.s..."   5 months ago   Up 3 months   0.0.0.0:6374->6379/tcp, [::]:6374->6379/tcp, 0.0.0.0:16374->16379/tcp, [::]:16374->16379/tcp   redis4
8356fd4d661a   redis:5.0.9   "docker-entrypoint.s..."   5 months ago   Up 3 months   0.0.0.0:6372->6379/tcp, [::]:6372->6379/tcp, 0.0.0.0:16372->16379/tcp, [::]:16372->16379/tcp   redis2
bf999dd1a29b   redis:5.0.9   "docker-entrypoint.s..."   5 months ago   Up 3 months   0.0.0.0:6378->6379/tcp, [::]:6378->6379/tcp, 0.0.0.0:16378->16379/tcp, [::]:16378->16379/tcp   redis8
2fc644e0143d   redis:5.0.9   "docker-entrypoint.s..."   5 months ago   Up 3 months   0.0.0.0:6373->6379/tcp, [::]:6373->6379/tcp, 0.0.0.0:16373->16379/tcp, [::]:16373->16379/tcp   redis3

② 根据 容器状态 进行过滤操作

bash 复制代码
docker ps -f status=running
docker ps -f status=exited

③ 通过 镜像名 进行获取操作

bash 复制代码
docker ps -f ancestor=nginx:1.23.4

④ 通过 镜像ID 进行过滤操作

bash 复制代码
docker ps -f ancestor=ac232364af84

⑤ 补充 :可以在上面的基础上后面加上-a 以及-q 参数

bash 复制代码
docker ps -f ancestor=ac232364af84 -a # 作用: 显示所有的容器

docker ps -f ancestor=ac232364af84 -q # 作用: 只返回ID信息

4. 容器的批量操作

① 批量化停止

bash 复制代码
docker ps -a # 全部查询, 可以看到一批正在运行容器
docker ps -q # ID 过滤

docker stop `docker ps -q` # 将这些容器的ID给 `docker stop` 进行批量停止操作

② 批量化启动

bash 复制代码
docker ps -a -q 				# 获取此时停止的容器ID
docker start `docker ps -a -q`	# 进行批量化的启动操作

5. 容器的交互模式

5.1 attached 模式
  • 描述 :执行docker run命令时不添加-it-d参数,容器将进入Attach模式。在此模式下,终端会持续阻塞并显示容器日志。
  • 示例:启动nginx容器。
  • 特点 :终端显示容器日志,ctrl + c可终止容器,但会导致容器退出。通常不推荐在开发环境中使用,日志查看可通过docker logs实现。
bash 复制代码
docker run nginx
5.2 Detached模式
  • 描述 :通过添加-d--detach参数运行容器,容器将在 后台运行,即Detached模式。此模式下,容器不会因终端中断而退出。
  • 示例:以Detached模式启动nginx容器。
  • 特点 :容器后台运行,不受终端ctrl + c影响。若需在容器内执行命令,可使用docker exec
cpp 复制代码
docker run -d nginx
5.3 Interactive模式
  • 描述 :容器运行后,如需进行复杂操作,可使用docker exec -it ... bash命令组合进入Interactive模式,通过bash终端操作容器。
  • 示例:进入运行中的mynginx容器。
cpp 复制代码
docker exec -it mynginx bash
  • 特点 :输入exit退出终端,避免使用ctrl + c以防容器退出。

6. 容器与宿主机内容复制

① 先创建并启动一个容器

bash 复制代码
docker run -d --name mynginx -p 8080:80 nginx:1.23.3

② 将首页文件拷贝出来进行编辑操作,通过exec对容器进行一个交互操作

bash 复制代码
docker exec -it mynginx  bash

# 操作如下: 
lighthouse@VM-8-10-ubuntu:~$ docker exec -it mynginx bash
#查看 index.html 位置, 之前这个有说明
root@b060ca49679e:/# cd /usr/share/nginx/html
root@b060ca49679e:/usr/share/nginx/html# ls
50x.html  index.html

# 查看 index.html 内容
root@b060ca49679e:/usr/share/nginx/html# cat index.html
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>		
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

注意:容器中我们是不能进行vim操作的,所以只能拷贝到宿主机上进行内容修改操作

bash 复制代码
root@b060ca49679e:/usr/share/nginx/html# vim index.html
bash: vim: command not found

# 1. 拷贝到宿主机上操作
lighthouse@VM-8-10-ubuntu:~$ docker cp mynginx:/usr/share/nginx/html/index.html .
Successfully copied 2.56kB to /home/lighthouse/.
lighthouse@VM-8-10-ubuntu:~$ ls
code  index.html  install  myenv  semnum

# 2. 对文件进行一个编辑操作
lighthouse@VM-8-10-ubuntu:~$ vim index.html
# 3. 将文件拷贝回去
lighthouse@VM-8-10-ubuntu:~$ docker cp ./index.html mynginx:/usr/share/nginx/html/index.html
Successfully copied 2.56kB to mynginx:/usr/share/nginx/html/index.html

# 4. 回到容器中进行检查操作
lighthouse@VM-8-10-ubuntu:~$ docker exec -it mynginx bash
root@b060ca49679e:/# cat /usr/share/nginx/html/index.html
<!DOCTYPE html>
<html>
<head>
<title>I Love You!</title>			# 变成了 I Love You 了 
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

7. 容器自动删除

带上参数 --rm 就会自动进行删除操作了,交互式的容器

示例:创建一个容器并且进行运行操作

bash 复制代码
docker run -it --rm --name mynginx01 -p 8081:80 nginx:1.23.3 bash
  • 当我们的这个容器退出了,我们在另一个终端查看就找不到我们的这个容器了,退出就删除了

8. 容器的自动重启

容器重启选项如下:

  • docker run --restart=no [容器名]:默认值不自动重启
  • docker run --restart=on-failure:3 [容器名] :on-failure 若容器的退出状态非 0,则 docker 自动重启容器,还可以指定重启次数,若超过指定次数未能启动容器则放弃
  • docker run --restart=always [容器名]:always 容器退出时总是重启
  • docker run --restart=unless-stopped [容器名]:unless-stopped 容器退出时总是重启,但不考虑 Docker 守护进程启动时就已经停止的容器

① 创建一个会自动重启的容器,我们针对这个容器指定了一个策略:--restart=always

bash 复制代码
docker run -d --name mynginx1 -p 8125:80 --restart=always nginx:1.23.3


lighthouse@VM-8-10-ubuntu:~$ docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                                                                                          NAMES
4206f8077eab   nginx:1.23.3   "/docker-entrypoint...."   37 seconds ago   Up 36 seconds   0.0.0.0:8125->80/tcp, [::]:8125->80/tcp                                                        mynginx1

可以看到我们的容器是在正常运行的

② 我们查看相关的容器策略

bash 复制代码
docker container inspect mynginx1

可以找到这么一个描述字段

bash 复制代码
"RestartPolicy": {
    "Name": "always",
    "MaximumRetryCount": 0
},

③ 接下来我们进入到容器中将nginx停止掉

bash 复制代码
docker exec -it mynginx1  bash

④ 在另一个终端进行监视

bash 复制代码
docker ps

⑤ 对原终端进行操作

bash 复制代码
nginx -s quit # 停止nginx
docker ps     # 打开监控一看可以看到容器重启了

但是我们执行 stop 就不会让上面的重启策略生效了

bash 复制代码
docker stop mynginx1

9. 容器环境变量的设置

① 启动一个nginx容器,通过 -e 选项进行环境变量的设置操作

bash 复制代码
docker run  -it --rm -e MYTEST=1 --name mynginx1 -p 8081:80 nginx:1.23.3 bash

# 输出
lighthouse@VM-8-10-ubuntu:~$ docker run  -it --rm -e MYTEST=1 --name mynginx1 -p 8081:80 nginx:1.23.3 bash
root@dd777034751a:/# env
HOSTNAME=dd777034751a
PWD=/
PKG_RELEASE=1~bullseye
HOME=/root
NJS_VERSION=0.7.9
TERM=xterm
SHLVL=1
MYTEST=1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_VERSION=1.23.3
_=/usr/bin/env

② 通过环境变量的一个配置文件配置环境变量,将需要配置的环境变量写入到文件中

bash 复制代码
lighthouse@VM-8-10-ubuntu:~$ vim myenv
lighthouse@VM-8-10-ubuntu:~$ cat myenv
mytest1=1
mytest2=2
mytest3=3
mytest4=4

③ 查看环境变量

bash 复制代码
lighthouse@VM-8-10-ubuntu:~$ docker run -it --rm --env-file=./myenv nginx:1.23.3 bash
root@76af887fbf40:/# env
HOSTNAME=76af887fbf40
PWD=/
PKG_RELEASE=1~bullseye
HOME=/root
NJS_VERSION=0.7.9
TERM=xterm
SHLVL=1
mytest4=4
mytest1=1
mytest3=3
mytest2=2
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_VERSION=1.23.3
_=/usr/bin/env
root@76af887fbf40:/# env | grep mytest
mytest4=4
mytest1=1
mytest3=3
mytest2=2

10. 容器快速诊断

bash 复制代码
docker run --rm busybox:1.36.0 ifconfig

输出

bash 复制代码
lighthouse@VM-8-10-ubuntu:~$ docker run --rm busybox:1.36.0 ifconfig
eth0      Link encap:Ethernet  HWaddr 06:96:63:D8:12:17  
          inet addr:172.17.0.3  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:90 (90.0 B)  TX bytes:42 (42.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

更准确地说,这是一种 "一次性容器"(ephemeral container)的典型用法

实际目的:通过运行一个轻量、干净、隔离的容器快速查看容器内部的网络环境,比如:

  • 容器分配到了什么 IP?
  • 是否有网络接口?
  • 是否能和其他容器通信?(结合 pingtelnet 等)

这在以下场景非常有用:

场景 用途
学习 Docker 网络 看容器默认 IP 范围(如 172.17.0.0/16
排查服务连通性 busyboxnicolaka/netshoot 容器测试 DNS、端口、路由
验证网络隔离 确认容器之间/与宿主机的网络是否按预期隔离

🌰 举个实际例子

假设你部署了一个微服务,但发现它无法访问 Redis。你可以:

bash 复制代码
# 用 busybox 临时测试网络
docker run --rm busybox ping 172.17.0.5      # 能 ping 通 Redis 容器吗?
docker run --rm busybox nslookup my-redis     # DNS 解析正常吗?
docker run --rm busybox telnet 172.17.0.5 6379  # 端口通吗?

💡 这些操作不会影响你的主应用容器 ,用完即焚(因为 --rm),非常安全高效。

虽然 ifconfig 直观,但 Linux 社区已转向更强大的 ip 命令:

bash 复制代码
docker run --rm busybox ip addr show	# 等效于 ifconfig
docker run --rm busybox ip route		# 查看路由

注意nginx 没有内置 ifconfig 工具,如下:

bash 复制代码
lighthouse@VM-8-10-ubuntu:~$ docker run --rm nginx:1.23.3 ifconfig
/docker-entrypoint.sh: 47: exec: ifconfig: not found

根本原因:ifconfig 工具是否存在于容器镜像中

  • busybox:1.36.0 :BusyBox 是一个集成了大量 Unix 工具的精简系统 ,其中包括 ifconfigpingtelnet 等常用网络命令。
    → 所以 ifconfig 可以正常运行。
  • nginx:1.23.3 :官方 Nginx 镜像基于 Debian (或 Alpine,取决于标签),但为了最小化镜像体积默认不包含 ifconfignetstatping 等网络调试工具
    → 所以执行 ifconfig 时报错:not found

💡 实际上,nginx:1.23.3(非 -alpine 后缀)是基于 Debian 的,但即使如此,Debian 镜像在 Docker 优化中也移除了 net-tools 包(ifconfig 所在包)。

11. 容器导入导出

① 创建容器并且查看运行情况

bash 复制代码
docker run -d --name mynginx -p  8085:80 nginx:1.23.3

② 进入到容器中进行文件的修改操作(类似于之前的 内容复制 内容那)

bash 复制代码
docker exec -it mynginx bash
cd /usr/share/nginx/html

# 示例
lighthouse@VM-8-10-ubuntu:~$ docker run -d --name mynginx -p  8085:80 nginx:1.23.3
b517812ccc7ce9ebde17eefdedfb906d5d9e58555f1c9dcbe9f6fd1495955662
lighthouse@VM-8-10-ubuntu:~$ docker exec -it mynginx bash
root@b517812ccc7c:/# cd /usr/share/nginx/html
root@b517812ccc7c:/usr/share/nginx/html# echo "Island1314" > index.html 
root@b517812ccc7c:/usr/share/nginx/html# cat index.html
Island1314

③ 对容器进行一个打包操作

bash 复制代码
lighthouse@VM-8-10-ubuntu:~$ docker export -o mynginx.tar mynginx
lighthouse@VM-8-10-ubuntu:~$ ls
code  install  myenv  mynginx.tar  semnum

④ 将我们的tar包还原成一个镜像,我们将当前的tar包发送到另一个服务器中

bash 复制代码
scp mynginx.tar root@123.60.26.220:/root/mydir

⑤ 文件发送到本地之后

bash 复制代码
docker import mynginx.tar mynginx:v0.30

# 示例
[root@hcss-ecs-28de mydir]# ls
mynginx.tar
[root@hcss-ecs-28de mydir]# docker import mynginx.tar mynginx:v0.30
sha256:83bfbb1c9165637ccd7e26a666cd82094822e84f011224450fe65bcba020e634
[root@hcss-ecs-28de mydir]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
mynginx				 v0.30	  83bfbb1c9165   6 seconds ago    140MB
busybox				 1.36.0	  af2c3e96bcf1	 2 years ago      4.86MB

⑥ 创建一个容器

bash 复制代码
docker run -d --name 001 -p 8081:80 mynginx:v0.30

这里发现不能识别,因为我们导入的时候 docker import 会将相关的数据丢失了

bash 复制代码
docker image inspect mynginx:v0.30

这个就是docker import的一个问题,会丢失相关的源数据,那么我们就将命令加回来,补回 command 信息

bash 复制代码
docker run -d --name 001 -p 8081:80 mynginx:v0.30 nginx -g "daemon off;"

四:🔥 容器实战案例

1. Mysql容器化安装

1.1 下载安装

① 进入 mysql 的镜像网站(mysql docker hub 官网,),查找 mysql 的镜像,可以看到有这么多的 tag

② 选择使用最多的 5.7 版本,拉取镜像

bash 复制代码
docker pull mysql:5.7

可以看到我们的 mysql 镜像,如下:

bash 复制代码
lighthouse@VM-8-10-ubuntu:~$ docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
mysql                5.7       5107333e08a8   2 years ago     501MB

③ 启动一个 MySQL 容器,并指定密码和端口开放

bash 复制代码
docker run --name mysql -e MYSQL_ROOT_PASSWORD=123 -p 8201:3306 -d mysql:5.7

这里指定的密码是:123456

参数 作用说明
-e MYSQL_ROOT_PASSWORD=123 设置环境变量,这是官方 MySQL 镜像要求的 ,用于初始化 root 密码 ⚠️ 注意:密码为 123 太弱,仅用于测试
-p 8201:3306 端口映射 :将宿主机的 8201 端口 → 容器内的 3306 端口
-d 后台运行(detached mode)

❓ 为什么容器内部端口是 3306?

这里的 3306 是 MySQL 官方默认的监听端口**,这是由 MySQL 服务器程序本身约定的,不是 Docker 决定的。

具体原因:

  • MySQL 在设计时,默认配置文件(my.cnf)中指定 port = 3306
  • 当 MySQL 启动时,会自动在这个端口上监听客户端连接;
  • 这是 IANA(互联网编号分配机构)注册的官方端口,属于"公认端口"(Well-known port)范围(0~1023);
  • 几乎所有 MySQL 客户端(如 mysql 命令、JDBC、Navicat)默认连接 3306,除非显式指定其他端口。

📌 所以:3306 是 MySQL 的"行业标准端口",就像:

  • HTTP → 80
  • HTTPS → 443
  • Redis → 6379

④ 容器创建好了之后,输入命令进行mysql的启动操作

bash 复制代码
lighthouse@VM-8-10-ubuntu:~$ docker run --name mysql -e MYSQL_ROOT_PASSWORD=123 -p 8201:3306 -d mysql:5.7
69f6d1cf10352a5521f4cf3bc8c9ebca08f70843284d5d12c741e04c9b0d0176
lighthouse@VM-8-10-ubuntu:~$ docker exec -it mysql bash
bash-4.2# mysql -u root -p
Enter password: 

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.44 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 
1.2 测试

① 输入mysql命令查询当前的库数据

bash 复制代码
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

② 查询Mysql版本

bash 复制代码
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.44    |
+-----------+
1 row in set (0.00 sec)

③ 创建数据库和表

bash 复制代码
create database test_db;

④ 使用数据库

bash 复制代码
use test_db;

⑤ 创建一个表并进行查看操作

bash 复制代码
create table test_user(name varchar(50),age int);

show tables;

⑥ 进行数据的插入操作并进行数据查看

bash 复制代码
insert into test_user values('kaizi','99');

select * from test_user;

同时:本地进行Mysql链接,链接正常

然后这里就能看到我们在服务器中创建的表了

运行查询操作

2. Redis安装

2.1 Redis 简历

Redis 出现的原因

  • 在 Web 应用发展的初期,关系型数据库受到了较为广泛的关注和应用,因为那时 Web 站点基本上访问和并发不高、交互也较少。
  • 随着访问量的提升,使用关系型数据库的 Web 站点在性能上出现了瓶颈,主要瓶颈在磁盘的I/O 上。
  • 随着互联网技术的进一步发展,对性能有了更高的需求,主要体现在低延迟的读写速度和支撑海量的数据和流量。

Redis 是什么

  • Redis 全称 Remote Dictionary Server,中文名为****远程字典服务器****。
  • Redis 是一个使用 ANSI C 编写的开源、包含多种数据结构、支持网络、基于内存、可选持久性的键值对存储数据库。

Redis 的特性

  • 基于内存运行,性能高效
  • 支持分布式,理论上可以无限扩展
  • key-value 存储系统
  • 开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API

Redis 的应用场景

  • 缓存系统("热点"数据:高频读、低频写)
  • 计数器
  • 消息队列系统
  • 实时排行榜
  • 社交网络

Redis 生活案例

  • Redis 就像一个新华字典,可以根据某个字符快速找到字典对应的字
2.2 实际操作

① 拉取redis容器镜像到本地

bash 复制代码
docker pull redis:7.0

可以看到我们的redis容器

bash 复制代码
docker images

② 创建一个redis容器

bash 复制代码
docker run --name redis -d -p 8090:6379 redis:7.0
docker ps

我们的8090端口也映射到了容器的6379端口上了

③ 进入到容器中并且启动 redis

bash 复制代码
docker exec -it redis bash
redis-cli

④ 进行操作测试

bash 复制代码
set sellcount 1
get sellcount

键值对存储操作 ,这里我们就链接成功了

3. C++容器的制作

3.1 制作 Centos 镜像

① 下载镜像

bash 复制代码
docker pull centos:7

② 启动容器

bash 复制代码
docker run  -it --name mycpp centos:7 bash

③ 检查是否运行,打开另一个终端检查

bash 复制代码
docker ps

④ 更新缓存数据

bash 复制代码
yum clean all # 先清除所有旧的、可能已损坏的缓存数据
yum makecache # 让系统根据新的配置文件重新生成缓存

⑤ 下载 gcc

bash 复制代码
yum install gcc

这样就下载好了

⑤ 创建一个文件进行文件的编译操作

bash 复制代码
[root@94b9ae1994cc /]# vi code.c

[root@94b9ae1994cc /]# cat code.c
#include<stdio.h>
int main(){
	printf("Hello Docker");
	return 0;
}

⑥ 编译运行

3.2 制作 Ubuntu 镜像

① 下载 Ubuntu 镜像

cobol 复制代码
docker pull ubuntu:22.04

② 启动容器

cobol 复制代码
docker run --name mygcc -it ubuntu:22.04 bash

③ 配置国内镜像源加速

cobol 复制代码
sed -i 's@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g' /etc/apt/sources.list

④ 安装 gcc 和 vim

sql 复制代码
apt update
apt install gcc vim -y

⑤ 编辑代码

scss 复制代码
mkdir src
cd src
vim demo.c

⑥ 编译代码,并且在容器中运行

undefined 复制代码
gcc demo.c -o demo
./demo
3.3 一些问题

注意:在进行任何修改之前,先备份是一个好习惯。

bash 复制代码
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup

由于官方源已失效,需要使用归档(vault)源。执行以下命令下载新的配置文件。

bash 复制代码
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

如果你的环境中没有 curl,也可以尝试使用 wget:

bash 复制代码
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

4. 容器资源更新

① 运行一个 Nginx 容器

bash 复制代码
docker run -d --name mynginx -p 8081:80 nginx:1.23.3

② 查看容器进程

bash 复制代码
docker top mynginx aux

③ 查看资源动态变化

bash 复制代码
docker stats

# 输出
lighthouse@VM-8-10-ubuntu:~$ docker stats mynginx
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT    MEM %     NET I/O         BLOCK I/O         PIDS 
b517812ccc7c   mynginx   0.00%     3.617MiB / 3.32GiB   0.11%     1.08kB / 126B   1.14MB / 20.5kB   3 

④ 更新容器最大内存

bash 复制代码
docker update -m 300m --memory-swap 600m mynginx

⑤ 执行命令打满 CPU

bash 复制代码
for i in `seq 1 $(cat /proc/cpuinfo |grep "physical id" |wc -l)`; do dd if=/dev/zero of=/dev/null & done

⑥ 配置只能使用 10% 的 CPU

bash 复制代码
docker update --cpu-period=100000 --cpu-quota=10000 mynginx

⑦ 查看 CPU 使用情况

bash 复制代码
docker stats

⑧ 停止容器,释放资源

bash 复制代码
docker stop mynginx
docker rm mynginx

五:🔥 共勉

😋 以上就是我对 【Docker#6】Docker 容器常用命令 的理解, 觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~ 😉

相关推荐
石工记2 小时前
OpenClaw AI 助手 Docker Compose 一键部署文档(MacBook Pro 2020 专属版,可下载)
人工智能·docker·容器
程序员一点2 小时前
第19章:openEuler 中的容器支持(Docker 与 iSulad)
运维·docker·容器·openeuler
科技块儿2 小时前
社交媒体账号安全如何通过IP查询工具检测异常登录?
服务器·网络·数据库·tcp/ip·安全
胶水代码3 小时前
软件开发之DevOps
运维·devops
智能运维指南3 小时前
信创背景下,国产 DevOps 选型的价值跃迁路径设计(2026)
运维·devops
生活予甜3 小时前
2026年算法备案办理服务优选服务商口碑解读
大数据·运维·人工智能
jiayong233 小时前
流程设计器技术选型评估报告
运维·ubuntu·流程引擎
AI-小柒3 小时前
OpenClaw技术深度解析:从智能助手到自动化引擎的范式革命(附DataEyes实战)
大数据·运维·开发语言·人工智能·python·http·自动化
-Da-3 小时前
【操作系统学习日记】操作系统核心机制深度解析:中断、DMA与进程管理
linux·后端·系统架构