GitHubとAWSを組み合わせることで、強力な自動化基盤を構築できます。この記事では、GitHub ActionsとAWSサービスを連携させた実践的なハンズオンを紹介します。初心者でも確実に実装できるよう、GitHub ActionsでのEC2自動デプロイから、S3静的サイト公開、Lambda関数デプロイまで、段階的に解説します。
GitHub×AWSで実現できること
自動化の全体像
コード変更(git push)
↓
GitHub Actions自動実行
↓
ビルド・テスト
↓
AWSへ自動デプロイ
↓
本番環境更新メリット:
- 手動デプロイの排除
- ヒューマンエラー削減
- リリース時間短縮
- 一貫性のある環境構築
できることの例
| サービス | 用途 | 難易度 |
|---|---|---|
| EC2 | Webアプリ自動デプロイ | ⭐⭐ |
| S3 | 静的サイト公開 | ⭐ |
| Lambda | サーバーレス関数デプロイ | ⭐⭐ |
| ECS | コンテナアプリデプロイ | ⭐⭐⭐ |
| CodeDeploy | ブルーグリーンデプロイ | ⭐⭐⭐ |
事前準備
必要なもの
GitHub側:
- GitHubアカウント
- リポジトリ(Public/Private)
AWS側:
- AWSアカウント
- IAMユーザー(適切な権限)
- 対象サービス(EC2/S3など)
IAMユーザー作成
手順:
1. AWSコンソール → IAM
2. Users → Add users
3. ユーザー名: github-actions-user
4. Access key - Programmatic access ✅
5. Attach policies directly:
- AmazonEC2FullAccess(EC2デプロイ用)
- AmazonS3FullAccess(S3デプロイ用)
6. Create user
7. Access Key ID と Secret Access Key を保存注意: 本番環境では最小権限の原則に従い、必要な権限のみ付与してください。
GitHub Secretsに認証情報を保存
1. GitHubリポジトリ → Settings
2. Secrets and variables → Actions
3. New repository secret
登録する情報:
- AWS_ACCESS_KEY_ID: (IAMのAccess Key ID)
- AWS_SECRET_ACCESS_KEY: (IAMのSecret Access Key)
- AWS_REGION: ap-northeast-1(東京リージョン)ハンズオン1:EC2にNode.jsアプリを自動デプロイ
システム構成
GitHub Repository
↓ git push
GitHub Actions
↓ SSH接続
EC2インスタンス
↓ アプリ更新
Webアプリ公開EC2インスタンスの準備
1. インスタンス起動:
AMI: Amazon Linux 2023
インスタンスタイプ: t2.micro(無料枠)
セキュリティグループ:
- SSH (22) ← 自分のIP
- HTTP (80) ← 0.0.0.0/0
- Custom (3000) ← 0.0.0.0/0(開発用)2. SSH接続して環境構築:
ssh -i your-key.pem ec2-user@your-ec2-ip
# Node.jsインストール
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
source ~/.bashrc
nvm install 20
nvm use 20
# アプリディレクトリ作成
mkdir ~/myapp
cd ~/myapp
# pm2インストール(プロセス管理)
npm install -g pm23. SSH鍵をGitHub Secretsに登録:
秘密鍵(your-key.pem)の内容をコピー
GitHub Secrets に登録:
- EC2_SSH_KEY: (秘密鍵の内容)
- EC2_HOST: (EC2のパブリックIP)
- EC2_USER: ec2-userサンプルアプリ作成
package.json:
{
"name": "github-aws-demo",
"version": "1.0.0",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.18.0"
}
}server.js:
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send(`
GitHub Actions × AWS EC2
自動デプロイ成功!
デプロイ時刻: ${new Date().toLocaleString('ja-JP')}
`);
});
app.get('/health', (req, res) => {
res.json({ status: 'OK' });
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});GitHub Actions設定
.github/workflows/deploy-ec2.yml:
name: Deploy to EC2
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Deploy to EC2
env:
SSH_KEY: ${{ secrets.EC2_SSH_KEY }}
HOST: ${{ secrets.EC2_HOST }}
USER: ${{ secrets.EC2_USER }}
run: |
# SSH秘密鍵を設定
echo "$SSH_KEY" > private_key.pem
chmod 600 private_key.pem
# EC2にファイル転送
scp -i private_key.pem -o StrictHostKeyChecking=no -r \
server.js package.json ${USER}@${HOST}:~/myapp/
# EC2でアプリ更新
ssh -i private_key.pem -o StrictHostKeyChecking=no ${USER}@${HOST} << 'EOF'
cd ~/myapp
npm install
pm2 restart myapp || pm2 start server.js --name myapp
pm2 save
EOF
# 秘密鍵削除
rm -f private_key.pem
- name: Verify deployment
run: |
sleep 5
curl -f http://${{ secrets.EC2_HOST }}:3000/health || exit 1
echo "Deployment successful!"デプロイ実行
1. リポジトリにプッシュ:
git add .
git commit -m "Add EC2 auto deploy"
git push origin main2. GitHub Actionsで確認:
Actions タブ
→ Deploy to EC2 ワークフロー
→ ログ確認
→ ✅ 成功3. ブラウザでアクセス:
http://your-ec2-ip:3000
→ 「自動デプロイ成功!」表示完了! コードを変更してpushするたびに自動デプロイされます。
GitHub Actionsの実践例は「【試行錯誤の記録】GitHub ActionsでWordPress自動投稿!403エラーとの戦い」でも紹介しています。
ハンズオン2:S3で静的サイトを自動公開
システム構成
GitHub Repository(HTML/CSS/JS)
↓ git push
GitHub Actions
↓ AWS CLI
S3バケット
↓ 静的Webホスティング
インターネット公開S3バケット作成
1. バケット作成:
1. S3コンソール → Create bucket
2. Bucket name: my-github-demo-site(グローバルで一意)
3. Region: ap-northeast-1
4. Block Public Access: すべてOFF(公開用)
5. Create bucket2. 静的Webホスティング有効化:
バケット → Properties
→ Static website hosting → Enable
→ Index document: index.html
→ Error document: error.html
→ Save changes3. バケットポリシー設定:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-github-demo-site/*"
}
]
}サンプルサイト作成
index.html:
GitHub Actions × S3
GitHub Actions × S3
静的サイトの自動デプロイ成功!
style.css:
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.container {
background: white;
padding: 2rem;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
text-align: center;
}
h1 {
color: #333;
margin-bottom: 1rem;
}script.js:
document.getElementById('timestamp').textContent =
`最終デプロイ: ${new Date().toLocaleString('ja-JP')}`;GitHub Actions設定
.github/workflows/deploy-s3.yml:
name: Deploy to S3
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
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: Sync to S3
run: |
aws s3 sync . s3://my-github-demo-site \
--exclude ".git/*" \
--exclude ".github/*" \
--delete
- name: Invalidate CloudFront (optional)
run: |
echo "CloudFront未使用の場合はスキップ"
# aws cloudfront create-invalidation \
# --distribution-id YOUR_DISTRIBUTION_ID \
# --paths "/*"デプロイ実行
1. プッシュ:
git add .
git commit -m "Add S3 static site deploy"
git push origin main2. S3エンドポイントにアクセス:
http://my-github-demo-site.s3-website-ap-northeast-1.amazonaws.com完了! HTMLを変更するたびに自動で公開されます。
ハンズオン3:Lambda関数の自動デプロイ
システム構成
GitHub Repository(Lambda関数)
↓ git push
GitHub Actions
↓ zip & AWS CLI
Lambda関数更新
↓ API Gateway
REST API公開Lambda関数作成
1. AWSコンソールでLambda作成:
Lambda → Create function
Function name: github-demo-function
Runtime: Node.js 20.x
Create function2. 環境変数設定(オプション):
Configuration → Environment variables
Key: STAGE
Value: productionサンプル関数
index.js:
exports.handler = async (event) => {
console.log('Event:', JSON.stringify(event));
const name = event.queryStringParameters?.name || 'World';
const timestamp = new Date().toISOString();
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify({
message: `Hello, ${name}!`,
timestamp: timestamp,
environment: process.env.STAGE || 'development',
deployedBy: 'GitHub Actions'
})
};
};package.json:
{
"name": "github-lambda-demo",
"version": "1.0.0",
"description": "GitHub Actions Lambda deployment demo"
}GitHub Actions設定
.github/workflows/deploy-lambda.yml:
name: Deploy to Lambda
on:
push:
branches: [main]
paths:
- 'lambda/**'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
working-directory: ./lambda
run: npm install --production
- name: Create deployment package
working-directory: ./lambda
run: |
zip -r function.zip .
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
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 Lambda
working-directory: ./lambda
run: |
aws lambda update-function-code \
--function-name github-demo-function \
--zip-file fileb://function.zip
- name: Wait for update
run: |
aws lambda wait function-updated \
--function-name github-demo-function
- name: Test Lambda function
run: |
aws lambda invoke \
--function-name github-demo-function \
--payload '{"queryStringParameters":{"name":"GitHub"}}' \
response.json
cat response.jsonAPI Gateway設定(オプション)
REST APIとして公開:
1. API Gateway → Create API
2. REST API → Build
3. Create resource: /hello
4. Create method: GET
5. Integration type: Lambda Function
6. Lambda Function: github-demo-function
7. Deploy API → Stage: prodエンドポイント:
https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/hello?name=World応用パターン
パターン1:環境別デプロイ
複数環境の管理:
on:
push:
branches:
- main # 本番環境
- develop # 開発環境
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Set environment
run: |
if [ "${{ github.ref }}" == "refs/heads/main" ]; then
echo "ENVIRONMENT=production" >> $GITHUB_ENV
echo "LAMBDA_FUNCTION=prod-function" >> $GITHUB_ENV
else
echo "ENVIRONMENT=development" >> $GITHUB_ENV
echo "LAMBDA_FUNCTION=dev-function" >> $GITHUB_ENV
fi
- name: Deploy
run: |
aws lambda update-function-code \
--function-name ${{ env.LAMBDA_FUNCTION }} \
--zip-file fileb://function.zipパターン2:ブルーグリーンデプロイ
無停止デプロイ:
- name: Create new version
run: |
VERSION=$(aws lambda publish-version \
--function-name my-function \
--query 'Version' --output text)
echo "VERSION=$VERSION" >> $GITHUB_ENV
- name: Update alias
run: |
aws lambda update-alias \
--function-name my-function \
--name production \
--function-version ${{ env.VERSION }}パターン3:ロールバック機能
デプロイ失敗時の自動ロールバック:
- name: Deploy and test
id: deploy
run: |
# デプロイ
aws lambda update-function-code ...
# ヘルスチェック
if ! curl -f https://api.example.com/health; then
exit 1
fi
- name: Rollback on failure
if: failure() && steps.deploy.outcome == 'failure'
run: |
aws lambda update-function-code \
--function-name my-function \
--s3-bucket backup-bucket \
--s3-key previous-version.zipトラブルシューティング
問題1:EC2デプロイでSSH接続失敗
エラー:
Permission denied (publickey)原因:
- SSH鍵の改行コードが正しくない
- 鍵の権限が適切でない
解決:
# 改行コードを明示的に処理
run: |
echo "$SSH_KEY" | tr -d '\r' > private_key.pem
chmod 600 private_key.pem問題2:S3デプロイで403エラー
原因:
- IAMユーザーに権限がない
- バケットポリシーが未設定
解決:
1. IAMユーザーに AmazonS3FullAccess 付与
2. バケットポリシーで PublicReadGetObject 設定
3. ブロックパブリックアクセスを確認問題3:Lambda関数が更新されない
原因:
- 関数名が間違っている
- zipファイルサイズ超過(50MB制限)
解決:
# 関数名確認
aws lambda list-functions
# zipサイズ確認
ls -lh function.zip
# 大きい場合はS3経由でデプロイ
aws s3 cp function.zip s3://my-bucket/
aws lambda update-function-code \
--function-name my-function \
--s3-bucket my-bucket \
--s3-key function.zipセキュリティベストプラクティス
1. IAM権限の最小化
NG(フルアクセス):
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}OK(必要な権限のみ):
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:DeleteObject",
"lambda:UpdateFunctionCode"
],
"Resource": [
"arn:aws:s3:::my-bucket/*",
"arn:aws:lambda:ap-northeast-1:*:function:my-function"
]
}2. Secrets管理
GitHub Secrets以外の選択肢:
- AWS Secrets Manager:より高度な管理
- AWS Systems Manager Parameter Store:無料枠あり
GitHub ActionsでSecrets Manager使用:
- name: Get secrets
run: |
SECRET=$(aws secretsmanager get-secret-value \
--secret-id my-app-secret \
--query SecretString --output text)
echo "::add-mask::$SECRET"
echo "SECRET=$SECRET" >> $GITHUB_ENV3. 監査ログ
CloudTrailで操作履歴記録:
CloudTrail → Create trail
→ S3バケットに操作ログ保存
→ GitHub Actionsの操作も記録まとめ
GitHub ActionsとAWSの連携で、強力な自動化基盤を構築できます。
実装したハンズオン:
- EC2自動デプロイ:Node.jsアプリをSSH経由でデプロイ
- S3静的サイト:HTML/CSS/JSを自動公開
- Lambda関数:サーバーレス関数の自動更新
メリット:
- 手動作業の削減
- デプロイミスの防止
- 一貫性のある環境
- リリース時間の短縮
コスト:
- GitHub Actions:パブリックリポジトリは無料
- AWS無料枠:1年間または月次制限内
- 実質コスト:ほぼ無料で始められる
まずは簡単なS3デプロイから始めて、徐々に複雑な構成に挑戦してみましょう!
関連記事
- 【試行錯誤の記録】GitHub ActionsでWordPress自動投稿!403エラーとの戦い

- GitHub CLI完全ガイド:コマンドラインでGitHub操作を効率化

- VSCodeでGitを使いこなす:初心者から実務まで完全ガイド

コメント