2022.07.06[Wed]
[シリーズ連載] Dokku + Github Actions でプルリクエストに連動したサーバーを立てる

Dokku + Github Actions でプルリクエストに連動したサーバーを立てる 後編

  • Docker
  • CI/CD

目次

前編はこちら: https;//techlab.q-co.jp/articles/51/

Webエンジニアの茄子です。
前編では、dokkuのインストールからアプリケーションをデプロイするところまで行いました。
本記事ではデプロイをGithub Actionsで行う設定を紹介します。

dokkuのガイドではアプリケーション(app)は1レポジトリ1コンテナの対応で、`dokku git:set` によってそのデプロイ対象ブランチを切り替えるという想定のセットアップになっていました。
ここから主目的である、すべて同じアプリケーションで違うブランチという構成に設定していきます。
まずは、いくつかの下準備をします。

Dockerのディレクトリを外部ボリュームに移動

Dockerはイメージなどで容量が必要なので元の8GBでは足りなくなります。そのためDockerの使うディレクトリを外部ボリュームに移動させます。
下記リンクのチュートリアルに従って移動してください。サービスやOSが違う場合は適宜読み替えてください。

チュートリアル:  https://dokku.com/docs/community/tutorials/run-on-external-volume/
AWS Docs:  https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-using-volumes.html

メンテナンスcronの設定

使っていくと不要になったイメージなどがどんどん溜まっていくので、削除するcronをあらかじめ設定しておきます。

# /etc/cron.d/docker-cleanup を作成
0 7 * * * root docker system prune -a --force

Github Actions用の鍵を登録

Github Actionsの処理の中でSSHキーが必要になります。
レポジトリの Settings -> Secrets -> Github Actions を開き、インスタンスにログインするものと同じプライベートキーを登録してください。インスタンス作成時と別のものを使う場合はインスタンスへの登録に加えて、dokkuへの登録も改めて必要になります。

# dokkuに追加する場合
cat <pubkeyファイル> | sudo dokku ssh-keys:add admin2

また、インスタンスのファイアウォールが有効な場合、Github ActionsからDokkuサーバーへのアクセスを許可する必要があります。
https://docs.github.com/ja/rest/meta#get-github-meta-information から使われる可能性のあるIPアドレスのリストを取得できます。大量なので少し時間がかかるかもしれません。

Github Actions 設定ファイル

本題のPRごとにする設定をします。
https://github.com/dokku/github-action/blob/master/example-workflows/review-app.yml
dokkuが用意している Github ActionsプラグインにPreview App というPR向けの機能が用意されているのでこちらを元に設定します。

pull_request.yaml

アプリケーションのルートに .github/workflows/pull_request.yaml を作成します(ファイル名は任意)
ドメイン、鍵の名前等を適宜自身の環境に合わせて変更してください。

以下に示す設定では、コンテナはGithubのPR番号をとって、pr-1, pr-2 のような名前で作成されます。( =サイトは https://pr-1.dokku.yourdomain.com )
review_app_name: pr-${{ github.event.pull_request.number }}
で任意に変更可能です。(変更した場合、SSHで domains:set をする場所も変更してください。)

---
name: 'pull_request'

on:
  pull_request

jobs:
  review_app:
    runs-on: ubuntu-latest
    # 元の == 'opened' だと追加コミットした時に発火しない
    if: github.event_name == 'pull_request' && github.event.action != 'closed'
    steps:
      - name: Cloning repo
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Push to dokku
        uses: dokku/github-action@master
        with:
          command: review-apps:create
          git_remote_url: 'ssh://dokku@dokku.yourdomain.com:22/<レポジトリ名>'
          git_push_flags: --force -v
          review_app_name: pr-${{ github.event.pull_request.number }}
          ssh_private_key: ${{ secrets.GITHUB_PRIVATE_KEY }}

    # HTTPSにする設定が無いので別途接続し直して有効に
      - name: Set HTTPS
        run: |
          echo "Setting HTTPS."
          mkdir -p ~/.ssh
          echo "${{ secrets.GITHUB_PRIVATE_KEY }}" | tr -d '\r' > ~/.ssh/id_rsa
          chmod 700 ~/.ssh/id_rsa
          eval $(ssh-agent -s)
          ssh-add ~/.ssh/id_rsa
          ## ユーザーdokkuはdokkuコマンド専用ユーザー
          ssh -v -o StrictHostKeyChecking=no dokku@dokku.yourdomain.com "domains:set pr-${{ github.event.pull_request.number }} pr-${{ github.event.pull_request.number }}.dokku.yourdomain.com"

  destroy_review_app:
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request' && github.event.action == 'closed'
    steps:
      - name: Destroy the review app
        uses: dokku/github-action@master
        with:
          command: review-apps:destroy
          git_remote_url: 'ssh://dokku@dokku.yourdomain.com:22/<レポジトリ名>'
          review_app_name: pr-${{ github.event.pull_request.number }}
          ssh_private_key: ${{ secrets.GITHUB_PRIVATE_KEY }}

push-main.yaml

目的はPR用のサーバーですが、メインのブランチも一緒に運用していく場合はプッシュ用のActionも作ります。
.github/workflows/push-main.yaml

---
name: 'push-main'

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Cloning repo
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Push to dokku
        uses: dokku/github-action@master
        with:
          git_remote_url: 'ssh://dokku@dokku.yourdomain.com:22/<レポジトリ名>'
          ssh_private_key: ${{ secrets.GITHUB_PRIVATE_KEY }}

動作確認

・新しいブランチを作って適当な変更を加えてプッシュし、プルリクエストを作ってサーバーが起動する
・更に適当な変更を加えてプッシュし、変更点が反映される
・プルリクエストをマージしmainのサーバーが更新される(push-mainを作った場合)

以上を確認できたら、完成です。

Share

  1. 01 Dokku + Github Actions でプルリクエストに連動したサーバーを立てる 前編 >
  2. 02 Dokku + Github Actions でプルリクエストに連動したサーバーを立てる 後編
gitのコミット時にコードの変更部分に対して、自動でフォーマットを行うDokku + Github Actions でプルリクエストに連動したサーバーを立てる 前編