Github ActionsでMultiContainerなAzure WebApp for Containersをデプロイする

友達に頼まれて、@kunyamiさんのスライド 堅牢&運用楽々な WordPress を Azure App Service でを参考に、WordpressをMultiContainerなAzure WebApp for Containersで構築してたのですが、いくつかハマったのでメモとして残します。

基本的な設定は、@kunyamiさんの資料の通りに進めたのですが、今回は、一部Wordpress管理外の静的なページを含むため、独自コンテナをビルドする必要があったので、GitHub Actionsを使用して、コンテナイメージのビルド、Azure WebApp for Containersへのデプロイをすることにしました。

リポジトリは以下の様な構成になっています。

  • Dockerfile - デプロイ用Dockerfile
  • docker-compose.yml - デプロイ用 docker-composeファイル
  • 静的ファイル用のディレクト
  • その他設定ファイルなど

ベースイメージは、wordpress公式のものを使用して、静的なページは、ビルド時にコピーする様にしました

Dockerfileサンプル

FROM wordpress:latest

COPY static_webpages /var/www/html/static_webpages

事前準備

Azure WebAppデプロイ用クレデンシャルの作成

いつものですね。以下のコマンドを実行すると表示されるJSONがクレデンシャルです。

$ az ad sp create-for-rbac --name "https://[WebAppの名前].azurewebsites.net" --role contributor \
    --scopes /subscriptions/[サブスクリプションID]/resourceGroups/wetest \
    --sdk-auth

秘匿情報の設定

Github Actions内で利用する秘匿情報は、Githubの対象リポジトリ内の Settings -> Secrets で設定します。

f:id:kaz_29:20200504130051p:plain
github Secrets

今回は、ビルドしたイメージをDocker Hubに保存するので、Docker Hubアカウントパスワードと先ほど作成した、クレデンシャルをSecretsに追加します。

  • AZURE_CREDENTIALS - Azureクレデンシャル
  • DOCKER_PASSWORD - Docker Hubのパスワード

Github Actionsの設定

Github Actionsの設定は、リポジトリ内の .github/workfloes ディレクトリ以下に設定ファイルを配置します。今回作成したのは以下の様なファイルです。

name: Build And Deploy

env:
  DOCKER_USERNAME: [Docker Hubのユーザ名]
  DOCKER_IMAGENAME: [docker image名]
  AZURE_WEBAPP_NAME: [webappの名称]

on: 
  push:
    branches:
      - master
  
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v2
    
      - name: Azure authentication
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS  }}

      - name: Build & push Docker image
        uses: docker/build-push-action@v1
        with:
          image: ${{ env.DOCKER_USERNAME }}/${{ env.DOCKER_IMAGENAME }}
          repository: ${{ env.DOCKER_USERNAME }}/${{ env.DOCKER_IMAGENAME }}
          dockerfile: Dockerfile
          username: ${{ env.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
          tags: ${{ github.sha }} 

      - name: 'Deploy to Azure Web App for Container'   
        uses: azure/webapps-deploy@v2
        with: 
          images: ${{ env.DOCKER_USERNAME }}/${{ env.DOCKER_IMAGENAME }}:${{ github.sha }}
          app-name: ${{ env.AZURE_WEBAPP_NAME }}
          configuration-file: docker-compose-webapp.yml

yamlファイルを見れば一目瞭然ですが、今回作成したJobには以下の4つのStepが定義されています。

  • Check out code - コードをチェックアウト
  • Azure authentication - Azureの認証処理
  • Build & push Docker image - docker imageのビルドとプッシュ
  • Deploy to Azure Web App for Container - Azure WebApp for Containersへのデプロイ

docker imageのビルドとプッシュ

docker imageのビルドとプッシュには、Docker公式のGitHub Actionを使っています。 公式サイトに詳しい解説があるので、そちらを参照してください。

今回は、ビルト時のタグにgit hashを使用しているので以下の様に指定しています。

          tags: ${{ github.sha }} 

Azureの認証とAzure WebApp for Containersへのデプロイ

Azure WebApp for Containersへのデプロイは、Azure 公式のGitHub Actionを使っています。 こちらも、公式サイトに詳しい解説があるので、そちらを参照してください。

MultiContainerなAzure WebApp for Containersのデプロイ方法

今回は、MultiContainerなAzure WebApp for Containersを使用しているのですが、公式ドキュメントにはMultiContainerの場合のデプロイ方法は書かれていないため、GitHub Actionのソースコードを確認したところ、以下の様に設定情報を初期化しているのを発見しました。

...
class ActionParameters {
    constructor(endpoint) {
        this._publishProfileContent = core.getInput('publish-profile');
        this._appName = core.getInput('app-name');
        this._slotName = core.getInput('slot-name');
        this._packageInput = core.getInput('package');
        this._images = core.getInput('images');
        this._multiContainerConfigFile = core.getInput('configuration-file');
        this._startupCommand = core.getInput('startup-command');
        this._endpoint = endpoint;
    }
...

ということで、MultiContainer時のdocker-composeファイルは configuration-file で指定できました。最終的なStepの設定が下記です。

      - name: 'Deploy to Azure Web App for Container'   
        uses: azure/webapps-deploy@v2
        with: 
          images: ${{ env.DOCKER_USERNAME }}/${{ env.DOCKER_IMAGENAME }}:${{ github.sha }}
          app-name: ${{ env.AZURE_WEBAPP_NAME }}
          configuration-file: docker-compose-webapp.yml

docker-compose.yml 内でイメージ名を指定していますが、 images に今回ビルドしたタグを含むイメージ名を指定しています。 これもドキュメントには記載がないのですが、試行錯誤している最中に以下のエラーが発生してエラーメッセージの内容から発見したのですが、MultiContainer時にimage名を指定すると、docker-compose内のイメージ名を上書きしてくれますので、自前でdocker-composeファイルを書き換える様な処理は書かなくても大丈夫でした。

試行錯誤中に発生したエラーメッセージ

Deployment Failed with Error: Error: For single-container, just specify a valid image name. For multi-container specifying a Docker-Compose file is mandatory and specifying image names is optional. Provide image names if the tags in Docker-Compose file need to be substituted.

また、slot-name でデプロイ対象のスロット名も指定できる様なので、B/Gデプロイもできそうですね。

まとめ

マーケットプレイスで公開されているGitHub Actionはソースコードも公開されているので、ドキュメントに記載のない内容はソースコードにあたるとすんなり解決できることも多そうです。 GitHub Actionsかなり便利なので、これからも積極的に使っていきたいです。