Skip to content

Docker 面试题精选 ​

生成时间:2026-06-06 21:12 | 共 10 题


1. 请详细描述 Docker 的整体架构,以及 Client、Daemon、Registry 三者之间的交互流程。 ​

难度: ⭐⭐

标准答案:

Docker 采用 C/S(Client/Server)架构,核心组件包括:

  • Docker Client:用户与 Docker 交互的入口(docker 命令行),负责接收用户指令并通过 REST API 发送给 Docker Daemon。Client 和 Daemon 可以不在同一台机器上,通过 DOCKER_HOST 环境变量指定远程 Daemon 地址。
  • Docker Daemon(dockerd):Docker 的核心后台进程,负责接收 Client 请求,管理镜像、容器、网络和数据卷等 Docker 对象。Daemon 监听 Unix socket(/var/run/docker.sock)或 TCP 端口。
  • Docker Registry:存储和分发 Docker 镜像的仓库服务。Docker Hub 是默认的公共 Registry,企业可搭建私有 Registry。

交互流程示例(docker pull nginx):

  1. Client 解析命令,向 Daemon 发送 POST /images/create?fromImage=nginx 请求
  2. Daemon 查找本地是否已有该镜像,若无则向 Registry 发起 HTTPS 请求拉取
  3. Registry 返回镜像 manifest,Daemon 逐层下载 layer 并存储到本地存储驱动
  4. 下载完成后 Daemon 向 Client 返回结果

延伸思考: Docker Daemon 暴露 TCP 端口时有哪些安全风险?如何通过 TLS 双向认证保护 Daemon 通信?


2. Dockerfile 中 COPY 和 ADD 指令有什么区别?在镜像构建中应该优先使用哪个? ​

难度: ⭐

标准答案:

特性COPYADD
基本复制✅✅
从 URL 复制❌✅
自动解压 tar 归档❌✅
多阶段构建中 --from✅✅

最佳实践:优先使用 COPY。 原因:

  1. COPY 语义明确,只做文件复制,行为可预测
  2. ADD 的自动解压功能可能导致意外行为(如将压缩包作为文件复制而非解压到目标目录)
  3. ADD 从 URL 下载文件不可靠且不会自动缓存,应使用 RUN curl 替代以获得更好的缓存控制
  4. Docker 官方 Dockerfile 最佳实践文档明确推荐优先使用 COPY

延伸思考: 如何利用 COPY --link 优化构建缓存?在什么场景下 ADD 的自动解压反而有用?


3. 什么是多阶段构建(Multi-stage Build)?它解决了什么问题?请给出一个实际示例。 ​

难度: ⭐⭐

标准答案:

多阶段构建允许在一个 Dockerfile 中使用多个 FROM 指令,每个 FROM 开始一个新阶段,可以选择性地从前一阶段复制构建产物,最终镜像只包含最后一个阶段的内容。

解决的问题:

  • 构建环境依赖(编译器、SDK)不需要进入运行时镜像
  • 显著减小最终镜像体积(通常从 GB 级降到 MB 级)
  • 减少攻击面,提升安全性
  • 替代了之前"一个 Dockerfile 构建 + 一个 Dockerfile 运行"的双 Dockerfile 模式

示例 — Go 应用:

dockerfile
# 阶段1:构建
FROM golang:1.22 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp .

# 阶段2:运行
FROM alpine:3.19
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/myapp /usr/local/bin/myapp
ENTRYPOINT ["myapp"]

最终镜像仅包含 Alpine + 二进制文件,约 10-20MB,而非完整的 Go 构建环境(>1GB)。

延伸思考: 多阶段构建中如何使用 --target 指定构建到某一阶段?在 CI/CD 中如何利用这一特性同时产出测试镜像和发布镜像?


4. 请对比 Docker 的三种主要网络模式(bridge、host、overlay),并说明各自的适用场景。 ​

难度: ⭐⭐

标准答案:

网络模式原理性能隔离性适用场景
bridge默认模式。容器通过虚拟网桥(docker0)连接,每个容器分配独立 IP,通过 NAT 访问外部中等(NAT 开销)高单机容器通信,开发测试环境
host容器直接使用宿主机网络栈,不创建独立网络命名空间最高(无虚拟化开销)低需要极致网络性能的场景,如网络监控、高性能服务
overlay跨主机容器网络,基于 VXLAN 隧道实现,需配合 Swarm 或独立 etcd/Consul较低(封装开销)高多主机集群通信,Swarm/Kubernetes 跨节点 Pod 通信

关键细节:

  • bridge 模式下容器间通过 --link(已废弃)或自定义 bridge 网络通信
  • host 模式下端口冲突是常见问题,多个容器不能绑定同一端口
  • overlay 网络需要键值存储(Swarm 模式内置)来管理网络发现和加密
  • Docker 还提供 none(无网络)和 macvlan(容器拥有独立 MAC 地址)模式

延伸思考: 在 Kubernetes 中为什么不直接使用 Docker 的 overlay 网络?macvlan 网络模式有什么特殊用途和限制?


5. Docker 数据卷(Volume)和绑定挂载(Bind Mount)有什么区别?在生产环境中应如何选择? ​

难度: ⭐⭐

标准答案:

特性Volume(数据卷)Bind Mount(绑定挂载)
存储位置Docker 管理的区域(/var/lib/docker/volumes/)宿主机任意路径
创建方式docker volume create 或 -v name:/path-v /host/path:/container/path
生命周期独立于容器,需显式删除依赖宿主机目录
可移植性高,不依赖宿主机目录结构低,依赖宿主机特定路径
性能Linux 接近原生;Mac/Win 有 I/O 开销同左
备份迁移docker run --rm -v vol:/src -v $(pwd):/dst alpine cp -a /src/. /dst/直接备份宿主机目录
权限控制Docker 自动管理可能遇到权限不匹配问题

生产环境建议:

  • 数据库持久化数据 → 使用 Volume(管理方便、可命名、可备份)
  • 开发环境代码热更新 → 使用 Bind Mount(实时同步宿主机文件变化)
  • 配置文件注入 → 使用 Bind Mount 或 docker config(Swarm)
  • 敏感信息 → 使用 docker secret(Swarm)或环境变量

延伸思考: Docker Volume 在 Mac 和 Windows 上的 I/O 性能问题如何解决?tmpfs 挂载适合什么场景?


6. 请编写一个 docker-compose.yml 实现一个 LNMP(Linux + Nginx + MySQL + PHP)架构,并说明关键配置项的作用。 ​

难度: ⭐⭐

标准答案:

yaml
version: "3.8"

services:
  nginx:
    image: nginx:1.25-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d:ro     # Nginx 配置
      - ./www:/usr/share/nginx/html:ro           # 网站根目录
      - nginx-logs:/var/log/nginx                # 日志持久化
    depends_on:
      - php
    networks:
      - frontend
      - backend
    restart: unless-stopped

  php:
    image: php:8.3-fpm-alpine
    volumes:
      - ./www:/usr/share/nginx/html:ro           # 与 Nginx 共享代码
    networks:
      - backend
    restart: unless-stopped

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}  # 从 .env 读取
      MYSQL_DATABASE: app_db
      MYSQL_USER: app_user
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - mysql-data:/var/lib/mysql                 # 数据持久化
      - ./mysql/init:/docker-entrypoint-initdb.d  # 初始化脚本
    networks:
      - backend
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  mysql-data:
  nginx-logs:

networks:
  frontend:
  backend:
    internal: true   # 内部网络,不暴露到宿主机

关键配置说明:

  • depends_on:控制启动顺序,但不等待服务就绪(需配合 healthcheck)
  • internal: true:backend 网络外部不可访问,提升安全性
  • :ro 只读挂载防止容器内进程修改配置文件
  • docker-entrypoint-initdb.d:MySQL 首次启动时自动执行初始化 SQL
  • .env 文件管理敏感配置,避免硬编码密码

延伸思考: 如何使用 docker compose watch 实现开发环境热更新?depends_on 的 condition: service_healthy 与 service_started 有何区别?


7. 容器安全的最佳实践有哪些?如何实现容器运行时的安全加固? ​

难度: ⭐⭐⭐

标准答案:

容器安全应从镜像安全、运行时安全、编排安全三个层面考虑:

镜像安全:

  • 使用最小基础镜像(distroless、alpine、scratch)
  • 不以 root 用户运行:RUN adduser -D appuser && USER appuser
  • 使用 docker scan / Trivy / Snyk 扫描镜像漏洞
  • 固定镜像版本标签(nginx:1.25.3 而非 nginx:latest)
  • 使用 COPY --chown 确保文件权限正确

运行时安全:

  • 只读文件系统:docker run --read-only --tmpfs /tmp
  • 限制资源:--memory=512m --cpus=1.0
  • 禁用特权:避免 --privileged,使用 --cap-drop=ALL --cap-add=NET_BIND_SERVICE
  • 安全选项:--security-opt=no-new-privileges:true
  • 只读挂载 /proc 和 /sys,或使用 maskedPaths
  • 使用 Seccomp / AppArmor / SELinux 策略限制系统调用

编排安全:

  • 使用 Docker Secrets 管理敏感信息,不使用环境变量
  • 网络隔离:内部网络不暴露端口
  • 启用 Docker Content Trust(DOCKER_CONTENT_TRUST=1)
  • 定轮换镜像签名密钥

延伸思考: --privileged 容器与宿主机有什么区别?为什么在 Kubernetes 中 Pod Security Standards 推荐使用 restricted 策略?


8. 如何对 Docker 容器进行性能调优?请从 CPU、内存、磁盘 I/O、网络四个维度说明。 ​

难度: ⭐⭐⭐

标准答案:

CPU 调优:

  • --cpus=2.0:限制容器最多使用 2 个 CPU 核心
  • --cpuset-cpus=0,2:绑定容器到指定 CPU 核心,减少上下文切换
  • --cpu-shares=512:设置 CPU 时间片权重(相对值,非绝对限制)
  • CFS 调度器参数:--cpu-period 和 --cpu-quota 精确控制 CPU 带宽

内存调优:

  • --memory=2g --memory-swap=2g:限制内存使用(swap=memory 表示禁用 swap)
  • --memory-reservation=1g:软限制,内存紧张时才生效
  • --oom-kill-disable=true(仅与 --memory 一起使用):禁止 OOM Killer 终止容器
  • --kernel-memory:限制内核内存(已废弃,Linux 5.x+ 不推荐)

磁盘 I/O 调优:

  • --device-write-bps /dev/sda:10mb:限制块设备写带宽
  • --device-write-iops /dev/sda:100:限制 IOPS
  • 使用 Volume 而非 Bind Mount 减少 I/O 开销(Mac/Windows)
  • 存储驱动选择:overlay2(推荐)vs devicemapper(已弃用)
  • 日志限制:--log-opt max-size=10m --log-opt max-file=3

网络调优:

  • 高性能场景使用 --network host 避免 NAT 开销
  • 调整内核网络参数:net.core.somaxconn、net.ipv4.tcp_tw_reuse
  • 使用 --dns 指定 DNS 减少解析延迟
  • Mac/Windows:docker-desktop 的 VM 网络是瓶颈,生产环境用 Linux

延伸思考: 如何使用 docker stats 和 cgroups 监控容器资源使用?在 Kubernetes 中 Resource Requests 和 Limits 与 Docker 资源限制是什么关系?


9. 如何将一个 1.2GB 的应用镜像瘦身到 200MB 以内?请列出至少 5 种具体方法。 ​

难度: ⭐⭐⭐

标准答案:

方法一:多阶段构建(最有效) 将编译环境和运行环境分离,只复制最终二进制到精简基础镜像。Go/C++ 等编译型语言可瘦身 80%+。

方法二:使用更小的基础镜像

  • node:20 (1.1GB) → node:20-alpine (180MB) → node:20-slim (250MB)
  • Python: python:3.12 → python:3.12-slim → python:3.12-alpine
  • 终极方案:distroless 或 scratch(无 shell、无包管理器)

方法三:合并 RUN 指令减少层数

dockerfile
# 优化前(3 层)
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*

# 优化后(1 层)
RUN apt-get update && \
    apt-get install -y --no-install-recommends curl && \
    rm -rf /var/lib/apt/lists/*

方法四:利用 BuildKit 缓存挂载

dockerfile
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt

缓存不进入镜像层,减少层体积。

方法五:.dockerignore 排除无关文件

.git
node_modules
__pycache__
*.pyc
.env
tests/
docs/

方法六:压缩镜像层docker save | docker load 或 docker export | docker import 合并为单层(牺牲构建缓存能力)。

方法七:使用 docker slim 工具 自动分析容器运行时依赖,裁剪未使用的文件,可瘦身 30-70%。

延伸思考: distroless 镜像无法进入 shell,如何进行调试?镜像瘦身和可调试性之间如何权衡?


10. 如何搭建企业级 Docker 私有仓库?请描述基于 Harbor 的完整方案,包括高可用和 CI/CD 集成。 ​

难度: ⭐⭐⭐

标准答案:

Harbor 架构方案:

Harbor 是 CNCF 毕业项目,提供企业级 Registry 功能:RBAC、镜像扫描、镜像签名、镜像复制、审计日志等。

部署方案(高可用):

yaml
# docker-compose-harbor.yml 核心组件
services:
  harbor-core:       # API 和 Web UI
  harbor-registry:   # 镜像存储(基于 Distribution)
  harbor-db:         # PostgreSQL(外部 HA 集群)
  harbor-redis:      # Redis 会话管理(外部 Sentinel 集群)
  harbor-portal:     # 前端
  trivy:             # 镜像漏洞扫描
  notary:            # 镜像签名(Docker Content Trust)

高可用设计:

  1. 存储层:使用 S3/OSS 对象存储作为 Registry 后端,天然支持多节点访问
  2. 数据库:PostgreSQL 使用主从复制或云 RDS
  3. Redis:使用 Redis Sentinel 或集群模式
  4. Harbor Core:多副本部署 + Nginx 负载均衡
  5. 镜像复制:跨数据中心配置 Harbor Replication Policy

CI/CD 集成(GitLab CI 示例):

yaml
# .gitlab-ci.yml
build-and-push:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  before_script:
    - echo "$HARBOR_PASSWORD" | docker login harbor.company.com -u "$HARBOR_USER" --password-stdin
  script:
    - docker build -t harbor.company.com/project/app:${CI_COMMIT_SHORT_SHA} .
    - docker push harbor.company.com/project/app:${CI_COMMIT_SHORT_SHA}
    - docker tag harbor.company.com/project/app:${CI_COMMIT_SHORT_SHA} harbor.company.com/project/app:latest
    - docker push harbor.company.com/project/app:latest
  after_script:
    - docker logout harbor.company.com

安全加固:

  • 启用 HTTPS(Let's Encrypt 或企业 CA)
  • 配置 RBAC:项目级读写权限控制
  • 强制镜像扫描策略:只允许通过扫描的镜像部署
  • 启用 Docker Content Trust + Notary 镜像签名
  • 配置 Webhook 对接安全审计平台

延伸思考: Harbor 的镜像代理缓存(Proxy Cache)功能如何加速公共镜像拉取?在空气隔离环境中如何实现镜像的离线分发?


💡 学习建议: 每道题的"延伸思考"都是面试中的追问方向,建议深入准备。Docker 面试通常从基础概念逐步深入到生产实践,掌握从"是什么"到"为什么"到"怎么优化"的完整链条是关键。