Skip to content
CI/CD 与发布治理 · 第 4 篇 / 共 8 篇
领域运维与部署
专题CI/CD 与发布治理专题
当前序列CI/CD 与发布治理
阅读位置第 4 篇 / 共 8 篇当前专题第 1 个序列 / 共 4 个序列

GitLab CI/CD 实战:Docker 构建镜像并通过 SSH 部署到服务器

如果团队代码本来就在 GitLab 上,那很多时候最顺手的选择就是直接用 GitLab CI/CD。

先说结论

对典型 Java 服务来说,GitLab CI 很适合跑下面这条链路:

text
提交到指定分支 -> Maven 打包 -> Docker 构建镜像 -> 推送镜像仓库 -> SSH 到服务器更新服务

如果团队已经在用 GitLab 管代码,那这通常比额外搭一层工具更自然。

一、一个最常见的 .gitlab-ci.yml 结构

一般会按阶段拆开:

  • build
  • docker
  • deploy

这样流水线更容易读,也更方便看失败点。

二、一个简化示例

yaml
stages:
  - build
  - docker
  - deploy

variables:
  IMAGE_NAME: registry.example.com/demo/user-service
  IMAGE_TAG: $CI_COMMIT_SHORT_SHA

build-job:
  stage: build
  image: maven:3.9.9-eclipse-temurin-21
  script:
    - mvn clean package -DskipTests
  artifacts:
    paths:
      - target/*.jar

docker-job:
  stage: docker
  image: docker:27
  services:
    - docker:27-dind
  script:
    - docker login -u "$REGISTRY_USER" -p "$REGISTRY_PASSWORD" registry.example.com
    - docker build -t $IMAGE_NAME:$IMAGE_TAG .
    - docker push $IMAGE_NAME:$IMAGE_TAG

deploy-job:
  stage: deploy
  image: alpine:3.20
  before_script:
    - apk add --no-cache openssh-client
    - mkdir -p ~/.ssh
    - echo "$DEPLOY_PRIVATE_KEY" > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts
  script:
    - |
      ssh $DEPLOY_USER@$DEPLOY_HOST "
        docker pull $IMAGE_NAME:$IMAGE_TAG &&
        export IMAGE_TAG=$IMAGE_TAG &&
        cd /mydata/apps/user-service &&
        docker compose up -d
      "
  only:
    - main

三、为什么 GitLab CI 很适合团队项目

1. 和分支策略结合得更自然

你可以很容易做到:

  • feature 分支只构建不部署
  • develop 自动发测试环境
  • main 走生产发布

2. 和 Merge Request 配合方便

很多团队会把“流水线必须通过”作为合并条件之一。

3. 权限和变量管理更集中

像这些变量可以统一放在 GitLab CI Variables:

  • 镜像仓库账号
  • SSH 私钥
  • 服务器地址

四、Docker in Docker 不是唯一选择

很多文章一提 GitLab CI + Docker 就直接上 dind,但它不是唯一方案。

你还可以考虑:

  • Shell Runner 直接使用宿主机 Docker
  • Kaniko 构建镜像
  • BuildKit 或 buildx

五、部署到服务器时更推荐什么方式

如果你的线上环境本来就是 Docker 或 Compose 管理,那最顺的一条路通常是:

  • 流水线只负责推镜像
  • 远程服务器只负责拉镜像和重启服务

六、常见坑

1. 把所有逻辑都塞进 YAML

一开始图快,把大量 shell 直接写进 .gitlab-ci.yml 很常见。

2. 构建和部署用的是不同版本标识

如果镜像 tag 不统一,最后会搞不清线上到底跑的是哪个版本。

3. 生产和测试共用同一套变量

这会把环境隔离搞乱。

4. 只做部署,不做发布后校验

部署命令返回成功,不代表业务真的正常。

一句话总结

GitLab CI/CD 最大的优势,不只是“能跑流水线”,而是让代码仓库、分支策略、构建制品和部署动作形成一套更统一的工程闭环。

延伸阅读相关文章优先当前专题,再补跨专题关联。
同一序列 · 顺着当前主线继续读灰度、蓝绿、滚动发布到底怎么选:以及上线失败后怎么回滚适合沿着流水线设计、自动部署、发布策略、数据库变更和多环境治理这条线往下读。CI/CD 与发布治理专题 · CI/CD 与发布治理同一序列 · 顺着当前主线继续读数据库变更怎么配合 CI/CD:表结构发布、兼容性和回滚思路适合沿着流水线设计、自动部署、发布策略、数据库变更和多环境治理这条线往下读。CI/CD 与发布治理专题 · CI/CD 与发布治理同专题其他序列 · 共享标签:CI/CD、GitGitLab CI、GitHub Actions、Jenkins 怎么看待选型适合把缓存、制品库、灰度发布、数据库变更和回滚演练放在同一条 CI/CD 主线上看。CI/CD 与发布治理专题 · CI/CD 流水线稳定性与发布治理同专题其他序列 · 共享标签:CI/CD、部署交付灰度发布和 feature flag 应该怎么配合适合把缓存、制品库、灰度发布、数据库变更和回滚演练放在同一条 CI/CD 主线上看。CI/CD 与发布治理专题 · CI/CD 流水线稳定性与发布治理跨专题关联 · 共享标签:CI/CD、部署交付镜像分层为什么会影响构建速度和回滚适合把镜像分层、镜像瘦身、时区日志、静态缓存和 WebSocket 代理放进一条容器交付主线上看。容器与站点部署专题 · 容器镜像与站点交付细节跨专题关联 · 共享标签:Linux、部署交付chmod 和 chown 怎么用适合把磁盘、权限、链接、systemd、日志和服务器初始化这些基础能力集中起来看。Linux 与服务器治理专题 · Linux 基础与服务器治理
继续阅读CI/CD 与发布治理当前序列第 4 篇 / 共 8 篇当前专题第 1 个序列 / 共 4 个序列
往前看
上一篇Jenkins 发布 Java 服务实战回到当前序列上一章上一序列Docker 与 Nginx 部署从第 1 篇开始:Docker 常用命令速查
往后看
下一篇灰度、蓝绿、滚动发布到底怎么选:以及上线失败后怎么回滚继续当前序列下一章下一序列CI/CD 流水线核心模型从第 1 篇开始:流水线阶段和门禁到底该怎么拆

把零散经验整理成可查、可复用、可持续更新的企业级知识门户