资讯动态

Nginx与Docker面试高频考点:从原理到排错实战

发布时间:2026/10/19 9:56:10 来源:尧图企业网站定制
前阵子给一个准备跳槽的朋友做模拟面试题目刚出到“Nginx反向代理和正向代理区别”他就开始背课本定义。等他背完我补了一句“那你线上环境里的代理 server 是给客户端用还是给服务端用”他愣了几秒。这其实是很多人在面试 Nginx 和 Docker 题目时最常见的状态答案记得住原理讲不清一追就露馅。这篇文章我想以面试官追问的视角把 Nginx 和 Docker 的高频考点重新捋一遍不堆题重点讲每道题背后的原理、配置细节和排错思路。准备跳槽的后端、运维或者刚入门想建立完整知识框架的开发者都可以对着这份清单自查。1. Nginx概念题反向代理与正向代理的边界感1.1 正向代理和反向代理到底怎么区分面试官很少直接让你背定义常见问法是“你们线上靠 Nginx 解决了什么问题”如果回答“做代理转发”那就等着被追问“正向还是反向区别在哪”。最直观的区别看代理服务器站在哪一边。正向代理主要服务客户端客户端知道代理的存在要手动配置代理地址代理替客户端去请求目标服务目标服务看到的是代理的 IP。反向代理主要服务服务端客户端不知道代理的存在它认为自己访问的就是真实服务代理按照规则把请求转发给后端某个节点。这里有个很常见的口误不少人把“反向代理”说成“服务器代理”或者“负载均衡代理”虽然表达上不算错但在面试里体现的是术语精度。我喜欢用一个类比正向代理是“代购”帮你买到你自己直接买不到的东西反向代理是“前台接待”来访者只要找前台前台再把问题转给后面的具体同事。这个类比在面试里现场讲出来通常会给印象分加分。除了区分方向最好还能说出反向代理的三个价值第一是隐藏后端结构外部只暴露一个入口后端扩容缩容对客户端无感第二是集中做负载均衡和流量分发第三是在代理层统一处理 SSL、缓存、限流、日志等横切逻辑。如果只说“转发请求”面试官会觉得你对这块没有深度思考。1.2 location匹配优先级配置题里的第一道坑Nginx 配置里 location 写得好不好很能看出基本功。面试里经常出现一个手写题给你一段配置问某个路径实际会命中哪个 location。下面是我常用的一段示例location /index.html { return 200 exact; } location ^~ /api/ { return 200 prefix-api; } location ~ ^/api/user$ { return 200 regex; } location /api { return 200 longer-prefix; } location / { return 200 default; }现在问请求/api/user最终会返回哪个字符串很多人一看到后面有个正则^/api/user$本能回答“regex”这是错的。Nginx 的匹配规则分四步先精确匹配命中了直接结束然后找前缀匹配记录最长的前缀结果如果最长前缀是^~形式也直接结束不再看正则否则进入正则匹配阶段按配置文件顺序逐个尝试正则命中就结束正则没命中才退回之前暂存的最长前缀结果。所以上面这个例子请求/api/user的前缀候选是/api/和/api更长的/api/恰好是^~形式直接终止匹配正则根本没机会参与最终返回 “prefix-api”。这个考点几乎每场面试都会出现值得动手验证一遍。Nginx 官方文档说得清楚但很多书里把它讲得太绕。你只要记住最霸道^~第二霸道正则第三普通前缀兜底最后才是/。面试时按这个顺序背出来基本不会错。1.3 proxy_pass 的斜杠问题少一个杠就是另一种行为另一个手写配置高频考点是 proxy_pass 末尾到底要不要带斜杠。很多人以为带不带无所谓实际效果完全不同。先说结论location /api/里如果写proxy_pass http://backend/;Nginx 会把 URI 里匹配的/api/前缀拿掉再把剩余路径拼接给后端如果写proxy_pass http://backend;不带路径Nginx 会保留原始 URI 整体转发。举个例子。location /api/ { proxy_pass http://backend/; }请求/api/user后端实际收到的是/user。如果后端接口本来就定义在/api下你把前缀替换掉了服务端直接 404。反过来如果你想让后端收到完整路径就得去掉末尾斜杠。面试里可以主动把这个坑讲出来并且说“我在项目里用脚本批量校验过配置防止同事提交错误斜杠”这种细节最容易加分。实际排障时看到大量 404 但后端接口确认正常第一反应就应该是检查 proxy_pass 的路径拼接规则。2. Nginx负载均衡与规则匹配配置题的拿分点2.1 upstream 三种策略与权重场景负载均衡是 Nginx 面试绕不开的第二座山。第一问通常是“你配过哪些策略”答案是轮询、权重、IP 哈希能说出 least_conn 更好。但光会背不行要能说出适用场景。默认轮询适合后端能力均等的场景简单但不够精细权重适合机器配置高低不齐的场景比如 8 核机器和 4 核机器按 2:1 分配流量ip_hash 把同一客户端的请求固定发给同一个后端适合服务端有本地 Session、又懒得改造成 Redis 共享会话的场景。但这里有个陷阱ip_hash 会导致单台热门 IP 的请求全部打到一个节点还可能出现单点热点而且节点宕机会造成会话迁移。面试时说完策略之后一定要补一句“现在一般不会只用 ip_hash 解决 Session更常见的是 Redis 统一会话Nginx 配置里用最少连接数这类策略”这样显得跟得上实践。下面是一个标准 upstream 配置示例upstream backend_servers { server 10.0.0.11 weight3; server 10.0.0.12 weight2; server 10.0.0.13 weight1; keepalive 32; } server { listen 80; location / { proxy_pass http://backend_servers; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }面试官如果接着问“keepalive 32 是什么”你要能分清这是 Nginx 到后端的连接复用不是浏览器长连接。很多人会把keepalive_timeout和 upstream 里的keepalive混为一谈前者是 Nginx 与客户端的长连接空闲时间后者是连接池里保留的空闲上游连接数。2.2 502、504、499从状态码到排错链路面试官如果让你“给一个 502 你从哪查”考察的不是你背状态码文案而是排错链路。502 Bad Gateway 通常意味着 Nginx 与后端之间出了问题。第一步先确认 Nginx 能不能访问到后端直接在服务器上执行curl -v http://127.0.0.1:8080/health看后端自身是否正常第二步看 Nginx 的 error.log区分是connection refused还是timeout第三步检查后端是否还有空闲连接、upstream keepalive 配置是否合理、后端进程有没有被频繁重启。504 是网关超时问题焦点从“连不上”变成了“后端响应太慢”重点查后端处理耗时、proxy_read_timeout参数以及后端线程池是否被打满。499 比较特别它表示客户端主动断开连接常见场景是接口很慢用户等不及关了页面或者前端超时设置比 Nginx 更短。把这三个状态码串在一起讲面试官基本上会觉得你不需要手把手教。注意千万别只答“502 就是后端没启动”这太绝对了后端进程健康但连接队列溢出也会触发 502。2.3 静态资源、gzip、keepalive、worker 参数等调优Nginx 调优题经常以“你怎么压测过 Nginx”为引子。这里可以准备一小段参数worker_processes通常设为 CPU 核数写auto也可以worker_connections决定单个 worker 进程能维持的最大连接数注意它同时受系统文件描述符限制调大前要先改ulimitgzip on开启文本压缩静态资源直接让 Nginx 处理不走后端再加expires缓存。并发量的粗略上限可以用worker_processes × worker_connections估算比如 4 个 worker、每个 1024 连接理论上最大并发约 4096。当然这是简化模型实际还要扣除系统占用但面试里能掏出这个公式已经比大多数人强。动静分离也可以在这里主动提静态资源用location匹配特定后缀或目录直接返回本地文件并设置缓存动态请求走proxy_pass转发到后端。把这两个分流写清楚配置题基本就拿下了。我见过很多人只背“动静分离”四个字却写不出配置面试官自然会怀疑简历里的“熟练使用 Nginx”是不是真的。3. Docker原理题镜像分层、写时复制与容器隔离3.1 容器与虚拟机共享内核的隔离为什么容器比虚拟机轻量答案的根源是共享内核。容器进程本质上就是宿主机上的普通进程只不过通过内核特性把“看得见的东西”和“能用的资源”隔离开。虚拟机则是有独立内核、独立硬件抽象层的完整系统。类比一下虚拟机像独栋别墅每栋都有自己的水电管网容器像公寓楼大家共享楼里的主管道但每家有自己的房本和门锁。共享内核这件事带来两个重要推论。第一启动容器不需要启动操作系统所以是秒级甚至毫秒级第二容器和宿主机共用内核你不可能在 Linux 宿主机上的容器里跑 Windows内核版本敏感的应用也要谨慎。面试回答“容器到底是虚拟机还是进程”答“进程级别的隔离”就比答“轻量虚拟机”高一个档次。3.2 镜像分层与写时复制COW镜像分层是 Docker 面试必考。镜像由多个只读层叠加Dockerfile 里每一条指令会生成一个新层。容器启动时Docker 在只读层之上创建一个可写层。多个容器共享同一个镜像时只读层全部共享各自的可写层互相独立。修改文件时Docker 不会真的去改底层只读层而是把要改的文件复制到可写层再修改这就是写时复制机制。所以容器删除时可写层跟着删除所有运行期修改全部丢失。这也是为什么数据库数据绝对不能放在容器可写层里必须用数据卷。面试官常追问“两个用相同镜像启动的容器磁盘占用是不是双倍”答案不是双倍只读层共享主要是可写层和容器元数据各自独立。能把这一层说清楚说明你理解的不只是“docker run 能用”而已。3.3 Dockerfile 优化层缓存与多阶段构建关于 Dockerfile 优化关键回答是每条指令产生一层构建缓存基于指令和上下文只要指令没变且上下文没变就会复用缓存。因此要把改动频繁的操作放在后面比如先COPY依赖清单文件、再RUN安装依赖、最后COPY源码。多个RUN尽量合并成一条避免产生大量垃圾层。多阶段构建用于显著降低镜像体积构建阶段用一个带完整工具链的基础镜像最终阶段只拷贝编译产物。下面是一个典型的 Go 服务多阶段构建示例# 构建阶段 FROM golang:1.21 AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED0 go build -o app . # 运行阶段 FROM alpine:3.19 COPY --frombuilder /app/app /usr/local/bin/app ENTRYPOINT [app]这个例子同时考了层缓存顺序和镜像瘦身两个点。运行时镜像里没有编译器、没有源码、没有中间文件体积可能从几百 MB 降到十几 MB。和单纯说“一定要用多阶段构建”相比手写一个能跑的示例说服力完全不是一个级别。3.4 namespaces 与 cgroups讲得出名字还能讲清区别容器隔离靠两个内核机制namespaces 负责“看得见什么”cgroups 负责“能用多少”。namespaces 有 PID、Network、Mount、UTS、IPC、USER 等类型每个容器看到的是自己的进程空间、网络栈、文件系统挂载点和主机名cgroups 限制 CPU、内存、磁盘 IO 等资源用量。面试追问“容器里执行top看到的是什么”答案是容器隔离出的 PID namespace 视角只能看到自己进程空间内的进程看不到宿主机其他进程。能讲到这一层基本就和只会背“容器是一个沙箱环境”的人拉开了差距。还有一道追问是“容器真的安全吗”正确态度是容器隔离不是绝对安全边界共享内核意味着内核漏洞可能影响所有容器所以生产环境里还要结合权限管控、镜像扫描和运行时安全策略来加固。4. Docker网络与数据卷面试官最爱深挖的区域4.1 bridge网络的通信逻辑默认网络模式是 bridge。Docker 会在宿主机创建 docker0 网桥每个容器创建一对 veth 虚拟网卡一端留在容器里另一端挂在 docker0 网桥上。容器与容器、容器与宿主机之间通过这些虚拟网卡交换数据。同在一个桥接网络里的容器可以通过 IP 直接互相访问但默认 bridge 模式下容器名不能直接被解析自定义 bridge 网络则自带 DNS 解析能力。端口映射的场景是外部流量先到达宿主机端口再由 iptables 的 DNAT 规则转给容器 IP。因此容器 IP 本身在宿主机外部是不可路由的你不做-p映射外部就访问不到容器。这个理解在排查“为什么容器里服务正常外部却访问不了”时特别有用问题基本出在端口映射、防火墙或者网卡配置上而不是服务进程本身。4.2 host、none、container 模式区别bridge 之外还有三种模式面试时最容易互相混淆我整理成一张表网络模式容器网络栈端口占用典型场景bridge独立网络栈通过 docker0 网桥与宿主机通信需要 -p 映射默认模式隔离性好host直接复用宿主机网络栈直接占用宿主机端口追求低延迟、高吞吐的性能敏感场景none只有 loopback 接口无需要完全自定义网络配置的场景container共享另一个容器的网络栈共用该容器的端口sidecar 模式比如日志采集容器通过 127.0.0.1 访问业务容器host 模式少了一层 NAT 中转网络性能损耗最小但代价是容器没有独立 IP端口冲突风险很高比如两个容器都想监听 8080 就会直接打起来。container 模式在 K8s 的 sidecar 设计里思路类似面试时如果能结合“业务容器和日志采集容器共享网络采集代理连 127.0.0.1 就能拿到业务指标”这种场景来讲会显得很有实战感。4.3 跨主机容器通信只要问到跨主机难度就上来了。先说朴素问题默认 bridge 模式下容器 IP 是在各自宿主机上分配的另一台宿主机根本不知道这个 IP 归属于哪个网段。所以最简单的方案是端口映射把每个容器的服务端口映射到宿主机再靠外部负载均衡转发。但容器数量一多端口管理就是灾难。另一个思路是覆盖网络也就是 overlay 网络让容器 IP 在整个集群范围内可路由。面试不要求你把 VXLAN 封包细节背出来但你要能说清核心容器间的流量会经过封装在底层网络中传输对上层容器表现为一个虚拟大二层网络。从 Swarm 到 Kubernetes 的 CNI 插件本质都在解决同一件事。能分清“单机网络模型”和“跨主机网络模型”是两种体系就已经证明你有结构化理解。4.4 数据卷数据的三种挂载方式存储方面的高频题是-v、volume 和 bind mount 的区别。简单说volume 由 Docker 管理数据存放在/var/lib/docker/volumes下适合数据库这类希望 Docker 统一管理的持久化数据bind mount 直接映射宿主机绝对路径适合把配置文件或开发代码挂进容器tmpfs 是内存盘容器停了数据就没了适合临时缓存。拿 MySQL 举例最容易落地容器删除后数据必须还在所以必须用 volume 或 bind mount 挂载数据目录如果不挂载即使镜像没变容器重建后数据也全丢。还有一个很多新手栽跟头的细节是权限容器内的 uid 要和宿主机挂载目录的属主匹配否则会出现 permission denied。面试时主动提这个权限问题比背一堆参数更有价值。5. 综合场景题容器生命周期与排错实战5.1 一条 docker run 命令里的考点面试官经常随手丢一条docker run命令让你解释每个参数。比如docker run -d --name web -p 8080:80 \ -v /opt/html:/usr/share/nginx/html:ro \ --restart unless-stopped nginx:1.25你要逐项拆解-d后台运行--name web指定容器名-p 8080:80把宿主机 8080 端口映射到容器 80 端口-v /opt/html:/usr/share/nginx/html:ro把宿主机 HTML 目录以只读方式挂载进容器--restart unless-stopped表示除了手动停止外容器异常退出或 Docker 重启时自动拉起nginx:1.25锁定了镜像版本。这里有个很少有人答得上来的细节unless-stopped和always的区别。always在 Docker 重启时也会拉起即使你之前手动 stop 过unless-stopped会尊重手动停止状态。这个细节知道的人不多答出来很有鉴别度。5.2 RUN、CMD、ENTRYPOINT的分工这三个指令的区分也是 Dcoker 面试里的常客。整理成表格更好记指令执行阶段覆盖规则典型用法RUN构建镜像时执行不影响运行时安装依赖、编译代码CMD容器启动时执行docker run 后面的命令会整条覆盖 CMD提供默认启动命令ENTRYPOINT容器启动时执行不会被整条覆盖可追加参数固定容器的主程序入口一个经典组合是ENTRYPOINT放主程序命令CMD放默认参数。运行时如果不传参数走 CMD 默认值传了参数则覆盖 CMD 作为新参数传给 ENTRYPOINT。这个组合在写工具型镜像时非常常见面试官一问“怎么做一个可带默认参数的工具镜像”你答出这个模式就到位了。5.3 docker-compose 的边界与 depends_on 的坑docker-compose 属于容器编排的入门课。面试问 compose 一般是为了确认你懂得多容器应用怎么拉起。核心字段无非services、image、ports、volumes、networks、environment、depends_on。最有价值的坑是depends_on只控制启动顺序不等待服务真正就绪。例如数据库容器刚启动时还在初始化业务容器已经启动并尝试连接结果就是连接被拒绝。一个不优雅的解决办法是让业务代码做重试更好的做法是配合 healthcheck等依赖服务健康后再启动下游。能主动讲出这个坑说明你真的用 compose 跑过微服务而不只是看过文档。后面如果接一句“正式多节点环境我会换编排平台compose 更适合单机开发环境”就又把边界说清了。5.4 容器起不来时的排错顺序空说排错太虚给一个可复用的顺序。第一步docker logs container看应用日志能解决大部分启动失败第二步docker inspect container看状态、异常退出码、健康检查结果重点关注ExitCode和Error字段第三步docker exec -it container sh进入容器检查环境变量、文件权限、进程状态第四步排查宿主机资源用dmesg看有没有 OOM 记录。常见原因我也汇总一下端口冲突看docker inspect的端口映射和宿主机端口占用挂载目录缺失确认 bind mount 路径是否被自动创建Entrypoint 脚本因为 CRLF 换行符问题在 Linux 容器里启动失败这是个非常隐蔽的坑Windows 上编辑的脚本尤其容易踩。把这一套排错链路串下来面试中遇到“容器起不来会怎么处理”基本就能顺畅答完。最后说点备考心得。我见过不少人把面试题背得滚瓜烂熟但只要追问到“你线上怎么配的”“挂了之后你的反应是什么”就崩盘。Nginx 和 Docker 面试题的优势在于所有问题都是可以在本地复现的实验。location 匹配规则自己起一个 Nginx 写两条配置测一遍镜像分层和容器可写层自己启动容器改文件再删除观察行为网络模式自己建两个容器 ping 一下看通不通。把实验结论记在笔记里比背十页题库有用得多。如果在简历里写项目经验记得把“我用 Nginx 解决了什么问题”“我为什么用 Docker 而不是直接部署”这类有取舍的故事写进去面试官也更愿意聊真实经历而不是听你默写答案。准备面试不是背题是把自己的工程选择讲清楚这条经验适用于任何岗位。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑