CI/CD:CodePipeline vs GitHub Actions

你的 code push 了,然後手動 SSH 進去拉 code、重啟服務?都 2026 年了,該自動化了。

先講結論

AWS 的 CI/CD 全家桶是 CodePipeline + CodeBuild + CodeDeploy,跟 AWS 服務整合最深但學習曲線陡。GitHub Actions 更靈活、社群生態更好、大多數場景也更便宜。如果你的 code 在 GitHub 上,用 GitHub Actions + 部署到 AWS 是 2026 年的最佳選擇。


方案一:GitHub Actions(推薦)

基本流程

git push → GitHub Actions → 
  build Docker image → 
  push to ECR → 
  update ECS service

ECR:你的 Docker image 倉庫

# 建立 ECR Repository
aws ecr create-repository --repository-name web-app \
  --image-scanning-configuration scanOnPush=true \
  --encryption-configuration encryptionType=AES256
 
# 設定 Lifecycle Policy(保留最近 20 個 image)
aws ecr put-lifecycle-policy --repository-name web-app \
  --lifecycle-policy-text '{
    "rules": [{
      "rulePriority": 1,
      "description": "Keep last 20 images",
      "selection": {
        "tagStatus": "any",
        "countType": "imageCountMoreThan",
        "countNumber": 20
      },
      "action": {"type": "expire"}
    }]
  }'
 
# 登入 ECR
aws ecr get-login-password --region ap-northeast-1 | \
  docker login --username AWS --password-stdin 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com

GitHub Actions Workflow

# .github/workflows/deploy.yml
name: Deploy to ECS
 
on:
  push:
    branches: [main]
 
env:
  AWS_REGION: ap-northeast-1
  ECR_REPOSITORY: web-app
  ECS_CLUSTER: prod-cluster
  ECS_SERVICE: web-app
 
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - run: npm ci
      - run: npm test
 
  deploy:
    needs: test
    runs-on: ubuntu-latest
    permissions:
      id-token: write   # OIDC
      contents: read
    steps:
      - uses: actions/checkout@v4
 
      # 用 OIDC 連 AWS(不需要 Access Key)
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy
          aws-region: ${{ env.AWS_REGION }}
 
      # 登入 ECR
      - uses: aws-actions/amazon-ecr-login@v2
        id: ecr-login
 
      # Build + Push
      - name: Build and push image
        env:
          ECR_REGISTRY: ${{ steps.ecr-login.outputs.registry }}
          IMAGE_TAG: ${{ github.sha }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:latest .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
 
      # 更新 ECS Service
      - name: Deploy to ECS
        run: |
          aws ecs update-service \
            --cluster $ECS_CLUSTER \
            --service $ECS_SERVICE \
            --force-new-deployment

GitHub Actions + OIDC:不要用 Access Key

# 在 AWS 建立 OIDC Provider(給 GitHub)
aws iam create-open-id-connect-provider \
  --url https://token.actions.githubusercontent.com \
  --client-id-list sts.amazonaws.com \
  --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1
 
# 建立 IAM Role(給 GitHub Actions 用)
cat > trust-policy.json << 'EOF'
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
    },
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Condition": {
      "StringEquals": {
        "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
      },
      "StringLike": {
        "token.actions.githubusercontent.com:sub": "repo:your-org/your-repo:ref:refs/heads/main"
      }
    }
  }]
}
EOF
 
aws iam create-role --role-name github-actions-deploy \
  --assume-role-policy-document file://trust-policy.json

用 OIDC 取代 Access Key 是安全最佳實踐。Access Key 放在 GitHub Secrets 裡仍然有洩漏風險,OIDC 完全不需要存 credential。


方案二:AWS CodePipeline

什麼時候選 CodePipeline

  • Code 在 CodeCommit(AWS 的 git,注意:CodeCommit 自 2024 年 7 月起已停止接受新客戶,建議使用 GitHub 或 GitLab)上
  • 需要跟 AWS 服務深度整合(CodeDeploy blue/green)
  • 企業合規要求全在 AWS 內完成
  • 不想依賴第三方 CI 服務

CodePipeline + CodeBuild + CodeDeploy

# 1. 建立 CodeBuild Project
aws codebuild create-project --name web-app-build \
  --source type=GITHUB,location=https://github.com/your-org/web-app \
  --artifacts type=NO_ARTIFACTS \
  --environment type=LINUX_CONTAINER,computeType=BUILD_GENERAL1_SMALL,image=aws/codebuild/amazonlinux2-x86_64-standard:5.0,privilegedMode=true \
  --service-role arn:aws:iam::123456789012:role/codebuild-role
 
# buildspec.yml
# buildspec.yml
version: 0.2
 
phases:
  pre_build:
    commands:
      - echo Logging in to ECR...
      - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
      - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - IMAGE_TAG=${COMMIT_HASH:=latest}
  build:
    commands:
      - echo Building Docker image...
      - docker build -t $REPOSITORY_URI:$IMAGE_TAG .
      - docker tag $REPOSITORY_URI:$IMAGE_TAG $REPOSITORY_URI:latest
  post_build:
    commands:
      - echo Pushing image...
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - docker push $REPOSITORY_URI:latest
      - printf '[{"name":"app","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
  files: imagedefinitions.json

多環境部署

分支策略

main → production
staging → staging
feature/* → 不部署(只跑 test)

GitHub Actions 多環境

# deploy-staging.yml
on:
  push:
    branches: [staging]
 
jobs:
  deploy:
    environment: staging  # GitHub Environment(有 approval 機制)
    # ... 同上,但 ECS_CLUSTER/ECS_SERVICE 用 staging 的值
 
# deploy-production.yml
on:
  push:
    branches: [main]
 
jobs:
  deploy:
    environment: production  # 需要手動 approve
    # ...

Rollback

# 快速 rollback:把 ECS service 的 Task Definition 指回上一版
aws ecs update-service --cluster prod-cluster \
  --service web-app \
  --task-definition web-app:42  # 上一個版本號
 
# 或者直接 revert git commit 讓 CI/CD 重跑
git revert HEAD && git push origin main

GitHub Actions vs CodePipeline

GitHub ActionsCodePipeline
學習曲線低(YAML 清楚)高(三個服務要串)
免費額度2000 分鐘/月(public repo 無限)每個 pipeline $1/月
社群 Action超多幾乎沒有
AWS 整合OIDC + CLI原生
自建 Runner支援CodeBuild(AWS 管)
ApprovalGitHub EnvironmentManual Approval stage
缺點依賴 GitHub三個服務要串、Debug 痛苦

自架 vs AWS

面向自架(GitLab CI)GitHub ActionsCodePipeline
Runner自己管 GitLab RunnerGitHub 管 / Self-hostedCodeBuild(AWS 管)
RegistryHarborECRECR
部署SSH + docker-composeECS update / kubectlCodeDeploy
費用Runner 機器費免費/按分鐘按 pipeline + build 分鐘

如果你讀過 CDCD 模板,GitHub Actions 的概念一模一樣——只是語法和生態不同。


K8s 映射

AWS CI/CDK8s 對應
CodePipelineTekton Pipelines
CodeBuildKaniko(in-cluster build)
CodeDeploy (blue/green)Argo Rollouts
GitHub Actions → ECSGitHub Actions → kubectl / ArgoCD
ECRHarbor / DockerHub

如果你用 EKS,最佳搭配是 GitHub Actions build image → push to ECR → ArgoCD 偵測到新 image → 自動部署。詳見 K8s GitOps


系列導覽

上一篇下一篇
EventBridge FinOps

好的 CI/CD 讓你有信心在週五下午部署——壞的 CI/CD 讓你週五下午不敢碰任何東西。