10年老兵带你学Java(第20课):容器化与DevOps - Docker + CI/CD持续交付

本课目标

  • 理解什么是 Docker,为什么它是现代部署的标配
  • 掌握 Docker 基本命令
  • 能够将 Spring Boot 项目打包成 Docker 镜像
  • 理解什么是 CI/CD,以及 GitHub Actions 的用法
  • 学会搭建一个基本的自动化部署流水线

一、为什么需要 Docker?

1.1 经典问题:“在我电脑上是好的”

程序员最常听到的一句话:

“本地测试没问题啊,怎么服务器上报错了?”

问题根源:环境不一致。

  • 本地:Windows/macOS,JDK 17,MySQL 8.0
  • 服务器:Linux,JDK 11,MySQL 5.7

Python 程序员有句玩笑:“pip install 没问题,但那是在我的虚拟环境里。”

1.2 Docker 是什么?

Docker是一个容器化技术。它把应用连同它的运行环境一起打包,形成一个镜像。镜像在哪运行,环境就完全一致。

对比:

传统部署Docker部署
速度安装配置繁琐,耗时1-2小时下载镜像,几秒启动
一致性依赖服务器环境,经常出问题环境完全一致
扩展买新服务器,重新安装配置直接启动多个容器
隔离性不同项目依赖冲突容器间完全隔离

1.3 核心概念

  • 镜像(Image):模板,只读的。相当于Java里的Class
  • 容器(Container):镜像的实例,运行中的程序。相当于Java里的Object
  • 仓库(Repository):存放镜像的地方。Docker Hub = GitHub

二、Docker 快速上手

2.1 安装

Linux(Ubuntu):

sudoaptupdatesudoaptinstalldocker.io# 启动sudosystemctl startdockersudosystemctlenabledocker# 测试docker--version

macOS/Windows:
下载Docker Desktop:https://www.docker.com/products/docker-desktop

2.2 常用命令

# 拉取镜像dockerpull mysql:8.0# 运行容器dockerrun-d--namemysql-p3306:3306-eMYSQL_ROOT_PASSWORD=123456mysql:8.0# 查看运行中的容器dockerps# 查看所有容器dockerps-a# 进入容器内部dockerexec-itmysql /bin/bash# 停止/启动容器dockerstop mysqldockerstart mysql# 删除容器dockerrmmysql# 查看镜像dockerimages# 删除镜像dockerrmi mysql:8.0# 查看日志dockerlogs-fmysql

2.3 运行 MySQL 和 Redis

# MySQLdockerrun-d\--namemysql\-p3306:3306\-eMYSQL_ROOT_PASSWORD=123456\-eMYSQL_DATABASE=scan_order\mysql:8.0# Redisdockerrun-d\--nameredis\-p6379:6379\redis:7

三、把 Spring Boot 项目打成 Docker 镜像

3.1 编写 Dockerfile

在项目根目录新建Dockerfile

# 第一阶段:构建 FROM maven:3.9-openjdk-17 AS builder WORKDIR /app COPY pom.xml . COPY src ./src RUN mvn clean package -DskipTests # 第二阶段:运行 FROM openjdk:17-jdk-slim WORKDIR /app COPY --from=builder /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]

或者如果你本地已经打包好了 jar 包,更简单的写法:

FROM openjdk:17-jdk-slim WORKDIR /app COPY target/scan-order-backend-1.0.0.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]

.dockerignore文件(避免把不需要的东西打入镜像):

target/ .git/ *.md Dockerfile

3.2 构建镜像

# 进入项目目录cdscan-order-backend# 打包(如果还没打包)mvn clean package-DskipTests# 构建镜像dockerbuild-tscan-order-backend:1.0.0.# 查看镜像dockerimages

3.3 运行容器

dockerrun-d\--namescan-order\-p8080:8080\-eSPRING_DATASOURCE_URL=jdbc:mysql://host.docker.internal:3306/scan_order\-eSPRING_DATASOURCE_USERNAME=root\-eSPRING_DATASOURCE_PASSWORD=123456\scan-order-backend:1.0.0

host.docker.internal是 Docker 提供的特殊域名,指向宿主机。


四、使用 Docker Compose 编排多个服务

4.1 docker-compose.yml

一台服务器上往往有多个服务一起跑(Java应用 + MySQL + Redis + Nginx)。docker-compose可以一键启动/停止所有服务。

version:'3.8'services:mysql:image:mysql:8.0container_name:mysqlports:-"3306:3306"environment:MYSQL_ROOT_PASSWORD:123456MYSQL_DATABASE:scan_ordervolumes:-./data/mysql:/var/lib/mysqlredis:image:redis:7container_name:redisports:-"6379:6379"backend:build:./scan-order-backendcontainer_name:scan-order-backendports:-"8080:8080"depends_on:-mysql-redisenvironment:SPRING_DATASOURCE_URL:jdbc:mysql://mysql:3306/scan_orderSPRING_DATASOURCE_USERNAME:rootSPRING_DATASOURCE_PASSWORD:123456SPRING_REDIS_HOST:redisnginx:image:nginx:alpinecontainer_name:nginxports:-"80:80"volumes:-./nginx/nginx.conf:/etc/nginx/nginx.confdepends_on:-backend
# 一键启动所有服务docker-composeup-d# 查看状态docker-composeps# 一键停止docker-composedown# 查看日志docker-composelogs-fbackend

五、CI/CD:代码提交自动部署

5.1 什么是 CI/CD?

  • CI(持续集成):代码提交后,自动构建、自动测试
  • CD(持续交付/部署):构建成功后,自动部署到服务器

没有 CI/CD 时:

程序员 → git push → 打包jar → 上传到服务器 → 运行 → 观察日志 ↑ 以上全是手动操作,耗时且容易出错

有了 CI/CD 后:

程序员 → git push → GitHub Actions 自动构建 → 自动部署到服务器 ↑ 全自动,几分钟后新功能上线

5.2 GitHub Actions 使用

GitHub Actions 是 GitHub 免费的 CI/CD 工具,只要你把代码放在 GitHub 上就能用。

创建 workflow 文件:

在项目根目录创建.github/workflows/deploy.yml

name:Build and Deployon:push:branches:[main]jobs:build-and-deploy:runs-on:ubuntu-lateststeps:-uses:actions/checkout@v3# 设置JDK 17-name:Set up JDK 17uses:actions/setup-java@v3with:java-version:'17'distribution:'temurin'# 缓存Maven依赖(加快构建速度)-name:Cache Maven packagesuses:actions/cache@v3with:path:~/.m2/repositorykey:${{runner.os}}-m2-${{hashFiles('**/pom.xml')}}# 构建-name:Build with Mavenrun:mvn clean package-DskipTests# 构建Docker镜像-name:Build Docker imagerun:|docker build -t scan-order-backend:${{ github.sha }} .# 部署到服务器(通过SSH)-name:Deploy to Serveruses:appleboy/ssh-action@masterwith:host:${{secrets.SERVER_HOST}}username:rootkey:${{secrets.SERVER_SSH_KEY}}script:|cd /opt/scan-order docker-compose pull docker-compose up -d# 通知(可选)notify:runs-on:ubuntu-latestneeds:build-and-deployif:always()steps:-name:企业微信机器人通知uses:w9jbs/fishrobot@masterwith:webhook:${{secrets.WX_WEBHOOK}}msg:"✅ 项目构建完成,版本:${{ github.sha }}"

配置服务器密钥(Secrets):
在 GitHub 仓库的Settings → Secrets里添加:

  • SERVER_HOST:服务器IP
  • SERVER_SSH_KEY:服务器的SSH私钥(登录服务器,执行ssh-keygen生成)

5.3 完整的部署流程

程序员 push 代码 ↓ GitHub 检测到 push 事件 ↓ 自动启动一个虚拟机(ubuntu-latest) ↓ 检出代码 → 安装 JDK → Maven 构建 → 打包 jar ↓ 构建 Docker 镜像 ↓ SSH 登录服务器 ↓ 执行 docker-compose pull && up -d ↓ 自动重启容器,新版本上线 ↓ 企业微信机器人发送通知

六、本课作业

  1. 在本地安装 Docker Desktop(或在Linux服务器上装Docker)
  2. 把扫码点餐后端项目打成 Docker 镜像并运行
  3. 用 docker-compose 同时启动 MySQL + Redis + Java应用
  4. (选做)在 GitHub 上创建仓库,配置 GitHub Actions 自动化部署

七、下一课预告

下一课我们将学习Java 性能优化与调优,从 JVM 调优、SQL 优化、接口性能优化三个维度,让你的系统跑得更快、更稳。