
🌈 个人主页:Zfox_
🔥 系列专栏:Docker

目录
- [一:🔥 容器概述](#一:🔥 容器概述)
-
- [🦋 什么是容器](#🦋 什么是容器)
- [🦋 类比理解](#🦋 类比理解)
- [🦋 为什么需要容器](#🦋 为什么需要容器)
-
- [🎀 环境一致性:"一次构建,到处运行"](#🎀 环境一致性:“一次构建,到处运行”)
- [🎀 资源高效利用:"榨干" 硬件性能](#🎀 资源高效利用:“榨干” 硬件性能)
- [🎀 部署与扩展:简化流程,提升效率](#🎀 部署与扩展:简化流程,提升效率)
- [🎀 隔离与安全:保障应用独立运行](#🎀 隔离与安全:保障应用独立运行)
- [🦋 容器生命周期](#🦋 容器生命周期)
-
-
- 创建(Created)
- 运行中(Running)
- [停止(Stopped / Exited)](#停止(Stopped / Exited))
- [销毁(Deleted / Removed)](#销毁(Deleted / Removed))
- 暂停(Paused)【可选状态】
-
- [🦋 容器的特殊情况](#🦋 容器的特殊情况)
-
-
- [容器 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 run或kubectl 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 create或docker run(run = create + start) - 状态特点 :
- 容器文件系统已基于镜像创建(叠加可写层)
- 网络、卷、环境变量等配置已初始化
- 但进程未启动,处于"就绪但未运行"状态
- ✅ 可通过
docker ps -a查看状态为Created
📌 类比:房子装修完毕、水电接通,但还没人入住。
运行中(Running)
-
触发方式 :
docker start或docker run -
关键行为 :
- 容器主进程(PID 1)启动(如
nginx、./my_brpc_server) - 网络端口监听、日志输出、接受请求
- 可通过
docker exec进入容器执行命令
- 容器主进程(PID 1)启动(如
-
状态检查 :
bashdocker 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容器,避免磁盘堆积:
bashdocker 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)。
-
验证方法:
bashdocker 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 + 设置内存上限(危险组合)
-
启动参数:
bashdocker run -m 512m --oom-kill-disable myapp -
行为 :内存达到上限后,不再分配新内存 ,
malloc()会 永久阻塞(hang)- 当内存达到 512MB 时,内核不会杀死进程;
- 但不再分配新内存 ,任何
malloc()或new操作会永久阻塞(hang); - 容器看起来"还在运行"(
docker ps显示 Up),但完全无响应; - 整个系统可能因内存碎片或全局内存压力而变慢。
-
风险 :比直接 OOM 更危险!因为容器 "假活"(up),健康检查可能无法发现,导致流量持续打入"僵尸实例"。
-
用途 :仅用于调试 ,绝不用于生产环境。
3️⃣ 禁用 OOM-Killer + 无内存上限(极度危险)
-
启动参数:
bashdocker run --oom-kill-disable myapp # 未设 -m -
行为:容器可无限使用宿主机内存;
-
后果
- 一旦内存耗尽,整个宿主机可能卡死、SSH 无法登录、其他容器全部瘫痪;
- 最终触发宿主机全局 OOM,随机杀死系统关键进程(如 systemd、sshd)
- 节点级故障,远比单个容器崩溃严重。
-
结论 :永远不要在生产环境使用
--oom-kill-disable而不设-m!
容器异常退出(Init 进程退出)------ 生命周期异常
核心机制
- 每个容器有且仅有一个 Init 进程(PID 1);
- 该进程由
CMD或ENTRYPOINT指定; - 只要 PID 1 退出(无论正常或异常),Docker 就认为容器任务完成,立即终止整个容器;
- 容器内所有子进程(包括后台线程、fork 出的进程)全部被 SIGKILL 清理。
常见异常退出原因
| 原因 | 表现 | Exit Code | 说明 |
|---|---|---|---|
| 主进程崩溃(段错误,空指针) | Exited (139) |
139 | C++ 程序空指针解引用等 |
| 主进程 OOM 被杀 | Exited (137) |
137 | 如上所述 |
| 主进程抛出未捕获异常 | Exited (1) |
1 | C++ throw 未 catch |
| 依赖服务不可达(如 etcd 连不上) | Exited (1) |
1 | 应用主动 exit(1) |
| 脚本执行完毕 | Exited (0) |
0 | 如 CMD ["echo", "hello"] |
Docker Daemon 的行为
-
默认 :容器退出后,保持 Stopped 状态,不再自动重启;
-
若设置了
--restart策略 :bashdocker 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 响应但超时不设)
- 主进程未正确处理信号(如忽略
-
检测:
bashdocker top myweb1 # 查看内部进程 docker inspect myweb1 | grep -A5 State -
解决:
- 确保主进程是真正的入口进程 (不要用
bash -c启动多进程) - 使用 tini 作为 init 进程(Docker 官方推荐):
- 确保主进程是真正的入口进程 (不要用
② 容器退出但状态不清理(Exited 但未删除)
-
现象 :
Exited容器占用磁盘(日志、可写层)→ 磁盘爆满 → 节点宕机。 -
解决:
-
启动时加
--rm(临时容器):bashdocker run --rm -p 8080:80 nginx # 退出后自动删除 -
定期清理:
bashdocker 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 配置可能不兼容企业内网
- 未正确设置
--dns或extra_hosts
-
解决:
bashdocker 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 未启动)
- 权限问题(如写日志目录无权限)
-
排查步骤:
bashdocker logs myweb1 # 查看退出原因 docker run --entrypoint sh -it myimage # 进入调试
工程最佳实践 -- 解决方法
-
内存限制明确:
bashdocker run -m 1g --cpus=1.0 --name im-gateway your-brpc-image -
主进程信号处理:
- 捕获
SIGTERM(Docker 停止时发送); - 执行优雅关闭:停止接收请求 → 处理完队列 → 关闭 etcd/Redis/RabbitMQ 连接 →
exit(0)。
- 捕获
-
禁止
--oom-kill-disable(除非调试); -
使用 tini 作为 Init 进程:
DockerfileENTRYPOINT ["/sbin/tini", "--", "./im_server"]→ 避免子进程变僵尸,确保信号正确传递;
-
合理配置重启策略
bash# docker-compose.yml restart: on-failure:5 -
状态外置
- 配置、数据、日志 → 使用 Volume 或绑定挂载;
- 消息队列(如 RabbitMQ)开启持久化。
-
全面监控与告警
- 监控指标:
container_exited_reason、oom_kill、CPU/内存使用率; - 告警规则:
Exited(137)、高频重启、健康检查失败。
- 监控指标:
-
日志与磁盘管理
- 限制日志大小;
- 定期清理
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:
bashdocker 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)。
- 将容器的状态从
Created或Exited变为Up(运行中)。 - 容器内的主进程开始执行。
-
使用场景:
- 重新启动一个之前已经停止的容器。
- 启动一个由
docker create命令创建好的容器。
-
示例:
bash# 启动上面创建的 my-nginx 容器 docker start my-nginx现在,Nginx 服务就在后台开始运行了。你可以通过
docker ps命令看到它的状态是Up。
3. docker run [IMAGE]
-
作用 :这是一个复合命令,它创建并立即启动一个新容器。它是最常用的容器启动命令。
-
过程:
- 检查镜像:检查本地是否存在指定的镜像。如果不存在,会尝试从 Docker Hub(或配置的其他镜像仓库)拉取。
- 创建容器 (等于
docker create):基于该镜像创建一个新的容器。 - 启动容器 (等于
docker start):立即启动这个刚刚创建的容器。 - 附加到主进程(可选) :默认情况下,
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 的环境中(如气密网络或内网),将一台机器上的镜像完整地迁移到另一台机器上。
- 备份和恢复:对重要的镜像进行完整备份,以便将来可以精确恢复。
- 工作流程 :
- 在源机器上:
docker save my-image:latest > my-image.tar - 将
my-image.tar文件拷贝到目标机器 - 在目标机器上:
docker load < my-image.tar或docker load -i my-image.tar
- 在源机器上:
2. docker import
- 输入源 :可以是由
docker export命令创建的容器文件系统快照的 tar 文件,也可以是任何包含文件系统的 tar 归档(例如,一个全新操作系统的根文件系统)。 - 输入内容 :这个 tar 文件仅仅是文件和目录的集合,它不包含任何 Docker 镜像的层级信息、历史记录或元数据。
docker export会将一个正在运行或已停止的容器的文件系统打包,但会丢失所有与镜像历史相关的信息。 - 输出结果 :创建一个全新的 、扁平化的 (只有一个层)Docker 镜像。 这个新镜像没有任何历史记录。你可以为它指定一个新的仓库名和标签。由于元数据丢失,像
CMD或EXPOSE这样的指令需要在使用docker import时通过-c(--change) 参数重新指定。 - 主要用途 :
- 创建基础镜像:从头开始创建一个新的基础镜像。例如,你可以通过一个最小化的 Linux 文件系统 tar 包来创建一个自定义的基础镜像。
- "扁平化"镜像:将一个现有的多层镜像转换成一个只有单层的镜像,以减小体积或隐藏构建历史。
- 迁移虚拟机或物理机:将现有系统的文件系统打包,然后导入到 Docker 中作为一个镜像来运行。
- 工作流程 :
- (可选)从一个容器创建快照:
docker export my-container > my-container.tar - 导入文件系统创建新镜像:
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:latest和my-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 prunedocker network prunedocker 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?
- 是否有网络接口?
- 是否能和其他容器通信?(结合
ping、telnet等)
这在以下场景非常有用:
| 场景 | 用途 |
|---|---|
| 学习 Docker 网络 | 看容器默认 IP 范围(如 172.17.0.0/16) |
| 排查服务连通性 | 用 busybox 或 nicolaka/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 工具的精简系统 ,其中包括ifconfig、ping、telnet等常用网络命令。
→ 所以ifconfig可以正常运行。nginx:1.23.3:官方 Nginx 镜像基于 Debian (或 Alpine,取决于标签),但为了最小化镜像体积 ,默认不包含ifconfig、netstat、ping等网络调试工具 。
→ 所以执行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 容器常用命令 的理解, 觉得这篇博客对你有帮助的,可以点赞收藏关注支持一波~ 😉
