Docker面试核心指南:从镜像容器原理到高频实践题

📅 发布时间:2026/10/13 2:54:06
Docker面试核心指南:从镜像容器原理到高频实践题
1. 找准主线Docker 面试题考的其实是“怎么理解这三个东西”最近一个月前前后后有十多位读者来找我聊 Docker 面试的事。有人把各种速成资料翻了一大堆能背出docker run -d -p 8080:80结果被问一句“容器启动的完整流程是什么”就开始卡壳也有人已经在项目里用 Docker 跑服务跑了大半年却说不清“为什么容器一删日志和数据就全没了”。我把这类问题集中整理了一遍按“基础知识、高频十大面试题、常用指令”三块重新拆开于是有了这篇内容。先说一个判断标准面试官很少真的想听你把docker ps背出来。他们真正想确认的是你能不能把“架构、隔离、分层、状态、生命周期”这几个词落到具体场景里。能解释清楚“镜像和容器的差别”说明你理解了不可变交付能说出“数据卷和容器层谁先丢”说明你理解了状态和数据能把“CMD 为什么会被覆盖”讲明白说明你理解了容器内进程的执行模型。只要这三条线立得住题目怎么换都不慌。1.1 容器与虚拟机的区别是所有问题的第一道门槛面试里至少有一半的题绕来绕去都会回到“容器和虚拟机到底差在哪”。如果这道题答出花来后面很容易被追问网络、存储、资源限制如果连这道题都含含糊糊整场基本就定性了。两者最核心的分界点是隔离层级不同。虚拟机通过虚拟化硬件运行一个完整内核Guest OS 独享一段资源容器则直接复用宿主机内核靠系统级隔离手段把进程、文件、网络、PID 这些视图隔开。这就是为什么容器启动能以“秒”为单位而虚拟机从开机到系统就绪通常要几十秒。特性容器虚拟机隔离维度进程和资源视图隔离硬件级虚拟化内核共享宿主机内核独占独立内核启动速度秒级本质是拉起进程慢需要引导完整系统资源占用轻量但仍占用宿主机资源固定分配 CPU、内存、磁盘镜像大小可能只有几十 MB通常几个 GB 起安全边界内核边界共享隔离更薄更强的系统边界听完区别还要防止踩一个常见坑不要只说“容器更轻”。面试官马上会追问“为什么更轻”如果你答不上来等于没准备。准确说法是容器不需要引导内核不需要初始化整块虚拟硬件它只不过是把用户态进程用 Namespace 和 Cgroups 包装了一下。1.2 镜像、容器、仓库的关系用一条时间线讲清楚镜像只是一堆只读文件层的组合仓库负责存镜像和分发镜像容器则是在镜像之上加了一层可读写层后跑起来的进程实例。打个生活化比方镜像是一张冷冻披萨饼底仓库是超市货架容器是那张被拿出来解冻、加料、烤好并端上桌的成品披萨。饼底是整个流程中可复用的部分货架上放了同一款饼底的不同批次而每次按菜单做出来的成品才是真正被吃掉的那一份。库、像、器串联起来意思就是把干净的交付物放在仓库里运行时根据需要拉取并实例化。理解了这个三角关系你就会明白为什么 99% 的题目最后都要落到“镜像层”和“容器层”这两个概念上。镜像层不可修改所有变更只发生在容器的可写层一旦docker rm容器那层可写文件就没了赖在外面的数据只能靠挂载卷存活。2. 基础概念不需要全背但这几个底子必须打牢2.1 先分清 client 和 daemon命令行不是你输入的地方很多人面试时容易把docker命令和后台服务混成一体。实际上你敲的docker run只是一个 client真正干活的是后台常驻的 daemon。client 把命令行参数转成请求通过本地 socket 发给 daemondaemon 再去操作镜像、容器、网络、存储。这个模型最直接的启发是daemon 挂了你输入的指令根本没机会执行。生产环境里排查“命令卡住”“容器状态拉不出来”第一步通常就是看 daemon 是否正常。理解 client/daemon 的通信方式还顺带解释了“为什么有些环境下要配置远程连接”、为什么安全上要慎用暴露的 socket。2.2 Namespace 和 Cgroups隔离与限制的真正实现者容器底层主要靠 Linux 的两个机制Namespace 负责“看起来像一台独立机器”Cgroups 负责“用资源不能超限”。Namespace 隔离的是视图。PID Namespace 让容器内的 1 号进程以为自己是系统第一个进程Mount Namespace 让容器内看到的是自己的文件系统挂载关系Network Namespace 让容器拥有独立的网络栈、自己的 IP 和端口空间。Cgroups 则是一套资源控制器能限制 CPU、内存、IO、PID 数量等。面试中被问“容器怎么限制内存”本质上就是在问 Cgroups 怎么配。一个容易忽略的点是隔离的是“视图”不是“安全边界”。容器和宿主机还是共享同一个内核如果把权限配置得太开放风险就会明显上升。这也是为什么正经项目里要做用户降权、只读根文件、丢弃多余 Capability。2.3 镜像分层Dockerfile 里的每一行都可能生成一层镜像由若干只读层堆叠而成。Dockerfile 里不同指令会创建不同层层与层之间按顺序叠加最终从容器角度看目录是合并在一起的。层最实际的价值是缓存复用。重新构建镜像时如果某层没有变化Docker 可以直接复用之前的层缓存。依赖装了半天的镜像再次构建往往只有最后几秒就是这个原因。正因如此调整依赖和代码的顺序会影响构建效率。把不常变的依赖安装先放把频繁改动的业务代码后放是控制构建速度的常用手段。这一条几乎一定会出现在面试题“如何优化 Dockerfile”里提前理解分层的规则比死记命令更可靠。2.4 镜像层只读容器层可写数据问题都从这里来容器启动时Docker 在镜像层之上挂一个可写层。对运行中的容器来说你写文件、改配置、生成日志默认都落在这个可写层。问题来了可写层和容器同生共死。容器被删除可写层也就没了。这解释了“日志文件为什么丢”“运行期间生成的数据为什么丢”。要持久化就必须挂载外部存储。VOLUME、-v / 路径、--mount这些语法本质都是在给容器“续上一条命”把数据存到容器生命周期之外的地方。理解这个概念后很多实战教训都能对上号不要在同一份镜像里反复改造成本镜像要把变化的数据放卷里不要在容器里存重要状态因为容器随时会被销毁重建。3. 高频十大面试题按“问法→答案→得分点”拆开这个板块是全文的正文重点我把面试中出现频率最高的十类题逐一拆解每题都给出可以直接口头回答的思路后面再加一句“该答到什么程度”作为自查。3.1 第一题镜像和容器到底什么关系问法一般是“镜像是用来干嘛的容器又是什么它们有什么区别”你要抓住的关键词是“静态”和“动态”。镜像是一堆只读层的静态产物不做任何运行容器是镜像实例化之后带可写层、带进程、带网络环境的动态实体。答案模板可以这么说镜像定义了“这个应用长什么样”容器则是“这个应用跑起来的样子”。同一个镜像可以启动多个容器每个容器之间相互独立容器删除后镜像还在可以继续生成新容器。能把“静态文件集”和“运行实例”这两个词说出来这一题基本就过了。3.2 第二题执行 docker run 后后台发生了什么这题出现频率相当高。你要答出四段链路检查本地有没有镜像没有就按名称去仓库拉取创建容器所需的文件系统在镜像层上叠加可写层分配网络资源默认接入 bridge 网络并分配 IP启动容器内的主进程把入口命令交给它执行。如果面试官再追问“-it是什么”可以补一句-t分配伪终端-i保持标准输入打开连起来的效果是像直接坐进容器里的 shell 一样。3.3 第三题为什么建议一个容器只跑一个进程很多人觉得“一个容器就是一个小虚拟机可以塞很多进程”这是最常见的误解。容器真正的主进程只有第一个也就是 PID 1。如果 PID 1 退出容器生命周期就结束了里面其它进程也会跟着被回收。单进程容器不是硬性规定而是一种职责拆分策略。一个容器只处理一件业务日志、监控、升级、扩缩容都更清晰如果硬塞多个进程还要额外引入初始化进程来管僵尸进程复杂度就上去了。你可以说“我会让每个容器只承载一个主进程典型的 web 服务就用一个 web 容器加一个数据库容器配合起来跑。”3.4 第四题CMD 和 ENTRYPOINT 的区别是什么这是高频中的高频。核心规则记住三条CMD提供默认启动命令可以被docker run后面的参数覆盖ENTRYPOINT是入口点执行时不会被普通参数覆盖两者同时写时CMD变成ENTRYPOINT的默认参数。面试话术可以这样讲如果希望镜像默认执行某个命令但允许外面替换就写CMD如果希望镜像把“必须执行的程序”焊死只允许追加参数就写ENTRYPOINT。举例说明ENTRYPOINT [nginx]配合CMD [-g, daemon off;]外面再传参数时只是改到了 nginx 的启动参数不会把 nginx 换成别的命令。3.5 第五题容器删了数据去哪了这题在新手面试里很常见。主线是分清“容器可写层”和“数据卷”。容器运行中产生的数据默认写在可写层。docker rm -f以后可写层连容器一起被移除数据就没了。如果你使用VOLUME或-v挂载数据会写到宿主机目录或命名卷里容器删除时卷还在重新启一个容器挂上同一个卷就是旧数据。得分点是能主动说出“什么时候该用命名卷什么时候该用 bind mount”。命名卷适合数据库文件这类程序自己管理的持久化数据bind mount 适合你需要直接从宿主机编辑的配置文件或代码目录。两个词都提出来答案的层次就不一样了。3.6 第六题容器网络模式怎么选面试可能问“host、bridge、none 有什么区别什么时候用哪个”你不需要追求全背但要能分清三个关键词。bridge 模式是默认方案容器接入一个虚拟网络每个容器有独立 IP容器之间可以通信对外通过端口映射暴露服务。host 模式直接使用宿主机网络栈容器没有独立 IP监听端口就是宿主机端口性能好但隔离弱。none 模式不给容器配网络适合需要完全隔离或走自定义网络的场景。再补充一个加分点使用自定义 bridge 网络时容器可以按“容器名”互相访问不用依赖 IP。很多人在生产环境用自定义网络就是因为容器重建后 IP 会变用名字访问才稳定。3.7 第七题怎么把镜像体积压下来这题很实战。面试时不要只唱“用 Alpine”要说完整的瘦身策略。我的思路分成四条选体积小的基础镜像安装依赖时清理包管理器的临时文件避免把下载缓存留在镜像里用多阶段构建前面阶段负责编译最终交付阶段只拷贝运行产物合理利用分层缓存把依赖安装和代码复制分开降低重复构建浪费。多阶段构建是关键得分点你可以说我通常在第一个阶段装完整开发工具链编译完以后在第二个阶段用一个精简运行时镜像只把编译产出拷过去这样最终镜像只有产物的体量。3.8 第八题我要把容器搬到另一台机器怎么做这是一道典型的命令题但它问的其实是“传递交付物和传递状态的区别”。如果只是把镜像搬走用docker save导出成压缩文件再到对方机器docker load导入。如果只想要文件系统内容、不关心镜像历史信息可以用docker export配合docker import但这种方式丢掉了镜像的构建历史和元数据并不推荐用来迁移镜像。最稳妥的答案其实不是迁移容器而是迁移“可重建性”用 Dockerfile 加依赖清单到新机器上重新构建。容器本身是可替代的你真正要搬的是镜像、数据卷内容、以及配置文件。3.9 第九题容器日志无限增长会把磁盘撑满吗不会自动清理所以确实会。默认的日志驱动是 json-file通常只按文件轮转规则来决定保留如果没有配置上限长期运行的容器就会不断写日志最终把磁盘占满。答案里要带两个配置max-size和max-file。前者限制单个日志文件大小后者限制文件数量。还可以补一句最好在 daemon 层面统一配置日志轮转策略而不是等容器启动后再手动处理。另外可以提一嘴日志驱动常用有json-file、journald、syslog。如果你们已经有统一日志平台再用文件式日志去采就多了一层负担。3.10 第十题容器真的安全吗这道题用来测试你有没有“敬畏心”。正确答案不是“安全”也不是“不安全”而是“安全边界比虚拟机薄”。容器共享宿主机内核之后本意是为隔离。安全上要做层层加固进程用非 root 用户运行、文件系统挂为只读、删掉不需要的内核能力、必要时配合完整虚拟化做边界。能把这些说清楚说明你真正在真实环境里考虑过风险而不是只会开容器。4. 常用指令按场景重排能记住的才是好命令命令不需要背需要按场景反复用。我把最常见的用法整理成几组每一条都带有它解决的问题。4.1 镜像管理拉取、构建、查看、删除docker pull your-image:tag # 拉取镜像 docker images # 查看本地镜像列表 docker build -t myapp:v1 . # 根据 Dockerfile 构建并打标签 docker rmi your-image:tag # 删除镜像 docker history myapp:v1 # 查看镜像的分层构建过程重点关注docker history它能让你直观看到每一层是谁生成的、有多大。排查镜像体积和层缓存问题时非常有用。4.2 容器生命周期创建、运行、查状态、看日志docker run -d --name web -p 8080:80 myapp:v1 docker ps # 只看运行中的容器 docker ps -a # 查看所有容器含已停止 docker stop web docker start web docker restart web docker logs -f --tail 200 web # 持续跟踪日志只看最后200行 docker exec -it web /bin/sh # 进入运行中容器的 shell docker rm -f web # 强制删除容器run和create的区别也值得补充create只创建容器不立即启动run实际是“创建启动”一步到位。日常用run比较多但理解拆分逻辑对故障排查有帮助。4.3 网络操作创建网络、挂到容器docker network ls docker network create -d bridge my-net docker run -d --network my-net --name app1 myapp:v1 docker network connect my-net app2 docker network disconnect my-net app2自定义 bridge 网络的最大好处是容器间可以直接用名字通信。同一个网络里的容器app1在连接app2:8080时不需要查 IP名字本身就是解析目标。4.4 数据卷与清理挂载、查看、回收空间docker volume create>