🙆‍♀️

【初心者向け】Docker + AWS ECS + GitHub ActionsでGo APIの自動デプロイ環境を構築してみた

に公開

はじめに

普段業務でDockerファイルやコンテナを使用していましたが、構築したことがありませんでした。
今後必要な知識やスキルだと感じたため、簡単に実際の構築手順を共有します。

前提条件

  • Dockerをインストール済み
  • AWSアカウント作成済み
  • IAMユーザーに以下の権限を付与済み
    • AmazonEC2ContainerRegistryPowerUser(ECR操作)
    • AmazonECS_FullAccess(ECS操作)
  • IAMユーザーのアクセスキーを作成済み
  • GitHubのアカウント作成済み

Dockerファイルの作成とAPIの構築

このセクションで達成できること: ローカル環境でDocker化されたGoアプリを動作確認できます。

1. プロジェクトフォルダの作成

まずは、自分のPC上に今回の作業専用のフォルダを作ります。

  • フォルダ作成:デスクトップなどに go-docker-project というフォルダを作ります
  • エディタで開く:VS Codeなどのエディタでそのフォルダを開きます

2. 3つのファイルを用意する

そのフォルダの中に、以下の3つのファイルを新規作成して、中身をコピー&ペーストしてください。

① main.go(プログラム本体)

package main

import (
	"fmt"
	"net/http"
)

func main() {
	// "/"にアクセスした時の処理
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Success! Go API is running.")
	})

	fmt.Println("Server is running on port 8080...")
	// 8080ポートでサーバーを起動
	http.ListenAndServe(":8080", nil)
}

② go.mod(Goの設定ファイル)

ターミナルで go mod init をしても良いですが、今は以下の内容でファイルを作成するだけでOKです。

module my-go-api
go 1.25.5

③ Dockerfile(コンテナの設計図)

※ファイル名に拡張子は不要です。Dockerfile という名前にしてください。

# 1. Goの公式イメージをベースにする
FROM golang:1.25.5-alpine AS builder

# 2. コンテナ内の作業場所を決める
WORKDIR /app

# 3. PC上のファイルをすべてコンテナにコピー
COPY . .

# 4. Goのプログラムをコンテナ内でビルド
RUN go build -o main .

# 5. コンテナが使うポート(8080)を公開
EXPOSE 8080

# 6. コンテナ起動時にプログラムを実行
CMD ["./main"]

3. Dockerイメージを作成・起動する

ターミナル(PowerShell等)を開き、作成したフォルダに移動(cd)してから以下のコマンドを打ちます。

イメージのビルド(作成)

設計図(Dockerfile)を元に、コンテナの「型」を作ります。

docker build -t my-go-app .

※ 最後に半角スペースと末尾のピリオドを忘れないようにしてください。

コンテナの起動

作った「型」を実際に動かします。

docker run -d -p 8080:8080 --name go-container my-go-app

各フラグの意味:

  • -d: バックグラウンドで実行します
  • -p 8080:8080: PCの8080番ポートをコンテナに繋ぎます
  • --name: コンテナに名前を付けます

4. 動作確認

ブラウザを開き、以下のURLにアクセスしてください。

http://localhost:8080

画面に Success! Go API is running. と表示されたら、PC上でコンテナ化されたGoアプリが完璧に動いています!

ローカルで動けば、コンテナの基礎はクリアです。次はコンテナをAWSへ持ち出すために Amazon ECR(Elastic Container Registry) へプッシュ(アップロード)します。

ECRの構築

このセクションで達成できること: コンテナイメージをAWS ECRに保存できます。

1. AWS ECR に「箱」を作る

まずはAWSの管理画面上で、イメージを保管するためのリポジトリを作成します。AWSコンソールにログインし、検索窓に「ECR」と入力してサービスを開きます。左メニューの「プライベートリポジトリ」を選択し、「リポジトリを作成」をクリック。

リポジトリ名:my-go-app と入力。

他はすべてデフォルトのまま、画面下の「リポジトリを作成」をクリック。

2. AWS CLI の初期設定(認証)

自分のPCからAWSを操作するための「鍵」をセットします。

※ まだインストールしていない場合は公式ページからダウンロードしてください。

① AWS CLI を実行

aws configure

② 認証情報を入力

以下の4項目を聞かれるので入力します(IAMユーザー作成時に発行されたものを入力してください)。

AWS Access Key ID: (あなたのアクセスキー)
AWS Secret Access Key: (あなたのシークレットキー)
Default region name: ap-northeast-1(東京リージョンの場合)
Default output format: json

③ 設定確認

ちゃんと設定されたかターミナルで以下を入力します。

aws configure list

3. ECRへプッシュする

ECRリポジトリの画面右上にある「プッシュコマンドの表示」ボタンを押すと、あなた専用のコマンドが表示されます。それを順番に実行します。

① ECRにログインする

AWSから「プッシュしていいよ」という許可をもらうコマンドです。

aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [あなたの12桁のAWSアカウントID].dkr.ecr.ap-northeast-1.amazonaws.com

成功すると Login Succeeded と表示されます。

② ローカルイメージに「AWS用のタグ」を付ける

Dockerに「このイメージは、将来このAWSリポジトリに行くものだよ」と教えます。

docker tag my-go-app:latest [あなたの12桁のAWSアカウントID].dkr.ecr.ap-northeast-1.amazonaws.com/my-go-app:latest

③ プッシュを実行する

実際にインターネット経由でAWSにアップロードします。

docker push [あなたの12桁のAWSアカウントID].dkr.ecr.ap-northeast-1.amazonaws.com/my-go-app:latest

4. 確認

AWSコンソールのECR画面に戻り、作成したリポジトリ「my-go-app」をクリックしてください。「イメージ」一覧に、いまプッシュした latest というタグのデータが表示されていれば成功です!


これで「コンテナの材料」がAWS上に準備できました。

次はECS(Fargate)を構築して、インターネットからGoのAPIにアクセスできるようにします。設定項目が多いので、1つずつ丁寧に進めましょう!

ECSの構築

このセクションで達成できること: AWS FargateでGoアプリのコンテナをクラウドで稼働できます。

1. ECS クラスターを作成する

AWSコンソールの検索窓から「ECS」と入力してサービスを開きます。

左メニューの「クラスター」を選択し、「クラスターを作成」をクリック。

クラスター名: my-go-cluster

インフラストラクチャ: 「Fargateのみ」が選択されていることを確認。

他はデフォルトのまま、画面下の「作成」をクリック。

2. タスク定義を作成する

「どのコンテナを、どのくらいのスペックで動かすか」を定義します。左メニューの「タスク定義」を選択し、「新しいタスク定義の作成」をクリック。

基本情報

項目
タスク定義ファミリー my-go-task
起動タイプ AWS Fargate
OS/アーキテクチャ Linux/X86_64
CPU 0.25 vCPU
メモリ 0.5 GB

コンテナの定義

項目
名前 go-api-container
イメージURI 「ECRイメージを閲覧」からイメージを選択
ポートマッピング 8080 / tcp

画面下の「作成」をクリック。

3. サービスを作成する

実際にタスクを起動し、維持します。先ほど作成したクラスター「my-go-cluster」を開きます。

「サービス」タブの「作成」をクリック。

サービスの詳細

項目
ファミリー my-go-task(先ほど作ったもの)
サービス名 my-go-service

デプロイ設定

項目
必要なタスク数 1

ネットワーキング(重要!)

項目
VPC/サブネット デフォルトのまま
パブリックIP ON
セキュリティグループ 新規作成

セキュリティグループの「インバウンドルール」に以下を追加します。

プロトコル ポート範囲 ソース
カスタムTCP 8080 XXX.XXX.XXX.XXX/0

※ 信頼できるIP(例:会社IPアドレス)に限定してください。

画面下の「作成」をクリック。

4. 動作確認

サービスのステータスが「Active(デプロイ完了)」になるまで1〜2分待ちます。

クラスターの「タスク」タブを開き、表示されているタスク(英数字の長いID)をクリックします。

右側の設定情報にある「パブリック IP」をコピーします。

ブラウザで以下にアクセスしてください。

http://[コピーしたパブリックIP]:8080

Success! Go API is running.と表示されれば、クラウドへのデプロイ完了です!

手動でデプロイできたことは大きな一歩です!次はGitHub Actionsを使って、コードをプッシュするだけで自動的にECSにデプロイされるようにパイプラインを構築します。

GitHubからAWSのコンテナへ自動デプロイする設定

このセクションで達成できること: コード更新で自動的にECSにデプロイされるCI/CD環境を構築できます。

GitHubのアカウントを作っただけでは「置き場」がない状態ですので、「リポジトリ(Repository)」を新しく作成する必要があります。これまでの作業(Goのコード、Dockerfile、自動デプロイ用のYAMLファイル)をそのリポジトリにアップロードすることで、GitHub Actionsが動き出します。

1. GitHubでリポジトリを作成する

GitHubにログインし、右上の「+」アイコンから [New repository] をクリック。

Repository name: my-go-app など好きな名前を入力。

Public/Private: コードを公開したくなければ「Private」(GitHub ActionsはPrivateでも無料で使えます)。

画面下の [Create repository] をクリック。

2. GitHub Secrets に AWS の認証情報を登録する

GitHubにAWSを操作する許可を与えるため、認証情報をリポジトリに保存します。

GitHubリポジトリの Settings > Secrets and variables > Actions を開きます。

New repository secret をクリックし、以下の2つを登録します。

名前
AWS_ACCESS_KEY_ID あなたのアクセスキー
AWS_SECRET_ACCESS_KEY あなたのシークレットキー

3. GitHub Actions の設定ファイルを作成する

プロジェクトのルートディレクトリに「.github/workflows/deploy.yml」というファイルを作成し、以下の内容を貼り付けてください。

フォルダ構成のイメージ

go-docker-project/
├── .github/
│   └── workflows/
│       └── deploy.yml  <-- これを追加
├── main.go
├── go.mod
└── Dockerfile

deploy.yml の内容

name: Deploy to Amazon ECS

# mainブランチにコードがpushされたときにこのワークフローを実行します
on:
  push:
    branches:
      - "main"

# 各設定値を環境変数として定義(後で変更しやすくするため)
env:
  AWS_REGION: ap-northeast-1        # デプロイ先のリージョン(東京)
  ECR_REPOSITORY: my-go-app         # ECRのリポジトリ名
  ECS_SERVICE: my-go-service        # ECSのサービス名
  ECS_CLUSTER: my-go-cluster        # ECSのクラスター名
  ECS_TASK_DEFINITION: my-go-task   # タスク定義のファミリー名
  CONTAINER_NAME: go-api-container  # コンテナ名(タスク定義内の名前)

jobs:
  deploy:
    runs-on: ubuntu-latest # GitHub Actionsを実行するマシンのOS
    steps:
      # 1. GitHubリポジトリから最新のソースコードを取得します
      - name: Checkout
        uses: actions/checkout@v4

      # 2. GitHub Secretsに保存した認証情報を使ってAWSへログインします
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ env.AWS_REGION }}

      # 3. Amazon ECRにログインしてイメージをプッシュできる状態にします
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      # 4. Dockerイメージをビルドし、ECRにプッシュします(タグにはコミットIDを使用)
      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          IMAGE_TAG: ${{ github.sha }} # コミットごとに一意のIDをタグにします
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

      # 5. 現在AWSに登録されているタスク定義(設定ファイル)をダウンロードします
      - name: Download task definition
        run: |
          aws ecs describe-task-definition --task-definition ${{ env.ECS_TASK_DEFINITION }} --query taskDefinition > task-definition.json

      # 6. 新しいタスクとして登録する際に邪魔になる不要な項目をJSONから削除します
      - name: Clean up task definition
        run: |
          jq 'del(.taskDefinitionArn, .revision, .status, .requiresAttributes, .compatibilities, .registeredAt, .registeredBy, .enableFaultInjection)' task-definition.json > temp.json && mv temp.json task-definition.json

      # 7. ダウンロードしたタスク定義の中の「イメージURI」を、今回作った新しいイメージに書き換えます
      - name: Fill in the new image ID in the Amazon ECS task definition
        id: task-def
        uses: aws-actions/amazon-ecs-render-task-definition@v1
        with:
          task-definition: task-definition.json
          container-name: ${{ env.CONTAINER_NAME }}
          image: ${{ steps.build-image.outputs.image }}

      # 8. 書き換えた新しいタスク定義をAWSに登録し、ECSサービスを更新(デプロイ)します
      - name: Deploy Amazon ECS task definition
        uses: aws-actions/amazon-ecs-deploy-task-definition@v1
        with:
          task-definition: ${{ steps.task-def.outputs.task-definition }}
          service: ${{ env.ECS_SERVICE }}
          cluster: ${{ env.ECS_CLUSTER }}
          wait-for-service-stability: true # 正常に起動するまで完了を待ちます

4. ローカルリポジトリを初期化して GitHub へプッシュする

ローカルで Git を初期化し、コードを GitHub にアップロードします。ターミナルで以下のコマンドを順番に実行してください。

 git init
 git add .
 git commit -m "Initial commit"
 git branch -M main
 git remote add origin https://github.com/[your-username]/my-go-app.git
 git push -u origin main

各コマンドの意味:

  • git init: 現在のフォルダを Git リポジトリとして初期化します
  • git add .: すべてのファイルをステージング(コミット準備)します
  • git commit: ファイルの変更をコミット(確定)します
  • git branch -M main: メインブランチの名前を「main」に設定します
  • git remote add origin: 後ろのURLをリモートリポジトリとして登録します
  • git push: ローカルの内容をGitHub にアップロードします

GitHub Actions が自動的に起動します!

GitHub のリポジトリの「Actions」タブを見ると、デプロイが進行している様子が表示されます。すべて完了したら、ECSのサービス画面で新しいタスクが起動しているはずです。

これで CI/CD パイプラインの構築は完了です!以降、コードを変更して git push するたびに、自動的に以下の処理が実行されます。

  1. Docker イメージをビルド
  2. Amazon ECR へプッシュ
  3. ECS サービスを更新

自動デプロイ環境の完成です。お疲れ様でした!

本番環境への進め方

このガイドで構築した環境は学習・テスト用途に最適ですが、本番運用に向けては以下の追加設定を検討してください。

ロードバランシング
AWS Application Load Balancer(ALB)を導入し、複数のタスクに負載を分散させることで、高可用性と耐障害性を実現できます。

ログ監視
CloudWatch Logs に ECS タスクのログを集約し、CloudWatch Alarms で異常を検知・通知する仕組みを構築します。

Auto Scaling
トラフィック変動に応じてタスク数を自動調整するスケーリングポリシーを設定し、コスト効率と性能を最適化します。

91works Tech Blog

Discussion