八股取士--docker

一、Docker 基础概念类


1. Docker 是什么?它和虚拟机的区别?

详细答案
Docker 是开源的容器化平台,核心区别:

维度Docker 容器虚拟机 (VM)
虚拟化层级OS 级别(共享宿主机内核)硬件级别(Hypervisor 虚拟硬件)
启动速度秒级(轻量级)分钟级(需启动完整 OS)
资源占用低(MB 级)高(GB 级)
隔离性进程级(较弱)完全隔离(更强)
镜像大小小(仅应用+依赖)大(完整 OS+应用)

示例

  • Docker 运行 Nginx:docker run -d nginx(1秒启动)
  • VM 运行 Nginx:需先启动 Ubuntu VM 再安装 Nginx

拓展
容器本质是隔离的进程,通过 Linux 命名空间(Namespaces)和控制组(Cgroups)实现


2. Docker 的核心组件有哪些?

详细答案

组件作用
Docker 守护进程 (dockerd)管理容器生命周期
Docker 客户端 (docker)用户命令行工具
Docker 镜像只读模板(包含应用+环境)
Docker 容器镜像的运行实例
Docker Registry镜像仓库(如 Docker Hub)

工作流程
客户端 → 守护进程 → 创建/运行容器


3. 什么是 Docker 镜像(Image)?

详细答案

  • 定义:只读的模板,包含运行容器所需的所有文件(代码、库、环境变量)
  • 特性
    • 分层存储(每层可复用)
    • 内容寻址(通过 SHA256 校验)
  • 构建:通过 Dockerfile 创建

示例

# 查看本地镜像
docker images
# 输出:
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    abc123456      2 weeks ago    133MB

4. 什么是 Docker 容器(Container)?

详细答案

  • 定义:镜像的运行实例,包含:
    • 可写层(在镜像层之上)
    • 隔离的进程空间
    • 网络/IP 配置
  • 生命周期
    创建 → 运行 → 暂停 → 停止 → 删除

示例

docker run -d --name my-nginx nginx  # 创建并运行容器
docker ps                           # 查看运行中容器

5. 什么是 Docker 仓库(Registry)?

详细答案

  • 作用:集中存储和分发 Docker 镜像
  • 类型
    • 公共仓库:Docker Hub(默认)
    • 私有仓库:Harbor、AWS ECR
  • 操作
    • docker pull:下载镜像
    • docker push:上传镜像

示例

docker pull ubuntu:22.04      # 从 Docker Hub 下载
docker push mycompany/app:v1  # 上传到私有仓库

6. Docker Hub 和私有仓库的区别?

详细答案

对比项Docker Hub私有仓库 (如 Harbor)
访问权限公开(部分私有需付费)完全私有控制
速度受网络限制内网高速访问
安全性依赖 Docker 公司自主控制安全策略
适用场景公共基础镜像企业专有镜像

私有仓库部署

docker run -d -p 5000:5000 --name registry registry:2

7. Docker 的常用命令有哪些?

详细答案

类别命令作用
生命周期docker run创建并启动容器
docker stop / docker start停止/启动容器
docker rm删除容器
镜像管理docker build构建镜像
docker rmi删除镜像
docker pull / docker push拉取/推送镜像
信息查看docker ps -a查看所有容器
docker logs查看容器日志
docker exec进入运行中容器

8. Docker 镜像分层原理是什么?

详细答案

  • 分层结构:镜像由多个只读层(Layer)堆叠组成
  • 写时复制 (Copy-on-Write):
    • 容器启动时添加可写层
    • 修改文件:从底层复制到可写层再修改
  • 优点
    • 节省磁盘空间(层复用)
    • 加速镜像分发(仅传输新层)

示例

FROM ubuntu:22.04        # 层1:基础镜像 (100MB)
RUN apt-get update       # 层2:更新包列表 (5MB)
COPY app.py /app         # 层3:添加代码 (1MB)

总镜像大小 ≈ 106MB(非 100+5+1=106MB,因共享基础层)


9. 镜像的只读层和可写层是什么?

详细答案

层级描述容器操作
只读层镜像原有层(不可修改)读取文件直接访问
可写层容器运行时添加的层(临时)所有修改在此层进行
数据卷外部挂载的持久化存储绕过可写层直接读写

写入流程
读取文件 → 存在于可写层? → 是:直接操作 / 否:从只读层复制到可写层再操作


10. Docker 的 ENTRYPOINTCMD 区别?

详细答案

指令作用覆盖方式
ENTRYPOINT定义容器启动时的默认执行程序--entrypoint 参数
CMD定义传递给 ENTRYPOINT 的默认参数运行时命令行参数覆盖

组合规则

  • 二者共存时:CMD 作为 ENTRYPOINT 的参数
  • CMD:可作为独立命令执行

示例

# Dockerfile
ENTRYPOINT ["echo"]
CMD ["Hello World"]

# 运行
docker run app               # 输出:Hello World
docker run app "Goodbye"     # 输出:Goodbye

11. Docker 如何删除悬空镜像(dangling images)?

详细答案

  • 悬空镜像:无标签且未被任何容器引用的中间层镜像
  • 删除命令
    docker image prune  # 交互式删除
    docker rmi $(docker images -f "dangling=true" -q)  # 批量删除
    
  • 产生原因:构建新镜像时旧镜像失去标签

示例

# 查看悬空镜像
docker images -f "dangling=true"

12. Docker 中 COPYADD 的区别?

详细答案

指令功能特性
COPY复制本地文件到镜像仅支持基本复制
ADD额外支持:1. 自动解压 tar 文件
2. 从 URL 下载文件

最佳实践

  • 优先使用 COPY(更透明)
  • 仅需解压或下载时用 ADD

示例

COPY app.py /app           # 复制文件
ADD data.tar.gz /data      # 复制并自动解压

13. 什么是 Dockerfile?

详细答案

  • 定义:文本文件包含构建镜像的指令序列
  • 作用
    • 自动化镜像构建
    • 确保环境一致性
  • 构建命令docker build -t myapp:v1 .

基础结构

# 指定基础镜像
FROM ubuntu:22.04

# 设置工作目录
WORKDIR /app

# 复制文件
COPY . .

# 安装依赖
RUN apt-get update && apt-get install -y python3

# 定义启动命令
CMD ["python3", "app.py"]

14. Dockerfile 常见指令有哪些?

详细答案

指令作用示例
FROM指定基础镜像FROM python:3.9-slim
RUN执行命令RUN pip install requests
COPY复制文件COPY . /app
ADD高级复制(解压/下载)ADD data.tar.gz /data
ENV设置环境变量ENV PORT=8080
EXPOSE声明监听端口EXPOSE 80
CMD容器启动命令CMD ["flask", "run"]
ENTRYPOINT容器入口程序ENTRYPOINT ["/entrypoint.sh"]
USER切换运行用户USER appuser

15. WORKDIRRUN cd 的区别?

详细答案

方式特点示例
WORKDIR持久化工作目录(影响后续指令)WORKDIR /app
RUN cd仅对当前 RUN 指令有效(后续指令重置)RUN cd /app && do_something

最佳实践
始终使用 WORKDIR 确保路径一致性

错误示例

RUN cd /app   # 仅当前层有效
RUN pwd       # 输出仍是 / (不是 /app)

16. Docker 中 EXPOSE-p 的区别?

详细答案

项目作用范围
EXPOSE声明容器监听的端口(元数据)Dockerfile 内部
-p映射宿主机端口到容器端口(实际可访问)运行时参数

示例

# Dockerfile
EXPOSE 8080
# 运行时映射端口
docker run -p 80:8080 myapp

此时外部通过宿主机 80 端口访问容器 8080 端口


17. 如何查看容器运行的日志?

详细答案

  • 命令docker logs [选项] 容器名/ID
  • 常用选项
    • -f:实时跟踪日志
    • --tail N:显示最后 N 行
    • -t:显示时间戳

示例

docker logs -f --tail 100 my_container

日志驱动
支持 JSON-file(默认)、Syslog、Fluentd 等


18. 如何进入一个正在运行的容器?

详细答案
两种方式:

  1. 交互式 Shell
    docker exec -it my_container /bin/bash
    
  2. 执行单条命令
    docker exec my_container ls /app
    

区别

  • exec:在运行中容器执行新进程
  • attach:附加到容器主进程(退出会导致容器停止)

19. 如何将本地目录挂载到容器中?

详细答案
两种挂载方式:

  1. 绑定挂载(Bind Mount)
    docker run -v /host/path:/container/path nginx
    
    • 直接映射主机目录
    • 适合开发环境(代码热更新)
  2. 数据卷(Volume)
    docker volume create my_vol
    docker run -v my_vol:/container/path nginx
    
    • Docker 管理的持久化存储
    • 适合生产环境(安全/易备份)

权限控制

  • 只读挂载::ro 后缀(如 -v data:/app:ro

20. 如何限制容器的 CPU 和内存使用?

详细答案
通过 --cpus--memory 参数限制:

docker run -d \
  --cpus=1.5 \          # 限制使用 1.5 核 CPU
  --memory=512m \       # 限制内存为 512MB
  --memory-swap=1g \    # 内存+Swap 总计 1GB
  nginx

资源监控

docker stats my_container
# 输出示例:
CONTAINER   CPU %   MEM USAGE / LIMIT   MEM %
nginx       0.01%   5MiB / 512MiB       0.98%

底层机制

  • 通过 Linux cgroups 实现资源隔离
  • OOM 处理:内存超限时容器被强制终止

二、Docker 网络与存储


21. Docker 网络模式有哪些?分别适用什么场景?

详细答案
Docker 支持 5 种网络模式:

模式描述适用场景
bridge默认模式,容器通过虚拟网桥连接单主机容器隔离通信
host容器直接使用宿主机网络栈高性能网络需求(如负载测试)
none禁用所有网络安全敏感场景(离线数据处理)
overlay跨主机容器网络(Swarm/K8s)多节点集群服务通信
macvlan容器分配独立 MAC 地址(类似物理设备)容器需直接暴露在物理网络

查看模式

docker network ls

22. bridge 网络模式和 host 网络模式的区别?

详细答案

特性bridge 模式host 模式
网络隔离容器有独立 IP 和网络命名空间共享宿主机网络命名空间
性能较低(NAT 转发开销)高(无额外转发)
端口映射-p 参数暴露端口容器端口直接使用宿主机端口
安全性较高(默认隔离)较低(直接暴露)
IP 分配Docker 分配私有 IP(172.17.0.0/16)使用宿主机 IP

示例

# bridge 模式(默认)
docker run -d -p 8080:80 nginx

# host 模式
docker run -d --network=host nginx  # 直接使用宿主机80端口

23. overlay 网络模式是什么?什么时候用?

详细答案

  • 定义:基于 VXLAN 实现的跨主机容器网络,允许不同物理机上的容器直接通信
  • 核心组件
    • 键值存储(Consul/etcd)同步网络状态
    • Docker Swarm 模式自动管理
  • 使用场景
    • Docker Swarm 集群服务通信
    • Kubernetes Pod 跨节点通信(需 CNI 插件)

创建流程

  1. 初始化 Swarm:docker swarm init
  2. 创建 overlay 网络:docker network create -d overlay my-overlay
  3. 在集群中启动服务:docker service create --network=my-overlay nginx

优势

  • 容器 IP 跨主机可达
  • 内置服务发现(通过服务名访问)

24. 容器如何相互通信?

详细答案
三种通信方式:

  1. 同一 bridge 网络:通过容器 IP 或容器名直接访问
    docker run -d --name web --network=my-bridge nginx
    docker run -it --network=my-bridge alpine ping web
    
  2. Link 连接(已废弃)--link 参数(不推荐)
  3. 自定义网络:创建用户定义的 bridge 网络
    docker network create app-net
    docker run -d --net=app-net --name app1 myapp
    docker run -d --net=app-net --name app2 myapp
    

最佳实践

  • 使用自定义网络替代默认 bridge
  • Swarm/K8s 集群使用 overlay 网络

25. Docker 如何暴露容器端口?

详细答案
两种暴露方式:

  1. 运行时映射 (-p/--publish):
    # 映射宿主机8080→容器80
    docker run -d -p 8080:80 nginx
    
    # 随机映射
    docker run -d -p 80 nginx
    
  2. Dockerfile 声明 (EXPOSE):
    EXPOSE 80  # 元数据声明,实际暴露仍需 -p
    

查看映射

docker port <container>  # 查看端口绑定

26. 什么是 Docker Volume?

详细答案

  • 定义:由 Docker 管理的持久化数据存储机制
  • 特点
    • 独立于容器生命周期(容器删除后保留)
    • 支持备份、迁移和共享
    • 存储在宿主机特定目录(Linux:/var/lib/docker/volumes/)
  • 操作命令
    • docker volume create
    • docker volume ls
    • docker volume inspect

示例

docker volume create db_data
docker run -d -v db_data:/var/lib/mysql mysql

27. Volume、Bind Mount、tmpfs mount 区别?

详细答案

类型数据存储位置特点
VolumeDocker 管理目录 (/var/lib/docker/volumes)跨容器共享、易备份
Bind Mount用户指定宿主机路径直接访问主机文件系统
tmpfs mount仅存内存(不持久化)高性能临时存储

使用场景对比

  • Volume:生产环境数据库存储
  • Bind Mount:开发环境代码热更新
  • tmpfs:敏感数据临时处理

挂载示例

# Volume
docker run -v myvol:/data app

# Bind Mount
docker run -v /host/path:/container/path app

# tmpfs
docker run --tmpfs /app/cache app

28. 如何在多个容器之间共享数据?

详细答案
两种共享方式:

  1. Volume 共享
    docker volume create shared_data
    docker run -d -v shared_data:/data --name writer busybox sh -c "echo 'test' > /data/file"
    docker run -it -v shared_data:/data --name reader busybox cat /data/file
    
  2. Bind Mount 共享
    # 多个容器挂载同一主机目录
    docker run -v /host/data:/data container1
    docker run -v /host/data:/data container2
    

注意事项

  • Volume 更适合生产环境(权限隔离)
  • 避免并发写入冲突(需应用层处理)

29. 如何将容器的数据持久化?

详细答案
持久化方案:

  1. Volume 持久化(推荐):
    docker volume create app_data
    docker run -d -v app_data:/app/data myapp
    
  2. Bind Mount 持久化
    docker run -d -v /opt/app/data:/app/data myapp
    
  3. 数据库导出
    docker exec mysql sh -c 'mysqldump -u root -p$MYSQL_ROOT_PASSWORD db > /backup/db.sql'
    

数据迁移

# 备份 Volume
docker run --rm -v app_data:/source -v $(pwd):/backup alpine tar cvf /backup/app_data.tar /source

# 恢复 Volume
docker run --rm -v app_data:/target -v $(pwd):/backup alpine tar xvf /backup/app_data.tar -C /

30. OverlayFS 是什么?

详细答案

  • 定义:Linux 联合文件系统(Union Filesystem),Docker 的默认存储驱动
  • 核心机制
    • LowerDir:只读镜像层(可多层)
    • UpperDir:容器可写层
    • MergedDir:统一视图目录
  • 写时复制 (Copy-on-Write):
    • 读文件:优先从 UpperDir 读取,不存在则从 LowerDir 读取
    • 写文件:复制到 UpperDir 修改
    • 删文件:在 UpperDir 创建空白文件标记删除

优势

  • 节省磁盘空间
  • 加速容器启动
  • 支持快速创建容器副本

查看存储驱动

docker info | grep "Storage Driver"
# 输出:Storage Driver: overlay2

三、Docker Compose 与编排


31. 什么是 Docker Compose?

详细答案
Docker Compose 是用于定义和运行多容器应用的工具,核心功能:

  1. 声明式配置:通过 YAML 文件定义服务、网络、卷
  2. 一键启停:单命令管理整个应用生命周期
  3. 服务依赖:自动处理容器启动顺序
  4. 环境隔离:不同项目使用独立网络

解决痛点

  • 替代繁琐的 docker run 命令链
  • 统一管理复杂应用的多个组件(如 Web + DB + Cache)

示例

docker-compose up -d  # 启动所有服务
docker-compose down   # 停止并清理

32. Compose 的常用命令有哪些?

详细答案

命令作用
docker-compose up创建并启动所有服务(-d 后台运行)
docker-compose down停止并删除容器、网络
docker-compose ps查看运行中的服务容器
docker-compose logs查看服务日志(-f 实时跟踪)
docker-compose build构建或重新构建服务镜像
docker-compose exec进入运行中的容器
docker-compose config验证并查看解析后的配置

常用组合

# 重新构建并启动
docker-compose up -d --build

# 查看特定服务日志
docker-compose logs -f web

33. Docker Compose 文件的常用字段有哪些?

详细答案

字段作用示例
version指定 Compose 文件版本version: '3.8'
services定义服务列表services: web: ...
image指定服务镜像image: nginx:1.25
build构建镜像的 Dockerfile 路径build: ./app
ports端口映射ports: - "8080:80"
volumes数据卷挂载volumes: - db_data:/var/lib/mysql
environment设置环境变量environment: DEBUG: "true"
networks加入网络networks: - frontend
depends_on服务依赖关系depends_on: - db

完整示例

version: '3.8'
services:
  web:
    build: .
    ports:
      - "8000:5000"
    depends_on:
      - db
  db:
    image: postgres:14
    volumes:
      - db_data:/var/lib/postgresql/data

volumes:
  db_data:

34. depends_on 的作用是什么?

详细答案

  • 作用:控制服务启动顺序(但不保证服务已就绪)
  • 限制
    • 仅确保容器启动顺序(如先启动 DB 再启动 Web)
    • 不检测服务可用性(需应用层重试逻辑)
  • 替代方案
    • 使用健康检查(healthcheck)
    • 脚本轮询服务端口(如 wait-for-it.sh)

示例

services:
  web:
    depends_on:
      db:
        condition: service_healthy  # 等待db健康
    healthcheck:
      test: curl -f http://localhost:5000 || exit 1
      interval: 30s
  db:
    healthcheck:
      test: pg_isready -U postgres
      interval: 10s

35. 如何在 Compose 中配置网络?

详细答案
三种网络配置方式:

  1. 默认网络:自动创建名为 {project}_default 的 bridge 网络
  2. 自定义网络
    services:
      web:
        networks:
          - frontend
      db:
        networks:
          - backend
    
    networks:
      frontend:
        driver: bridge
      backend:
        driver: bridge
    
  3. 加入外部网络
    networks:
      default:
        external:
          name: existing_network
    

网络特性

  • 同网络内的容器可通过服务名互访
  • 隔离不同项目的网络环境

36. Docker Compose 和 Kubernetes 的区别?

详细答案

维度Docker ComposeKubernetes
定位单机多容器编排集群级容器编排平台
适用场景开发/测试环境生产环境
扩展能力简单服务依赖自动扩缩、自愈、负载均衡
网络模型单机网络(bridge/host)跨主机 CNI 网络(Calico/Flannel)
存储管理基础卷绑定PV/PVC/StorageClass 体系
高可用不支持内置节点/应用级高可用
配置文件docker-compose.ymlDeployment/Service YAML

演进关系
Compose → Swarm → Kubernetes(生产标准)


37. 如何在 Compose 中实现数据持久化?

详细答案
两种持久化方式:

  1. 命名卷(Named Volume)
    services:
      db:
        image: mysql:8.0
        volumes:
          - db_data:/var/lib/mysql
    
    volumes:
      db_data:  # Docker 管理存储
    
  2. 绑定挂载(Bind Mount)
    services:
      app:
        volumes:
          - ./data:/app/data  # 映射主机目录
    

数据备份

# 备份命名卷
docker run --rm -v db_data:/source -v $(pwd):/backup alpine tar cvf /backup/db_backup.tar /source

38. 如何在 Compose 中设置环境变量?

详细答案
四种设置方式:

  1. 直接声明
    services:
      web:
        environment:
          DEBUG: "true"
          PORT: 8080
    
  2. 变量文件
    env_file: .env  # 从文件加载
    
    .env 文件内容:
    DB_USER=admin
    DB_PASSWORD=secret
    
  3. Compose 变量
    services:
      db:
        image: postgres:${POSTGRES_VERSION}
    
    运行时指定:POSTGRES_VERSION=14 docker-compose up
  4. Shell 环境变量
    export DB_PASS=secret
    docker-compose up  # 自动读取当前 shell 环境变量
    

优先级
直接声明 > 变量文件 > Shell 环境变量


四、Docker 性能与安全


39. 如何优化 Docker 镜像大小?

详细答案
优化策略

  1. 选择小型基础镜像
    FROM alpine:3.18  # 仅 5MB
    # 替代 ubuntu (75MB)
    
  2. 多阶段构建
    # 阶段1:构建环境
    FROM golang:1.20 AS builder
    COPY . .
    RUN go build -o app
    
    # 阶段2:运行环境
    FROM alpine:3.18
    COPY --from=builder /app /usr/bin/app
    
  3. 合并 RUN 指令
    RUN apt-get update && \
        apt-get install -y python3 && \
        rm -rf /var/lib/apt/lists/*  # 清理缓存
    
  4. 使用 .dockerignore
    # .dockerignore
    .git
    node_modules
    *.log
    

效果

  • 典型 Java 应用:从 650MB → 150MB
  • Python 应用:从 300MB → 40MB

40. 如何减少镜像构建时间?

详细答案
加速方案

  1. 构建缓存利用
    • 将高频变更层放在 Dockerfile 底部
    • 固定依赖版本(避免缓存失效)
  2. 并行下载依赖
    RUN --mount=type=cache,target=/var/cache/apt \
        apt-get update && apt-get install -y pkg1 pkg2
    
  3. BuildKit 特性
    DOCKER_BUILDKIT=1 docker build .  # 启用并行构建
    
  4. 镜像层复用
    # 公共层单独构建
    FROM base-image AS deps
    COPY requirements.txt .
    RUN pip install -r requirements.txt
    
    # 应用层
    FROM deps AS app
    COPY . .
    

实测效果:构建时间减少 40-70%


41. Docker 容器启动慢的原因有哪些?

详细答案
常见原因

  1. 镜像过大:下载和解压耗时
    • 优化:使用小型镜像(Alpine/Distroless)
  2. 初始化脚本复杂
    • 优化:精简启动命令,异步初始化
  3. 磁盘 I/O 瓶颈
    • 优化:使用 SSD,避免主机 I/O 过载
  4. 网络延迟
    • 优化:本地镜像仓库,预拉取镜像
  5. 安全扫描
    • 优化:禁用不必要的扫描(如 Clair)

诊断命令

docker run --rm alpine time dd if=/dev/zero of=test.img bs=1G count=1  # 测试磁盘IO

42. 如何分析容器的资源使用情况?

详细答案
分析工具

  1. docker stats:实时监控
    docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
    
  2. cAdvisor:容器指标可视化
    docker run -d --name=cadvisor \
      -v /:/rootfs:ro \
      -v /var/run:/var/run:ro \
      google/cadvisor
    
  3. Prometheus + Grafana
    • 采集指标:container_cpu_usage_seconds_total
    • 内存:container_memory_usage_bytes
  4. 进入容器分析
    docker exec -it my_container top
    

43. Docker 安全性如何保障?

详细答案
安全措施

  1. 非特权用户
    USER appuser  # 避免 root 运行
    
  2. 只读文件系统
    docker run --read-only alpine
    
  3. Capabilities 限制
    docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx
    
  4. 安全扫描
    docker scan nginx  # 使用 Snyk 扫描漏洞
    
  5. Seccomp/AppArmor
    docker run --security-opt seccomp=profile.json app
    

44. 容器逃逸是什么?如何防御?

详细答案

  • 容器逃逸:攻击者突破容器隔离获取宿主机权限
  • 防御方案
    1. 内核升级:修复 CVE 漏洞(如 Dirty Pipe)
    2. 禁用危险配置
      docker run --privileged=false  # 禁用特权模式
      
    3. 只读 rootfs
      docker run --read-only ...
      
    4. 用户命名空间
      dockerd --userns-remap=default  # 启用用户映射
      
    5. 安全策略
      • 使用 gVisor 或 Kata Containers 增强隔离

45. Docker 中的 Capabilities 是什么?

详细答案

  • Capabilities:Linux 内核的权限细分机制(替代 root 全权)
  • 默认限制:容器默认仅有 14 项 capabilities(非完整 root)
  • 关键操作
    Capability权限
    CHOWN修改文件所有者
    NET_RAW创建 RAW/PACKET 套接字
    SYS_ADMIN挂载文件系统、命名空间操作

管理命令

docker run --cap-add=SYS_PTRACE --cap-drop=NET_RAW debug-tool

46. 如何为容器配置只读文件系统?

详细答案
实现方式

  1. 全局只读
    docker run --read-only alpine
    
  2. 部分可写
    docker run --read-only -v /tmp:/tmp app  # /tmp 可写
    
  3. Dockerfile 配置
    RUN mkdir /writeable && chmod a+rw /writeable
    VOLUME /writeable
    

适用场景

  • 安全敏感应用(减少攻击面)
  • 无状态服务(日志输出到 stdout)

47. 什么是 rootless Docker?

详细答案

  • 定义:无需 root 权限运行 Docker 守护进程和容器
  • 价值
    • 安全:攻击者无法获取宿主机 root
    • 兼容:普通用户可管理容器
  • 安装
    curl -fsSL https://get.docker.com/rootless | sh
    
  • 限制
    • 部分网络模式不可用(如 host 模式)
    • 性能损失约 10-20%

验证

id  # 显示普通用户
docker run hello-world

48. Docker Daemon 的工作原理?

详细答案
工作流程

  1. 监听请求
    • 通过 UNIX 套接字 /var/run/docker.sock 或 TCP 接收命令
  2. 路由处理
    • 创建/启动容器 → 调用 containerd
    • 构建镜像 → 调用 BuildKit
  3. 容器管理
    dockerd
    containerd
    containerd-shim
    runc
    container_process
  4. 状态同步
    • 存储状态到 /var/lib/docker
    • 事件通知(如容器启停)

关键组件

  • containerd:容器生命周期管理
  • runc:OCI 容器运行时实现
  • BuildKit:镜像构建引擎

五、实战与排错


49. 如何调试一个启动失败的容器?

详细答案
调试步骤

  1. 查看状态docker ps -a | grep <container_name>
  2. 检查日志docker logs <container_id>
  3. 描述容器docker inspect <container_id>(关注 State 字段)
  4. 进入容器
    # 尝试启动临时 shell
    docker run -it --rm --entrypoint=sh <image_name>
    
  5. 检查启动命令
    docker inspect --format='{{.Config.Cmd}}' <image_name>
    

常见问题

  • 端口冲突:docker run -p 8080:80 但 8080 被占用
  • 权限不足:docker run --user 1000
  • 挂载失败:docker run -v /host/path:/container/path 路径错误

50. 如何清理无用的镜像、容器和网络?

详细答案
清理命令

资源类型命令
停止的容器docker container prune
悬空镜像docker image prune
未使用镜像docker image prune -a
未使用网络docker network prune
构建缓存docker builder prune
全部无用资源docker system prune --volumes(谨慎使用)

定时清理(crontab):

# 每天凌晨清理
0 0 * * * docker system prune -af --filter "until=24h"

51. 如何将容器打包迁移到另一台机器?

详细答案
迁移方案

  1. 容器转镜像
    docker commit <container_id> my_migrated_image
    docker save my_migrated_image > image.tar
    scp image.tar user@new-host:/path
    # 在新主机加载
    docker load < image.tar
    
  2. 数据卷迁移
    # 备份卷
    docker run --rm -v db_data:/volume -v $(pwd):/backup alpine \
      tar cvf /backup/db_data.tar /volume
    # 新主机恢复
    docker run --rm -v db_data:/volume -v $(pwd):/backup alpine \
      tar xvf /backup/db_data.tar -C /
    

最佳实践

  • 使用 Docker Registry 中转镜像
  • 数据库迁移用 pg_dump/mysqldump 替代卷复制

52. 如何在 Docker 容器中运行系统服务?

详细答案
两种模式

  1. 前台运行(推荐):
    CMD ["nginx", "-g", "daemon off;"]  # 强制前台运行
    
  2. 使用 init 进程
    # 安装轻量级 init 系统
    RUN apt-get install -y runit
    CMD ["/usr/sbin/runsvdir-start"]
    

注意事项

  • 避免使用 systemd(容器非完整系统)
  • 日志输出到 stdout 以便收集

53. 如何查看容器内的进程?

详细答案
三种方法

  1. docker top
    docker top <container_id>
    # 输出:
    UID   PID    PPID  C  STIME  TTY  TIME   CMD
    root  12345  123   0  14:30  ?    00:00  nginx
    
  2. 进入容器
    docker exec -it <container_id> ps aux
    
  3. 主机视角
    # 查找容器主进程
    docker inspect -f '{{.State.Pid}}' <container_id>  # 输出 12345
    nsenter -t 12345 -p ps aux
    

54. 如何查看容器的环境变量?

详细答案
查看方法

  1. 启动时打印
    docker run --rm <image> env
    
  2. 运行中容器
    docker exec <container_id> env
    
  3. inspect 命令
    docker inspect --format='{{range .Config.Env}}{{println .}}{{end}}' <container_id>
    

特殊变量

  • HOSTNAME:容器主机名
  • HOME:用户家目录
  • PATH:可执行文件搜索路径

55. 如何升级正在运行的容器?

详细答案
标准流程

  1. 拉取新镜像docker pull new-image:v2
  2. 停止旧容器docker stop old-container
  3. 删除旧容器docker rm old-container
  4. 启动新容器
    docker run -d --name new-container \
      -v data_volume:/app/data \
      new-image:v2
    

零停机方案

  • 蓝绿部署
    # 启动新版本容器(相同网络)
    docker run -d --name app-v2 --network=app-net app:v2
    # 切换流量(如修改 Nginx 配置)
    docker exec nginx nginx -s reload
    # 停用旧版本
    docker stop app-v1
    

56. 如何回滚容器版本?

详细答案
回滚策略

  1. 镜像回滚
    docker run -d --name rollback-container \
      old-image:v1
    
  2. 数据回滚
    • 数据库:从备份恢复 mysqldump
    • 文件卷:恢复快照或备份文件
  3. 版本标签控制
    # 重新打标签
    docker tag old-image:stable old-image:rollback
    docker run -d rollback-image:rollback
    

预防措施

  • 镜像仓库保留历史版本(如 Harbor 标签保留策略)
  • 数据库定期备份

57. 如何在生产环境中部署 Docker?

详细答案
部署方案

方案适用场景工具
单机管理小型应用Docker Compose
集群管理中型应用Docker Swarm
生产级编排大型分布式系统Kubernetes(推荐)

关键实践

  1. 镜像安全
    • 私有仓库(Harbor)
    • 漏洞扫描(Trivy)
  2. 资源隔离
    docker run -d --cpus=2 --memory=1g app
    
  3. 日志收集
    docker run --log-driver=fluentd --log-opt fluentd-address=loghost:24224
    
  4. 监控告警:Prometheus + Grafana

58. 常见的 Dockerfile 优化技巧有哪些?

详细答案
优化技巧

  1. 多阶段构建
    FROM node:18 AS build
    COPY . .
    RUN npm build
    
    FROM nginx:alpine
    COPY --from=build /app/dist /usr/share/nginx/html
    
  2. 构建缓存
    # 先复制依赖文件(利用缓存)
    COPY package.json yarn.lock .
    RUN yarn install
    COPY . .  # 代码变更频繁放后面
    
  3. 减少层数
    RUN apt-get update && \
        apt-get install -y python3 && \
        rm -rf /var/lib/apt/lists/*  # 单层完成
    
  4. 使用小型镜像
    FROM python:3.11-slim  # 替代完整版
    
  5. 非 root 用户
    RUN groupadd -r appuser && useradd -r -g appuser appuser
    USER appuser
    

优化效果

  • 构建时间减少 40%
  • 镜像体积缩小 70%
  • 安全性显著提升

六、进阶与集成


59. 什么是多阶段构建(Multi-stage build)?

详细答案
多阶段构建是一种 Dockerfile 优化技术,允许在单个 Dockerfile 中使用多个 FROM 指令,每个阶段独立构建,最终仅将必要文件复制到最终镜像。

核心价值

  1. 减小镜像体积:构建工具和中间文件不会进入最终镜像
  2. 提升安全性:减少攻击面(不包含编译器等)
  3. 简化构建流程:单文件管理复杂构建链

示例

# 阶段1:构建环境(含JDK)
FROM maven:3.8-jdk-11 AS builder
COPY . .
RUN mvn package -DskipTests

# 阶段2:运行环境(仅JRE)
FROM openjdk:11-jre-slim
COPY --from=builder /target/app.jar /app.jar
CMD ["java", "-jar", "/app.jar"]

最终镜像从 600MB → 150MB


60. Docker 和 CI/CD 如何结合?

详细答案
集成流程

代码提交
CI 平台
构建镜像
扫描镜像
推送仓库
CD 部署

典型工具链

阶段工具Docker 命令
构建Jenkins/GitHub Actionsdocker build -t app:v1 .
扫描Trivy/Clairdocker scan app:v1
推送Harbor/Docker Hubdocker push harbor.com/app
部署Argo CD/K8skubectl apply -f deploy.yaml

GitHub Actions 示例

name: CI/CD Pipeline
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Build Docker image
      run: docker build -t myapp:${{ github.sha }} .
    - name: Push to Harbor
      run: docker push harbor.com/myapp:${{ github.sha }}

61. Docker 与 Kubernetes 的关系?

详细答案
层级关系

Kubernetes
Docker
调度/Pod/Service
容器编排
Deployment/Ingress
应用管理
containerd
容器运行时
runc

核心关系

  1. 运行时依赖:K8s 通过 CRI 接口调用 containerd(Docker 组件)运行容器
  2. 镜像标准:K8s 使用 OCI 镜像(Docker 镜像格式)
  3. 演进趋势
    • Docker → containerd → CRI-O(轻量级替代)
    • K8s v1.24+ 默认移除 dockershim

最佳实践:生产环境直接使用 containerd 而非完整 Docker


62. 如何在 Kubernetes 中使用 Docker 镜像?

详细答案
使用流程

  1. 构建镜像docker build -t myapp:v1 .
  2. 推送仓库docker push registry.com/myapp:v1
  3. K8s 部署
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp
    spec:
      template:
        spec:
          containers:
          - name: app
            image: registry.com/myapp:v1  # 使用Docker镜像
            imagePullPolicy: IfNotPresent
    

关键配置

  • imagePullSecrets:私有仓库认证
  • imagePullPolicy:镜像拉取策略(Always/Never/IfNotPresent)

63. 为什么 Docker 要从 dockerd 迁移到 containerd

详细答案
根本原因

  1. 架构解耦
    • Docker → 大而全(构建/网络/存储)
    • containerd → 专注容器运行时(更轻量)
  2. K8s 兼容
    • K8s 通过 CRI 标准调用运行时
    • containerd 原生支持 CRI(dockerd 需 shim 转换)
  3. 性能提升
    • 减少调用链:kubelet → containerd(跳过 dockerd)
    • 容器启动加速 30%

架构对比

组件Docker 时代containerd 时代
容器运行时dockerd → containerd → runckubelet → containerd → runc
镜像管理Docker Enginecontainerd + ctr

64. Docker Swarm 是什么?和 K8s 的区别?

详细答案
Docker Swarm

  • Docker 官方提供的轻量级容器编排工具
  • 核心特性:
    • 内置于 Docker Engine(docker swarm init
    • 声明式服务管理(docker-compose.yml)
    • 自动负载均衡

与 K8s 对比

维度Docker SwarmKubernetes
学习曲线简单(Docker 命令扩展)陡峭
功能范围基础编排(服务/扩缩/网络)全功能(存储/网络/策略)
集群规模≤100 节点≥1000 节点
社区生态衰退(Docker 公司战略调整)繁荣(CNCF)
适用场景中小集群快速部署企业级生产环境

Swarm 示例

docker swarm init
docker service create --name web --replicas 3 -p 80:80 nginx

65. 如何构建支持多架构的镜像?

详细答案
两种实现方式

  1. manifest 合并(手动):
    # 构建不同架构镜像
    docker buildx build --platform linux/amd64 -t app:amd64 .
    docker buildx build --platform linux/arm64 -t app:arm64 .
    
    # 创建多架构清单
    docker manifest create app:multi \
      --amend app:amd64 \
      --amend app:arm64
    docker manifest push app:multi
    
  2. Buildx 自动构建(推荐):
    docker buildx create --use  # 启用Buildx
    docker buildx build \
      --platform linux/amd64,linux/arm64 \
      -t username/app:v1 \
      --push .  # 自动推送多架构镜像
    

验证

docker manifest inspect username/app:v1
# 输出包含 amd64/arm64 架构

66. 如何在 Docker 中运行无 root 权限的应用?

详细答案
安全实践

  1. Dockerfile 配置
    FROM alpine
    RUN addgroup -S appgroup && adduser -S appuser -G appgroup
    USER appuser  # 切换到非root用户
    CMD ["myapp"]
    
  2. 运行时限制
    docker run -d \
      --user 1000:1000 \  # 指定UID:GID
      --cap-drop=ALL \     # 移除所有特权
      --read-only \        # 只读文件系统
      myapp
    
  3. rootless 模式
    # 安装rootless Docker
    curl -fsSL https://get.docker.com/rootless | sh
    systemctl --user start docker
    

权限验证

docker run --rm alpine id
# 输出:uid=1000(appuser) gid=1000(appgroup)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值