Docker 运维入门实战:改了代码不用手动部署——用 GitHub Actions 做一次最简单的 CI/CD

举报
yd_274623194 发表于 2026/11/01 14:20:38 2026/11/01
【摘要】 关键词:CI/CD、GitHub Actions、自动部署、SSH、镜像标签、回滚上一篇我们把 Docker 运维这条线收了尾:服务能对外提供、出了问题能定位、改了代码能安全更新、单个服务失控也不会拖垮整台机器。但还有一个手动的尾巴没去掉:每次改代码,都要自己登录服务器、构建、重启、等健康、再验证。改得越勤,这个流程就越烦,也越容易在某一步手滑。今天把这一步也自动化:改了代码、推上去,服务器...

关键词:CI/CD、GitHub Actions、自动部署、SSH、镜像标签、回滚

上一篇我们把 Docker 运维这条线收了尾:服务能对外提供、出了问题能定位、改了代码能安全更新、单个服务失控也不会拖垮整台机器。但还有一个手动的尾巴没去掉:每次改代码,都要自己登录服务器、构建、重启、等健康、再验证。改得越勤,这个流程就越烦,也越容易在某一步手滑。今天把这一步也自动化:改了代码、推上去,服务器自己更新——也就是最简单的 CI/CD。

先说清范围:本文只做一条最简单的流水线,不碰多环境、不碰灰度、不碰 Kubernetes。目标是“推代码就自动部署,且每一步都能验证、能回滚”。本文还是接着前面的结构讲:gateway(Nginx 网关)、web(静态网页)、api(8000 端口的 Python 接口服务),三者都在一台服务器上跑,代码放在 GitHub 仓库里。

一、CI 和 CD 各自在做什么:别被缩写吓到

CI(持续集成)和 CD(持续部署)听起来很大,落到这条线其实就是两件事:

  • CI:代码推上去之后,自动做一次“构建能不能过”。对 my-app 来说,就是 docker compose build api 能不能成功,镜像能不能打出来。
  • CD:构建通过之后,自动把新镜像部署到服务器上,跑前面讲过的那套更新流程:只动改了的服务、等健康、从网关侧验证。

区分这两步的意义在于:构建失败时,流水线应该停在 CI,不碰服务器——坏代码连上服务器的机会都没有。只有构建通过了,才轮到部署。

二、流水线长什么样:一次推送触发的三步

GitHub Actions 的流水线写在一个 YAML 文件里,放在仓库的 .github/workflows/deploy.yml。一次最简单的版本只有三步:

name: deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: 构建镜像
        run: docker compose build api
      - name: 部署到服务器
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SERVER_SSH_KEY }}
          script: |
            cd /opt/my-app
            git pull
            docker compose up -d --no-deps api
            docker compose ps api

读这段配置时抓住三个点就够了:第一,on.push.branches: [main] 表示只有推到 main 分支才触发,平时在别的分支上折腾不会误部署;第二,构建和部署是分开的两步,构建失败就不会走到部署;第三,部署那一步沿用的是前面讲过的更新办法——up -d --no-deps api 只动 api,gateway 和 web 不动。

三、密钥怎么放:千万别写进代码里

上面配置里 ${{ secrets.SERVER_HOST }} 这种写法不是占位符,是 GitHub Actions 的 Secrets:先在仓库的 Settings → Secrets and variables → Actions 里填好服务器地址、用户名和 SSH 私钥,流水线运行时再取出来用。日志里会自动把它们打码,不会明文出现在构建记录里。

这一条是 CI/CD 里最容易出事、也最不能省的规矩:服务器地址、账号、密钥、密码,永远不要直接写进仓库文件里。写进了 Git 历史,就算后来删掉,历史记录里也还留着,等于公开了。判断标准很简单:仓库公开之后,你会不会心慌——会,就说明有东西不该在里面。

四、部署完怎么验收:流水线里也要等健康

前面讲过,更新的验收标准是三条:健康状态 (healthy)、服务日志无报错、从网关侧真实请求一次。这三条在流水线里同样不能省,只是从“人手动敲”变成“流水线自动跑”:

# 部署脚本里,重启之后加上这两步再结束
docker compose ps api          # STATUS 一列应出现 (healthy)
curl http://localhost/api/health

如果健康检查一直没变 (healthy),或者网关侧请求失败,流水线应该直接报错停下,而不是悄悄算成功——自动部署的意义是“不用人守着”,不是“出问题也不告诉人”。GitHub Actions 里这一步失败,仓库的 Actions 页面会直接标红,推代码的人一眼就能看到。

五、出问题了怎么回滚:自动部署也要留后路

自动部署最怕的不是部署失败,而是“部署成功了,但新版本有问题”。这时回滚的办法和前面讲过的一样,只是触发方式从手动变成“再推一次”:

  • 如果是代码问题:把代码回退到上一个能用的提交,再推到 main,流水线会重新部署旧版本。
  • 如果是镜像问题:服务器上旧版本的镜像还在(前面讲过,别只用 latest,要打版本标签),直接在服务器上把镜像标签改回上一版,再 docker compose up -d --no-deps api,同样等健康、同样从网关侧验证。

回滚的前提还是那句话:旧镜像还在、旧代码能找到。自动部署没有改变这个前提,只是让“重新部署一次”的成本从手动登录服务器变成一次推送。

六、三个新手最容易踩的坑

1. 任何分支一推就部署
流水线只应该由 main 分支触发。开发分支、实验分支一推就上服务器,等于把没验证过的代码直接推给了用户。分支策略就是部署策略的一部分。

2. 构建和部署混成一步
构建失败时还继续往服务器上推,等于把坏代码的部署也自动化了。先构建、构建通过再部署,这个顺序别省。

3. 部署完只看流水线变绿
流水线变绿只说明“命令跑完了”,不说明“服务真的能用”。健康状态、日志、网关侧请求这三条验收,流水线里也要跑,缺一都不能算部署完成。

结语

从单容器、Compose 编排、数据卷、反向代理和 HTTPS、日志与健康检查、滚动更新、资源限制和重启策略,到今天的 CI/CD,这条 Docker 运维的线已经从“手动把服务跑起来”走到了“改了代码、推上去,服务器自己更新、自己验收”。下一篇可以往“服务器不止一台”走一步:多个服务、多个副本时,怎么让它们互相发现、怎么分摊流量——也就是从单机 Compose 往集群的方向看一眼。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。