はじめに
本記事では、S3 + CloudFront構成で静的サイト(例:React / Vue / HTML)をホスティングし、
GitHub Actionsによる自動デプロイ(CI/CD)を導入する方法を解説します。
対象読者:
-
AWS S3で静的サイトを公開している人
-
CloudFrontでキャッシュ配信している人
-
手動アップロードから卒業して自動化したい人
構成図
GitHub
↓ (push)
GitHub Actions
↓
AWS CLI
↓
S3 ← CloudFront(キャッシュ配信)
前提条件
-
AWSアカウントを保有
-
S3バケットを作成済(静的ウェブホスティング有効)
-
CloudFrontディストリビューションを設定済
-
GitHubリポジトリにソースコードを配置済
S3 + CloudFront + WAF でReactのデフォルトアプリケーションを公開する方法について詳しくは、下記の記事で解説しています。
https://qiita.com/cho-tehu/items/8dc94961f8d88ced890c
S3バケットの設定
-
バケットポリシーにCloudFrontからのアクセスのみ許可(OAC設定推奨)
-
パブリックアクセスはブロック
-
デプロイ対象:/build ディレクトリ(Reactの場合)
CloudFrontの設定
-
オリジン:S3バケット
-
キャッシュ無効化を自動化するため、CloudFrontの Distribution ID を控える
→ 後で aws cloudfront create-invalidation コマンドで使用します。
IAMユーザの作成
[ポリシーを直接アタッチする]を選択し、[ポリシーの作成]を選択

IAMポリシー例(最小権限):
arn:aws:s3:::my-static-site-bucket は自身のs3バケットのARNと置き換えてください。
S3 のプロパティから確認できます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:ListBucket",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::my-static-site-bucket",
"arn:aws:s3:::my-static-site-bucket/*"
]
},
{
"Effect": "Allow",
"Action": "cloudfront:CreateInvalidation",
"Resource": "*"
}
]
}
IAM ユーザー作成画面に戻り、更新ボタンを押したのち、作成したポリシー名で検索をし、選択
次へ

アクセスキーの作成
[コマンドラインインターフェイス (CLI)]を選択し、[次へ]を選択

ここで表示されるアクセスキー、シークレットアクセスキーをメモっておく。
csvでダウンロードすることもできる。

GitHub Secrets設定
GitHubリポジトリ → Settings → Secrets and variables → Actions
以下を登録:
| Name | Value |
|---|---|
AWS_ACCESS_KEY_ID |
IAMユーザーのアクセスキー |
AWS_SECRET_ACCESS_KEY |
シークレットキー |
AWS_REGION |
デプロイ先のAWSリージョン。東京リージョンの場合は「ap-northeast-1」 |
S3_BUCKET |
デプロイ先のS3バケット名。静的サイトをアップロードする先のバケット(例:my-static-site-bucket) |
DISTRIBUTION_ID |
CloudFrontのディストリビューションID(一覧から確認) |
GitHub Actionsワークフロー例
.github/workflows/deploy.yml を追加し、プッシュする。
name: Deploy to S3 and CloudFront
on:
push:
branches:
- main # mainブランチにpush時デプロイ
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
- name: Build project
run: |
npm ci
npm run build
- 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: ${{ secrets.AWS_REGION }}
- name: Deploy to S3
run: |
aws s3 sync build/ s3://${{ secrets.S3_BUCKET }} --delete
- name: Invalidate CloudFront cache
run: |
aws cloudfront create-invalidation \
--distribution-id ${{ secrets.DISTRIBUTION_ID }} \
--paths "/*"
デプロイの流れ
- mainブランチにpush
- GitHub Actionsが自動でビルド
- build/ディレクトリをS3へアップロード
- CloudFrontのキャッシュを自動無効化
- 数分後にサイトが最新化
動作確認
App.jsを適当に編集して、プッシュする。
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<div>自動デプロイ成功</div>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
これで完了です!
おつかれさまでした!
補足
Environment secrets と Repository secrets の違い
GitHub Actions では、ワークフロー内で使用する機密情報(API キーやトークンなど)を Secrets として安全に管理できます。Secrets には主に以下の 2 種類があり、用途やスコープが異なります。
1. Repository secrets(リポジトリ単位のシークレット)
特徴
- そのリポジトリ内のすべてのワークフローから参照可能
- リポジトリ単位 で管理したい値に向いている
- フォークされたリポジトリには自動では引き継がれない
- CI 全体で共通して使う API Key などを置きやすい
例:
- AWS アクセスキー
- Stripe や PayPay の API Key
- DB 接続情報
利用箇所:
Settings → Secrets and variables → Actions → Repository secrets
2. Environment secrets(環境単位のシークレット)
特徴
- GitHub Actions の “Environment(環境)” に紐づいた Secret
- 本番 / 開発 / ステージング など環境ごとに値を分けたい場合に最適
- Environment に “デプロイ保護ルール” を設定可能
- Approver(承認者)必須
- デプロイ前にレビューが必要
- 特定ブランチのみデプロイ許可
- 本番環境のキーを誤って開発用ワークフローで使う事故を防げる
例:
- production 用 AWS アクセスキー
- staging 用 API Gateway URL
- 本番専用の外部サービスシークレット(Webhook secret など)
利用箇所:
Settings → Environments → (environment 名) → Environment secrets
まとめ
- デプロイ用 IAM ユーザーは 最小権限・APIアクセスのみ
- GitHub Secrets を使って 機密情報を安全に管理
- CloudFront のキャッシュ無効化も自動化すると手動操作不要
- Environment secrets を使うと 本番環境の安全性をさらに向上 できる
最後に
本記事では、S3 + CloudFront を使った静的サイトの自動デプロイ(CI/CD)を、GitHub Actions で実現する手順を解説しました。
ポイントを押さえれば、手動アップロードの手間をなくし、常に最新の状態でサイトを公開できる環境を構築できます。
S3で静的ウェブサイトをホストする場合、手動デプロイもかなりシンプルなので、結構わかりやすかったと思います。
次の機会には、EC2などデプロイ手順がS3より複雑なものも紹介していきたいと思います。














