CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Docker 容器入门/课时/综合练习与 K8s 方向
RawBlame
课时目录12 节

Docker 容器入门

  1. 01容器是什么
  2. 02安装与环境
  3. 03Docker CLI 基础
  4. 04镜像与分层
  5. 05编写 Dockerfile
  6. 06构建与优化
  7. 07镜像仓库
  8. 08数据卷与挂载
  9. 09网络
  10. 10Docker Compose
  11. 11容器安全基础
  12. 12综合练习与 K8s 方向

综合练习与 K8s 方向

容器化 CodeRoadMap 组件;Kubernetes 下一步。

45 分钟

综合练习与 K8s 方向

这一课你将能做到

  1. 独立完成一次全链路演练:Spring Boot 项目 → 多阶段 Dockerfile → compose 三件套 → 一键部署 → 数据持久化验证 → 镜像发布
  2. 用一份自检清单验收你的容器化工程,确保每一课的关键点(缓存、卷、网络、健康检查、安全)都没有漏项
  3. 说清 Docker 之后为什么要学 Kubernetes,能画出两者的概念映射表并规划下一步路径

为什么要学

前 11 课的知识是散装的:Dockerfile 在第 5、6 课,卷在第 8 课,网络在第 9 课,编排在第 10 课。真实项目里它们必须同时正确,任何一环掉链子都是「本地好好的,部署就出事」。本课把它们串成一条可重复执行的部署流水线——这既是你的实战验收,也是可以直接抄进个人项目/简历的工程模板。

最后,本课回答 Docker 学习的终极问题:「然后呢?」答案是 Kubernetes——但先要把单机玩明白,K8s 的每个概念在 Docker 里都有对应物,你会带着地图进入下一站。

先建立图像

完整流水线全景图:

开发机                                     生产服务器(Linux)
┌────────────────────────────┐            ┌──────────────────────────┐
│ mvn package(或镜像内构建)    │            │ docker pull ←── Registry │
│ docker build(多阶段+非root)│──push────→ │ docker compose up -d     │
│ docker compose 配置          │            │   ├ app    :8080 →公网    │
│ docker tag + push           │            │   ├ mysql  数据卷持久化    │
└────────────────────────────┘            │   └ redis  仅内网互通     │
                                          └──────────────────────────┘

最终项目结构(这就是你的模板):

my-project/
├── src/                     # Spring Boot 源码
├── pom.xml
├── Dockerfile               # 多阶段 + 非 root + TZ + exec 格式
├── .dockerignore
├── docker-compose.yml       # app + mysql + redis
├── .env                     # 密码(不入 git)
├── .env.example             # 密码模板(入 git)
└── .gitignore               # 含 .env

跟着做

步骤 1:完善 Dockerfile(多阶段 + 非 root + 健康检查)

# ---- 构建阶段 ----
FROM maven:3.9-eclipse-temurin-21 AS builder
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline -B
COPY src ./src
RUN mvn clean package -DskipTests

# ---- 运行阶段 ----
FROM eclipse-temurin:21-jre
ENV TZ=Asia/Shanghai
RUN useradd -r -u 10001 appuser
USER appuser
WORKDIR /app
COPY --from=builder --chown=appuser:appuser /build/target/app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-XX:MaxRAMPercentage=75.0", "-jar", "app.jar"]

健康检查不用额外装 curl(JRE 镜像没有),直接复用 Java:

HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
  CMD ["java", "-jar", "-Dspring.main.web-application-type=none", "-Dloader.main=org.springframework.boot.actuate.endpoint.HealthEndpointMain", "app.jar"]

过于复杂时,务实做法是健康检查放到 compose 层做(下一步),镜像内不放——两种选一即可。

步骤 2:最终版 docker-compose.yml

services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: appdb
    volumes:
      - mysql-data:/var/lib/mysql
    networks: [app-net]
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]
      interval: 5s
      timeout: 3s
      retries: 12
      start_period: 30s
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}"]
    volumes:
      - redis-data:/data
    networks: [app-net]
    restart: unless-stopped

  app:
    build: .
    image: myteam/demo-app:1.0.0
    ports:
      - "8080:8080"
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/appdb
      SPRING_DATASOURCE_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      SPRING_DATA_REDIS_HOST: redis
      SPRING_DATA_REDIS_PASSWORD: ${REDIS_PASSWORD}
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_started
    networks: [app-net]
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 1g

volumes:
  mysql-data:
  redis-data:

networks:
  app-net:

(deploy.resources.limits 在 compose v2 中对 docker compose up 生效,实现内存限额。)

步骤 3:本地一键验收

docker compose up -d --build
docker compose ps                 # mysql (healthy)、app (running)
curl http://localhost:8080/actuator/health

步骤 4:执行「灾难演练」验证数据与自愈

# 演练 1:数据跨容器存活
docker compose exec mysql mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "CREATE DATABASE demo; USE demo; CREATE TABLE t(id INT); INSERT INTO t VALUES (7);"
docker compose up -d --force-recreate --no-deps mysql   # 重建 mysql 容器
docker compose exec mysql mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT * FROM demo.t;"
# 输出 7 —— 卷生效

# 演练 2:进程自愈
docker compose exec app kill 1       # 杀掉主进程,观察容器
docker compose ps                    # restart 策略把它拉了回来

# 演练 3:全量重建后数据仍在
docker compose down
docker compose up -d
docker compose exec mysql mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT * FROM demo.t;"
# 输出 7 —— down 不删卷

步骤 5:发布镜像到仓库

docker login
docker tag myteam/demo-app:1.0.0 myteam/demo-app:1.0.0-a1b2c3d   # 版本+commit 双 tag
docker push myteam/demo-app:1.0.0
docker push myteam/demo-app:1.0.0-a1b2c3d

步骤 6:服务器部署(Linux + Engine)

# 服务器上首次部署
git clone <你的仓库> && cd my-project   # 或只 scp compose 文件与 .env
cp .env.example .env && vim .env        # 填生产密码
docker compose pull                     # 拉取 registry 上的 app 镜像
docker compose up -d
curl http://localhost:8080/actuator/health

步骤 7:日常更新与回滚 SOP

# 更新(零停机目标下的标准三步)
docker compose pull app
docker compose up -d app
docker image prune -f

# 回滚:改 .env 中镜像 tag 或 compose 里 image 的版本,再 up -d

步骤 8:验收自检清单(逐项打勾)

  1. Dockerfile:多阶段构建 ✓ 非 root ✓ exec 格式入口 ✓ TZ ✓
  2. .dockerignore 排除 .git/logs ✓ 构建上下文 < 50MB
  3. compose:服务名互连 ✓ healthcheck + service_healthy ✓ restart 策略 ✓
  4. 数据:mysql/redis 均 named volume ✓ down 不丢数据(演练 3 通过)✓
  5. 安全:密码只在 .env ✓ .env 不入 git ✓ mysql/redis 无公网端口 ✓
  6. 发布:双 tag(版本+commit)✓ 服务器 pull 部署 ✓ 回滚流程演练过 ✓

讲清楚要点

  1. 这套模板覆盖了单机生产的完整闭环:构建(多阶段)、编排(compose)、持久化(卷)、时序(healthcheck)、自愈(restart)、发布(registry)、回滚(tag 切换)。把它当作你的脚手架,而不是从零发明。

  2. 「构建一次,处处运行」是容器化的灵魂:CI 或本机构建出的镜像 push 一次,测试/预发/生产拉的都是同一个 digest——排查问题时环境差异这个变量被彻底消除。

  3. K8s 要解决的问题是单机方案的三个天花板:

    • 单机 = 单点故障,机器挂了服务全停 → K8s 多节点调度与自愈;
    • 流量涨了只能纵向加配 → K8s 横向扩缩容(HPA);
    • 手动部署/回滚易错 → K8s 声明式滚动发布与版本回退。
  4. 概念映射表(Docker → K8s),进入 K8s 前先背熟:

    Docker 世界K8s 世界说明
    容器PodPod 是 1~N 个紧耦合容器的调度单位
    compose serviceDeployment定义镜像、副本数、更新策略
    restart: unless-stoppedReplicaSet 自愈挂了自动重建并重新调度
    -p 8080:8080Service集群内稳定访问入口 + 负载均衡
    容器名 DNSService DNS/Ingress集群内/外部访问统一抽象
    .env / 环境变量ConfigMap / Secret配置与密钥的集群级管理
    named volumePV / PVC持久卷与动态供给
    healthcheckliveness/readiness probe存活与就绪两个维度
  5. K8s 学习路径建议:先用 minikube 或 kind 在本机起集群 → 掌握 Pod/Deployment/Service 三件套 → 加上 Ingress、ConfigMap/Secret → 再学 PV/PVC 与 HPA → 最后看 Helm 与 GitOps。你现在的 compose 心智模型能直接迁移。

你可能会懵的地方

  • 什么时候才真的需要 K8s? 信号:多台服务器、需要高可用与零停机发布、流量波动需要弹性、微服务数量多到 compose 文件难以维护。如果你的系统就是单机几个服务,compose + 稳定的 SOP 是更务实的选择——不要为了简历堆砌复杂度。

  • K8s 还用 Docker 吗?听说「K8s 抛弃了 Docker」? K8s 1.24 起弃用的是 dockershim(K8s 直连 Docker 的适配层),改用 containerd 等标准 CRI 运行时。但你构建的 OCI 镜像完全通用,Docker 构建的镜像在 K8s 里照跑不误。你学的 Docker 知识没有作废,反而是 K8s 的地基。

  • Spring Boot 上 K8s 前还要补什么? 健康检查端点(actuator 已就绪)、优雅停机、日志输出到 stdout(让 K8s 收集)、配置外部化(ConfigMap 替代 application-prod.yml)、无状态化(会话不进内存)。这五点在容器阶段就该养成。

  • 我的项目只有一个 Spring Boot + MySQL,这套模板是不是过度设计? 不是。卷、健康检查、restart 策略、双 tag,每一样都在防一类具体事故;省略它们省下的十分钟,会在某次凌晨故障里加倍还回去。复杂度可以裁剪,习惯不能省。

  • 下一步最值得投入的方向排序? ① K8s 基础(部署能力跃迁);② CI/CD(GitHub Actions / Jenkins,把本课 SOP 自动化);③ 可观测性(Prometheus + Grafana 监控容器);④ 服务网格与云原生进阶。按此顺序投入产出比最高。

错法对照

错法问题正解
各课知识孤立使用(有卷没健康检查、有 compose 没 restart)事故从漏项里长出来按本课自检清单逐项验收
服务器上 docker build 部署构建慢、依赖网络、环境不一致CI/本地构建 → push → 服务器 pull
只有 latest 一个 tag无法回滚、无法追溯版本 + commit 双 tag
直接上 K8s 跳过 compose缺单机编排直觉,概念悬空先 compose 熟练,再迁移 K8s
演练只验证「能启动」数据丢失/自愈失效上线才发现本课三个灾难演练必须全过
面试讲容器化只说「会 docker 命令」停留在工具层讲完整流水线 + 每个环节防的事故

卡点急救

  1. 服务器 compose up 报找不到镜像:compose 里 image 与你 push 的仓库全名不一致;或忘了先 docker login 私有仓库。核对全名后 docker compose pull。
  2. 演练 1 里 SQL 报密码错误:-p$MYSQL_ROOT_PASSWORD 是 shell 变量,需先在当前 shell set -a; source .env; set +a(或直接手敲密码)。
  3. kill 1 后容器没被拉起:restart: unless-stopped 在你手动 compose stop 后不会自动恢复;确认策略写对且不是手动停止状态。
  4. 健康检查一直 starting:首次 MySQL 初始化超过 start_period;或 actuator 未引入依赖。加 spring-boot-starter-actuator 并放宽时间。
  5. K8s 入门无从下手:装 minikube(minikube start),把本课 compose 的 app 翻译成 Deployment + Service YAML,跑通后再加 Ingress——一次只迁移一个概念。

面试常问

  • 完整描述你如何把一个 Spring Boot 项目容器化并上生产?(串讲题,必背) 按「构建 → 编排 → 持久化 → 发布 → 部署 → 运维」六段回答:多阶段 Dockerfile(依赖缓存+非 root+exec 入口);compose 编排 app/mysql/redis(服务名互连+healthcheck 时序);数据落 named volume 并定期备份;双 tag 推私库;服务器 pull + up -d;restart 自愈 + 演练过数据重建与回滚。能加上「每个环节防什么事故」就是高分答案。

  • Docker 到 Kubernetes 的演进逻辑? 单机容器解决了环境一致性与交付标准化,但多机场景下无法自动调度、故障自愈、弹性伸缩。K8s 以声明式 API 管理集群资源:Pod/Deployment/Service 对应容器/编排/访问入口,本质是把 compose 的思想扩展到多机。

  • 生产环境你们怎么做容器化应用的更新与回滚? 更新:CI 构建新版本镜像(版本+commit tag)→ push → 服务器 compose pull && compose up -d app(或 K8s 滚动更新)。回滚:把镜像 tag 切回上一版本重新部署,秒级完成;配合健康检查确保旧版本流量切走前新版本就绪。

  • 容器化给运维带来了哪些改变? 部署物从「脚本+文档」变成不可变镜像;扩容从「装环境」变成「拉镜像起容器」;排障从「登机器翻文件」变成「logs/exec/stats 标准化操作」;配置从「机器上散落」变成「环境变量/compose/配置中心集中管理」。

自测三问

  1. 不看文档,手写完整的多阶段 Dockerfile(含非 root、TZ、exec 格式、MaxRAMPercentage)。
  2. 说出灾难演练三连(数据跨容器、进程自愈、全量重建)各自的命令与预期结果。
  3. 把 compose 里的 app 服务翻译成 K8s 概念,需要哪几个资源对象?各自对应 compose 的哪段配置?

小结一句话

把 11 课串成「构建 → 编排 → 持久化 → 发布 → 部署 → 自愈」的完整流水线,你就掌握了单机容器化的全部工程能力——而这张概念地图,正是通往 Kubernetes 的入场券。

延伸

  • Docker 官方入门完结合集
  • Kubernetes 官方中文文档
  • minikube 快速上手
  • 下一站建议:站内 Kubernetes 路线图——从 Pod 与 Deployment 开始,把本课的 compose 模板翻译成集群配置。
加载本节练习…
← 上一课容器安全基础