カテゴリー
アーカイブ

01.07
2026

Github Actions の手動デプロイを設定してみた

  • LINE

はじめに

今さら感はありますが、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のプロフェッショナル集団です。
積極採用中!尖ったPythonエンジニアへの第一歩はこちらから