Xserverへのアプリケーションの継続的デプロイを、GitHub Actionsのワークフローを活用して実現する方法を解説します。
この記事では、ReactフロントエンドとNest.JSバックエンドを含むプロジェクトの自動デプロイ方法を詳しく説明します。
GitHub Actionsの設定
まず、GitHub Actionsの設定を行います。
リポジトリの「Settings」タブから「Secrets and variables」→「Actions」を選択します。

以下の情報をActions secretsとして設定します。
※ 変数名は任意です。
- XSERVER_HOST: Xserverのホスト名
- XSERVER_PORT: SSHポート番号
- XSERVER_USER: Xserverのユーザー名
- XSERVER_SSH_KEY: SSH秘密鍵
- XSERVER_SSH_PASSPHRASE: SSH鍵のパスフレーズ(必要な場合)
ワークフローの設定
次に、以下ファイルを作成し、デプロイワークフローを設定します。
- .github/workflows/deploy.yaml
以下に、ワークフローの主要な部分を順番に説明します。
1. ワークフローのトリガー設定
何をトリガーにワークフローを実行するか、任意に設定してください。
on:
pull_request:
types: [ closed ]
branches: [ main ]
workflow_dispatch:
jobs:
deploy:
if: |
(
github.event_name == 'pull_request' &&
github.event.pull_request.merged == true &&
startsWith(github.event.pull_request.head.ref, 'release/')
) || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
上記例では、mainブランチへのreleaseブランチのプルリクエストがマージされた時、または手動で実行された時にトリガーされます。
2. 環境のセットアップ
Node.jsの設定とYarnのキャッシュを設定します。
steps:
- uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: '16.20.2'
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v3
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
Xserver環境では、Node.jsが実行できる最新バージョンは16.20.2となるため、以下のバージョンを設定しています。
node-version: '16.20.2'
3. 環境変数の取得
Actions secretsの設定値を使用して、XserverへSSH接続します。
env.productionを取得して、環境変数を参照できるようにします。
環境変数を使用していない場合、省略してください。
- name: Get .env file from production server
env:
HOST: ${{ secrets.XSERVER_HOST }}
USER: ${{ secrets.XSERVER_USER }}
PORT: ${{ secrets.XSERVER_PORT }}
KEY: ${{ secrets.XSERVER_SSH_KEY }}
PASSPHRASE: ${{ secrets.XSERVER_SSH_PASSPHRASE }}
run: |
echo "$KEY" > deploy_key
chmod 600 deploy_key
mkdir -p ~/.ssh
ssh-keyscan -p $PORT $HOST >> ~/.ssh/known_hosts
eval $(ssh-agent -s)
echo "$PASSPHRASE" | ssh-add deploy_key
scp -P $PORT $USER@$HOST:/home/~ 各自のディレクトリ ~/.env.production ./.env.production
- name: Set environment variables from .env.production
run: |
export $(grep -v '^#' .env.production | xargs)
echo "REACT_APP_ENV=$REACT_APP_ENV" >> $GITHUB_ENV
echo "REACT_APP_API_HOST=$REACT_APP_API_HOST" >> $GITHUB_ENV
echo "REACT_APP_API_PORT=$REACT_APP_API_PORT" >> $GITHUB_ENV
...各自の環境変数
shell: bash
※ 「~ 各自のディレクトリ ~」箇所を書き換えてください。
4. フロントエンドのビルド
フロントエンドのディレクトリに移動し、依存関係をインストールしてビルドを実行します。
- name: Build Frontend
working-directory: ./frontend
env:
REACT_APP_ENV: ${{ env.REACT_APP_ENV }}
REACT_APP_API_HOST: ${{ env.REACT_APP_API_HOST }}
REACT_APP_API_PORT: ${{ env.REACT_APP_API_PORT }}
...各自の環境変数
run: |
yarn install --frozen-lockfile
yarn build
5. バックエンドのビルド
バックエンドのディレクトリに移動し、同様にビルドを実行します。
- name: Build Backend
working-directory: ./backend
run: |
yarn install --frozen-lockfile
yarn build
6. Xserverへのデプロイ
ビルドしたフロントエンドとバックエンドのファイルをXserverにデプロイし、バックエンドアプリケーションをPM2で起動または再起動します。
また、データベースのマイグレーションも実行しています。
- name: Deploy to Xserver
env:
HOST: ${{ secrets.XSERVER_HOST }}
USER: ${{ secrets.XSERVER_USER }}
PORT: ${{ secrets.XSERVER_PORT }}
KEY: ${{ secrets.XSERVER_SSH_KEY }}
PASSPHRASE: ${{ secrets.XSERVER_SSH_PASSPHRASE }}
run: |
# SSHの設定
echo "$KEY" > deploy_key
chmod 600 deploy_key
mkdir -p ~/.ssh
ssh-keyscan -p $PORT $HOST >> ~/.ssh/known_hosts
eval $(ssh-agent -s)
echo "$PASSPHRASE" | ssh-add deploy_key
# バックエンドディレクトリの作成
ssh -p $PORT $USER@$HOST "mkdir -p /home/~ 各自のディレクトリ ~/backend"
# フロントエンドのデプロイ
rsync -avz -e "ssh -p $PORT"
./frontend/build/ $USER@$HOST:/home/~ 各自のディレクトリ ~/public_html/~ 各自のディレクトリ ~/
# バックエンドのデプロイ
rsync -avz -e "ssh -p $PORT"
./backend/dist/ $USER@$HOST:/home/~ 各自のディレクトリ ~/backend/dist/
rsync -avz -e "ssh -p $PORT"
./backend/package.json $USER@$HOST:/home/~ 各自のディレクトリ ~/backend/
rsync -avz -e "ssh -p $PORT"
./backend/yarn.lock $USER@$HOST:/home/~ 各自のディレクトリ ~/backend/
rsync -avz -e "ssh -p $PORT"
./backend/ecosystem.config.js $USER@$HOST:/home/~ 各自のディレクトリ ~/backend/
# PM2でバックエンドを起動または再起動
ssh -p $PORT $USER@$HOST "cd /home/~ 各自のディレクトリ ~/backend &&
if pm2 list | grep -q 'アプリ名'; then
pm2 reload ecosystem.config.js --only アプリ名;
else
pm2 start ecosystem.config.js --only アプリ名;
fi"
# バックエンドの依存関係をインストール
ssh -p $PORT $USER@$HOST "cd /home/~ 各自のディレクトリ ~/backend &&
yarn install --frozen-lockfile"
# データベースマイグレーションの実行
ssh -p $PORT $USER@$HOST "cd /home/~ 各自のディレクトリ ~/backend &&
NODE_ENV=production npx typeorm migration:run -d dist/src/typeorm.config.js"
ecosystem.config.jsは、PM2の設定ファイルです。
以下のように設定して、main.jsで起動するサーバーを永続化します。
module.exports = {
apps: [
{
name: 'アプリ名',
script: 'dist/src/main.js',
env: {
NODE_ENV: 'production'
}
}
]
};
※ 「~ 各自のディレクトリ ~」、「アプリ名」箇所を書き換えてください。
7. クリーンアップ
最後に、SSHエージェントを終了し、一時的に作成したデプロイキーを削除します。
- name: Cleanup
if: always()
run: |
eval $(ssh-agent -k)
rm -f deploy_key
注意点
- セキュリティ上の理由から、本番環境の.envファイルをGitHubリポジトリに直接保存することは避け、Xserverから取得しています。
- PM2を使用してバックエンドアプリケーションを管理しています。
- PM2についてはこちらを参考にしてください。
以上の設定により、GitHubのmainブランチへのマージ時に自動的にXserverへデプロイが行われるCI/CDパイプラインが構築されます。