アーカイブ
はじめに
今さら感はありますが、GitHub Actions を使ってサーバーへデプロイするyamlの設定を書いたので、備忘録としてブログへ投稿
やりたいこと
今回やりたいことは至ってシンプルです
- Github Actions から AWS EC2 のサーバへボタンをポチればデプロイできるようにしたい
- pip install と migrate はデプロイ時に実行要否を任意に設定したい
デプロイ先やデプロイ対象の情報
デプロイ先
- AWS EC2(Ubuntu24.04)
- ※ssh は鍵認証のみのサーバー
デプロイ対象情報
- Djangoアプリケーション
yaml ファイル(最終形)
deploy-development.yml
- 以下のyamlファイルを、Gitリポジトリ直下の「.github/deploy-development.yml」で保存し、デフォルトブランチ(main)に反映すれば準備完了
- ※deploy-developmentの部分は任意
name: Deploy to Development
on:
workflow_dispatch:
inputs:
run_migrate:
description: 'migrate を実行する'
type: boolean
default: true
run_pip_install:
description: 'pip install を実行する'
type: boolean
default: true
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up SSH key
env:
EC2_KEY: ${{ secrets.DEV_EC2_KEY }}
run: |
mkdir -p ~/.ssh
printf '%s\n' "$EC2_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -t rsa ${{ secrets.DEV_EC2_HOST }} >> ~/.ssh/known_hosts 2>&1 || true
cat ~/.ssh/known_hosts
- name: Deploy to EC2
env:
RUN_MIGRATE: ${{ github.event.inputs.run_migrate }}
RUN_PIP_INSTALL: ${{ github.event.inputs.run_pip_install }}
run: |
echo "Deploying to ${{ secrets.DEV_EC2_HOST }}..."
# SSH接続テスト
ssh -i ~/.ssh/id_rsa -o ConnectTimeout=10 ${{ secrets.DEV_EC2_USER }}@${{ secrets.DEV_EC2_HOST }} "echo 'SSH connection successful'" || exit 1
# コードを転送(古いファイルを削除して更新)
rsync -avz --exclude '.git' -e "ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no" ./ ${{ secrets.DEV_EC2_USER }}@${{ secrets.DEV_EC2_HOST }}:${{ secrets.DEV_EC2_APP_DIR }}
# EC2上でコマンドを実行
ssh -i ~/.ssh/id_rsa ${{ secrets.DEV_EC2_USER }}@${{ secrets.DEV_EC2_HOST }} << "EOF"
set -e
cd ${{ secrets.DEV_EC2_APP_DIR }}
echo "Activating virtualenv..."
source ${{ secrets.DEV_EC2_ACTIVATE_PATH }}
if [ "${RUN_PIP_INSTALL}" = "true" ]; then
echo "Installing requirements..."
pip install -r requirements.txt
else
echo "Skipped pip install..."
fi
if [ "${RUN_MIGRATE}" = "true" ]; then
echo "Applying migrations..."
python manage.py migrate --noinput --settings=${{ secrets.DEV_DJANGO_SETTINGS_MODULE }}
else
echo "Skipped migrations..."
fi
echo "Restarting Gunicorn..."
sudo systemctl restart gunicorn
echo "Restarting Nginx..."
sudo systemctl restart nginx
echo "Deployment completed!"
EOF
- name: Cleanup sensitive files
if: always()
run: |
echo "Cleaning up sensitive files..."
rm -f ~/.ssh/id_rsa
rm -f ~/.ssh/known_hosts
rm -f ~/.ssh/config
echo "Cleanup completed!"
設定内容の解説
全体の概要
この Workflow は、GitHub Actions から EC2(開発環境)へ手動でデプロイするための設定となっています。
GitHub の画面から必要な処理(今回は pip install と migrate が選択可能)だけを選択してデプロイを実行できます。
ざっくり以下のフローで実行されています。
- ① 手動実行(workflow_dispatch)
- ② 実行時に「migrate」「pip install」を実行するか選べる
- ③ GitHub Actions から SSH で EC2 に接続
- ④ コードを rsync で転送
- ⑤ Django の migrate / Gunicorn / Nginx を再起動
各設定の説明を解説していきます。
Workflow 名
name: Deploy to Development
上記の設定で、GitHub Actionsに表示する「Workflow 名」を指定できます
※画像のように左サイドメニューに表示されます

実行トリガー
on:
workflow_dispatch:
inputs:
run_migrate:
description: 'migrate を実行する'
type: boolean
default: true
run_pip_install:
description: 'pip install を実行する'
type: boolean
default: true
「workflow_dispatch」を指定することで、手動実行をトリガーとしています。
「inputs」でデプロイ時のオプション設定を指定しています。
なお、「workflow_dispatch」のトリガーはデフォルト(main や master)ブランチに設定ファイルを反映しないと Github Actions には反映されません。

Job 定義
jobs:
deploy:
runs-on: ubuntu-latest
ここからがジョブの定義になっています。
「deploy」の部分は任意のジョブ名を指定し、「runs-on」は Github が用意している 「Runner」 を指定しています。
今回は最新の Ubuntu を指定
※使用可能なランナーはこちらを参照
リポジトリのチェックアウト
GitHub Actions 上でリポジトリの指定されたブランチのファイルを取得しています。
ここで取得したファイルをデプロイ先のサーバーに反映します。
steps:
- name: Checkout repository
uses: actions/checkout@v4
SSH キーのセットアップ
- name: Set up SSH key
env:
EC2_KEY: ${{ secrets.DEV_EC2_KEY }}
run: |
mkdir -p ~/.ssh
printf '%s\n' "$EC2_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -t rsa ${{ secrets.DEV_EC2_HOST }} >> ~/.ssh/known_hosts 2>&1 || true
cat ~/.ssh/known_hosts
SSH の秘密鍵(secrets.DEV_EC2_KEY)をデプロイを実行する runner のサーバーに配置して、デプロイ先(secrets.DEV_EC2_HOST)を known_hosts への登録を行なっています。
※secrets の設定方法は後述
デプロイ処理
- name: Deploy to EC2
env:
RUN_MIGRATE: ${{ github.event.inputs.run_migrate }}
RUN_PIP_INSTALL: ${{ github.event.inputs.run_pip_install }}
run: |
echo "Deploying to ${{ secrets.DEV_EC2_HOST }}..."
# SSH接続テスト
ssh -i ~/.ssh/id_rsa -o ConnectTimeout=10 ${{ secrets.DEV_EC2_USER }}@${{ secrets.DEV_EC2_HOST }} "echo 'SSH connection successful'" || exit 1
# コードを転送(古いファイルを削除して更新)
rsync -avz --exclude '.git' -e "ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no" ./ ${{ secrets.DEV_EC2_USER }}@${{ secrets.DEV_EC2_HOST }}:${{ secrets.DEV_EC2_APP_DIR }}
# EC2上でコマンドを実行
ssh -i ~/.ssh/id_rsa ${{ secrets.DEV_EC2_USER }}@${{ secrets.DEV_EC2_HOST }} << "EOF"
set -e
cd ${{ secrets.DEV_EC2_APP_DIR }}
echo "Activating virtualenv..."
source ${{ secrets.DEV_EC2_ACTIVATE_PATH }}
if [ "${RUN_PIP_INSTALL}" = "true" ]; then
echo "Installing requirements..."
pip install -r requirements.txt
else
echo "Skipped pip install..."
fi
if [ "${RUN_MIGRATE}" = "true" ]; then
echo "Applying migrations..."
python manage.py migrate --noinput --settings=${{ secrets.DEV_DJANGO_SETTINGS_MODULE }}
else
echo "Skipped migrations..."
fi
echo "Restarting Gunicorn..."
sudo systemctl restart gunicorn
echo "Restarting Nginx..."
sudo systemctl restart nginx
echo "Deployment completed!"
EOF
以下の流れでデプロイ処理を実行しています。
- ① デプロイ先のサーバーに SSH で接続できるかをチェック
- ② github の runner のサーバー上に展開されたソース一式を rsync で転送
- ③ SSH でデプロイ先に接続(以降はデプロイ先でのコマンド実行)
- ④ アプリケーションのディレクトリに移動
- ⑤ Python 仮想環境の activate を実行
- ⑥ 実行時に指定された pip install 実行のチェックの有無を確認して、有なら pip install を実行
- ⑦ 実行時に指定された migrate 実行のチェックの有無を確認して、有なら migrate を実行
- ⑧ gunicorn を再起動
- ⑨ nginx を再起動
ワークフロー完了時の処理
- name: Cleanup sensitive files
if: always()
run: |
echo "Cleaning up sensitive files..."
rm -f ~/.ssh/id_rsa
rm -f ~/.ssh/known_hosts
rm -f ~/.ssh/config
echo "Cleanup completed!"
最後に runner 上にある秘密鍵・known_hosts・config の機微な情報を削除
secrets の設定について
GitHub の Settings > Secrets and variables > actions から GitHub Actions から参照可能な定数を設定できます。
秘密鍵の情報やデプロイ先サーバー関連の接続情報など、機微な情報はこの secrets に設定して参照するようにしましょう。

まとめ
今回は、GitHub Actions の workflow_dispatch を使って、AWS EC2(Ubuntu 24.04)上の Django アプリケーションへ手動デプロイを行う仕組みを構築しました。
単に自動デプロイを行うだけではなく、オプション設定を追加することで、より柔軟な対応が実現できることを確認できました。
また、SSH 鍵や接続情報などを GitHub Secrets で管理とすることで、機微な情報をリポジトリやコード上に直接記載することなく、セキュアな運用が可能となります。
今後も GitHub Actions を使い倒していき、新たな知見が得られたらブログに書き残してきます。
このブログ記事を見てくださった方に少しでも参考になれば、幸いです。
積極採用中!尖ったPythonエンジニアへの第一歩はこちらから


