CIDC:CIDC 零基础实操指南:从代码提交到生产发布的全链路自动化

liuying
📝 摘要
本文面向希望自主搭建持续集成与持续部署(CIDC)流水线的开发者或运维人员,讲解从代码提交到服务器滚动更新的完整落地路径。文章以 GitHub 仓库配合 Docker 镜像及单台云服务器的典型场景为例,重点提炼三个核心价值:如何编写最小可用的 CI 脚本并确保测试前置执行;如何安全配置镜像仓库登录凭据并完成自动构建推送;以及如何避开权限、缓存、回滚这三类初学者常见陷阱。内容聚焦实操步骤,帮助读者快速掌握一套可复用的自动化部署体系。

读完本文,你将掌握 CIDC(持续集成与持续部署)的完整落地方法,能独立搭建一套从代码提交、自动测试、镜像构建到服务器滚动更新的流水线,并避开初学者最容易踩的权限、缓存、回滚三大坑。

---

CIDC:CIDC 零基础实操指南:从代码提交到生产发布的全链路自动化

第一步:明确你的交付物与目标环境

CIDC 不是安装一个软件,而是设计一条“代码 → 产物 → 部署”的管道。先回答三个问题:

1. 你的代码托管在哪?(GitHub / GitLab / Gitee)

2. 你的部署目标是什么?(单台服务器 / Kubernetes集群 / 云函数)

3. 你的产物是什么?(Docker镜像 / Jar包 / 静态文件)

以最常见场景为例:GitHub 仓库 + Docker 镜像 + 单台云服务器(Docker Compose 管理)。本教程按此场景操作,其他环境逻辑相同。

第二步:初始化仓库与 CI 脚本

在仓库根目录创建 `.github/workflows/ci.yml`(GitHub Actions 为例)。最小可用配置:

```yaml

name: CIDC Pipeline

on:

push:

branches: [ main ]

pull_request:

branches: [ main ]

jobs:

build-and-test:

runs-on: ubuntu-latest

steps:

- uses: actions/checkout@v4

- name: Set up JDK 17

uses: actions/setup-java@v4

with:

java-version: '17'

- name: Run tests

run: mvn test

- name: Build jar

run: mvn package -DskipTests

```

这段代码会在每次 push 到 main 分支时自动拉取代码、跑测试、打 jar 包。注意:测试必须在这里做,不要等到部署后才验证。

第三步:构建 Docker 镜像并推送镜像仓库

在 CI 脚本末尾追加构建与推送步骤。你需要一个镜像仓库(Docker Hub / 阿里云 ACR / 腾讯云 TCR)。以 Docker Hub 为例:

```yaml

- name: Login to Docker Hub

uses: docker/login-action@v3

with:

username: ${{ secrets.DOCKER_USERNAME }}

password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build and push

uses: docker/build-push-action@v5

with:

context: .

push: true

tags: yourname/myapp:latest

```

关键点:

- 在 GitHub 仓库 Settings → Secrets 里添加 `DOCKER_USERNAME` 和 `DOCKER_PASSWORD`,绝不要明文写密码。

- 镜像 tag 不要只用 `latest`,建议用 `${{ github.sha }}`(提交哈希),便于回滚。

第四步:编写部署端脚本(服务器侧)

在目标服务器上准备部署脚本 `deploy.sh`:

```bash

#!/bin/bash

set -e

docker pull yourname/myapp:latest

docker compose down

docker compose up -d

```

但这样不够健壮。推荐加健康检查:

```bash

docker pull yourname/myapp:latest

docker compose up -d --no-deps --force-recreate app

sleep 10

curl -f http://localhost:8080/health || { docker compose logs app; exit 1; }

```

第五步:在 CI 中触发远程部署

两种方式:

- 方式A(简单):在 CI 最后一步用 SSH 登录服务器执行 `deploy.sh`。需要把服务器的 SSH 私钥放入 GitHub Secrets,然后:

```yaml

- name: Deploy

uses: appleboy/ssh-action@v1

with:

host: ${{ secrets.HOST }}

username: root

key: ${{ secrets.SSH_KEY }}

script: |

cd /opt/app

bash deploy.sh

```

- 方式B(更安全):用 webhook 工具(如 webhook 或 Jenkins 的远程触发),服务器上监听 HTTP 请求后才拉取镜像。初学者先走方式A,但要注意 SSH 密钥泄露风险。

第六步:加入回滚机制

这是 CIDC 的灵魂。在服务器上保留上一次可用的镜像 tag:

```bash

# deploy.sh 改进版

LAST_GOOD_TAG=$(docker images --filter "reference=yourname/myapp" --format "{{.Tag}}" | sort -V | tail -2 | head -1)

docker pull yourname/myapp:$NEW_TAG

docker compose up -d --no-deps --force-recreate app

sleep 10

curl -f http://localhost:8080/health || {

docker compose down

docker compose up -d --no-deps --force-recreate app:$LAST_GOOD_TAG

exit 1

}

```

第七步:验证全链路

模拟一次真实发布:

1. 本地修改代码 → push 到 main

2. 打开 GitHub Actions 页面,观察 job 是否依次通过

3. 登录服务器,执行 `docker ps` 查看容器是否重建

4. 访问应用健康检查接口,确认返回 200

若失败,优先查看 CI 日志中具体步骤的红叉,定位是编译失败、镜像推送失败还是 SSH 部署失败。

---

常见坑(务必先看)

1. 镜像 tag 混乱:永远用 `${{ github.sha }}` 作为 tag,不要覆盖 `latest`,否则回滚时无法知道上一个版本是哪个。

2. SSH 权限过大:不要用 root 账户的私钥直接放 CI。创建一个只允许执行 `deploy.sh` 的受限用户,并在服务器上设置 `sudo` 白名单。

3. 健康检查缺失:很多新手 `docker compose up -d` 后不管进程是否真正可用,导致“部署成功但服务挂了”。必须加 curl 健康检查。

4. 缓存污染:CI 中如果用了 `actions/cache` 缓存依赖,当依赖版本更新时可能一直用旧缓存。给缓存 key 加上哈希(如 `${{ hashFiles('**/pom.xml') }}`)。

5. 忽略环境差异:本地能跑不代表服务器能跑。在 CI 中用同一个基础镜像构建,不要依赖本地已安装的软件。

文章版权声明:除非注明,否则均为豪泰虾原创文章,转载或复制请以超链接形式并注明出处。

目录[+]