Givepo
博客

云计算与 DevOps:Docker、CI/CD 与可靠部署实用指南

从可用于生产的 Dockerfile,到自动化流水线和零停机发布:让小团队每天多次发布而不出故障的 DevOps 实践。

Givepo 团队
阅读约 6 分钟
Illustration of a cloud above a CI/CD pipeline with build, test and scan steps passed and deploy in progress, next to a stack of containers云计算与 DevOps

编写代码只是交付软件的一半。另一半是构建、测试、发布到服务器并保持其稳定运行,理想情况下每周多次发布,而且不用深夜救火。DevOps 就是让这一切成为常规操作的一套实践,而容器、CI/CD 流水线和云基础设施则是让它落地的工具。

DevOps 的真正含义

DevOps 不是一个职位,也不是一种工具。它的理念是:构建软件的人和运维软件的人共同对两者负责,并以高度自动化作为支撑。DORA 研究项目用四个指标概括交付表现:

  • 部署频率:你多久向生产环境发布一次。
  • 变更前置时间:一次提交需要多久才能进入生产环境。
  • 变更失败率:发布引发需要修复的故障的比例。
  • 服务恢复时间:当一次发布失败时,你能多快恢复。

高绩效团队能同时在这四项上表现出色。事实证明,频繁发布小的变更,比偶尔发布大批量变更更快,也更安全。

使用 Docker 实现容器化

容器镜像把应用连同其确切的运行时、系统库和默认配置一起打包。容器则是该镜像的一个运行实例。由于镜像在笔记本、CI 和生产环境中完全一致,“在我电脑上能跑”的问题就不复存在。

多阶段构建能让生产镜像保持小巧和安全:依赖安装和应用编译都在临时阶段完成,只有产物被复制到精简的运行时镜像中。下面是一个使用 output: 'standalone' 构建的 Next.js 应用示例:

Dockerfile
# syntax=docker/dockerfile:1
FROM node:24-alpine AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile

FROM node:24-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN corepack enable && pnpm build

FROM node:24-alpine AS runtime
WORKDIR /app
ENV NODE_ENV=production
# Never run the application as root
RUN addgroup -S app && adduser -S app -G app
COPY --from=build --chown=app:app /app/.next/standalone ./
COPY --from=build --chown=app:app /app/.next/static ./.next/static
COPY --from=build --chown=app:app /app/public ./public
USER app
EXPOSE 3000
CMD ["node", "server.js"]

值得从第一天起就采用的容器最佳实践:

  • 添加 .dockerignore,让 node_modules、.git 和本地密钥永远不会进入构建上下文。
  • 把基础镜像固定到具体版本,并定期重新构建以获取安全补丁。
  • 每个容器只运行一个进程,并把日志输出到标准输出,由平台统一收集。
  • 通过环境变量传入配置,密钥完全不放进镜像。
  • 把数据存放在卷或托管服务中,绝不放在随时可能被替换的容器内部。

对于本地开发和小规模部署,Docker Compose 可以在一个文件中描述多个容器及其连接方式:

YAML
services:
  app:
    build: .
    ports:
      - '3000:3000'
    environment:
      DATABASE_URL: postgres://app:${POSTGRES_PASSWORD}@db:5432/app
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:17
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: app
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U app']
      interval: 5s
      retries: 10

volumes:
  db-data:

CI/CD 流水线

持续集成(CI)是指每次推送都会自动构建和测试,让问题在几分钟内暴露,而不是在发布前几天才发现。持续交付(CD)更进一步:每个通过流水线的变更都会被打包好、随时可以部署;而在持续部署中,它会被自动发布到生产环境。

一个扎实的 GitHub Actions 基础流水线,会在每个 pull request 和每次推送到 main 时安装依赖、类型检查、运行测试并构建:

YAML
name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: pnpm/action-setup@v4
        with:
          version: 10
      - uses: actions/setup-node@v5
        with:
          node-version: 24
          cache: pnpm
      - run: pnpm install --frozen-lockfile
      - run: pnpm typecheck
      - run: pnpm test
      - run: pnpm build

在此基础上,为团队反复踩坑的地方添加阶段:依赖和容器镜像的漏洞扫描、在预览环境中运行的端到端测试,以及只在 main 分支全部通过后才运行的部署任务。让流水线保持快速:十分钟的流水线会被认真执行,四十分钟的流水线会被想办法绕过。

部署策略

如何发布和发布什么同样重要。目标是零停机,并且出问题时有一条快速、平淡无奇的回退之路:

  • 滚动更新:每次替换少量实例。简单,也是大多数平台的默认方式,但新旧版本会并行运行一段时间。
  • 蓝绿部署:在旧版本旁边运行新版本,测试通过后一次性切换全部流量。回滚就是切回去。
  • 金丝雀发布:先把一小部分流量(比如 5%)导向新版本,观察错误率和延迟,再逐步扩大。
  • 功能开关:以关闭状态部署代码,之后再为选定用户开启。这把部署和发布分离开来。

数据库变更同样需要谨慎。使用扩展-收缩(expand and contract)模式:先以向后兼容的方式新增列或表,部署使用它们的代码,等到之后的版本再删除旧结构。这样在发布和回滚过程中,旧版本的应用依然可以正常工作。

云基础设施,简单来说

云服务商提供了一系列选择:从裸虚拟机(IaaS),到托管平台和容器服务(PaaS),再到只需提供代码的无服务器函数。越往后,你需要自己管理的越少,能掌控的也越少。对大多数团队来说,最佳平衡点是:难的部分交给托管服务(数据库、队列、对象存储、负载均衡器),应用本身使用容器。

使用 Terraform、OpenTofu 或 Pulumi 等工具,以代码的形式定义这些基础设施。这样服务器、网络和 DNS 都纳入版本控制,像代码一样被评审,并能在几分钟内重建,包括一个真正与生产环境一致的预发布环境。

服务器管理与安全要点

  • 最小权限:每个人、每个服务、每个 CI 任务只获得所需的权限。
  • 密钥应存放在密钥管理服务或平台的加密配置中,绝不放进代码仓库或镜像。
  • 定期打补丁,覆盖操作系统、基础镜像和依赖,并尽可能自动化。
  • 私有网络:数据库不暴露在公网上,只对外开放负载均衡器。
  • 全站 HTTPS,证书自动续期。
  • 备份只有恢复过才算数:自动化备份、加密、异地存储,并定期演练恢复。
  • 监控与告警覆盖可用性、错误率和延迟,配备值班轮换和常见事故的书面处理手册。

要点回顾

  • 容器让构建可复现。使用多阶段构建、精简的基础镜像和非 root 用户。
  • 把通往生产环境的路径自动化:每个变更都以相同方式构建、测试和扫描。
  • 频繁发布小的变更,并借助蓝绿部署、金丝雀发布或功能开关降低发布风险。
  • 用代码管理基础设施,有状态的部分使用托管服务,并演练从备份中恢复。

总结

DevOps 带来的不只是速度,更是从容。当构建可复现、流水线能及早发现问题、每次发布都能在一分钟内回滚时,部署就不再是一件大事,而是日常工作。先从一个 Dockerfile 和一条运行测试的 CI 流水线开始,再一次自动化一个手动步骤。

延伸阅读

  • #CI/CD
  • #Cloud
  • #DevOps
  • #Docker
作者
Givepo 团队

Givepo 是一家 IT 公司,专注于开发网站、移动应用和定制软件,助力您的业务持续发展。

分享本文

免费 30 分钟咨询

与我们的团队沟通您的想法、需求范围和预算。

预约咨询

更多文章

博客
人工智能与机器学习
·阅读约 7 分钟

人工智能与机器学习实战:它们在哪里创造真正的商业价值

拨开炒作的迷雾。了解机器学习和生成式 AI 的真实工作原理、它们当下在哪些场景创造可衡量的价值,以及如何让第一个 AI 项目真正上线,而不是止步于演示。

查看详情
网站开发
·阅读约 6 分钟

使用 Next.js、React 和 TypeScript 进行现代 Web 开发:最佳实践

Server Components、渲染策略、类型安全的数据与 Core Web Vitals。一份实用指南,教你用当今大多数团队选择的技术栈构建快速、易维护的 Web 应用。

查看详情
后端与 API
·阅读约 7 分钟

后端架构详解:REST API、微服务与可扩展数据库

如何设计开发者乐于使用的 REST API,微服务何时值得付出代价,如何设计能承受高负载的数据库,以及让后端系统保持快速和可靠的模式。

查看详情