Azure Web Appsお勉強メモ(6)Azure Container RegistryにpushしたらAzure Web Appsにデプロイする

はじめに

先日からAzure Web AppsにRailsアプリを動かすことをやっています。先日の記事でGitHub Actionsを使ってDockerイメージを作成してAzure Container Registryにpushすることはできました。

miyohide.hatenablog.com

今回は、Azure Web Appsへのデプロイを自動化します。

これまでの内容は以下を参照してください。

参考となる記事

何か参考になる記事はないものかと探していたら、マイクロソフトが以下の記事を公開していました。

docs.microsoft.com

この中でも、Azure Container RegistryのWebHookの機能がお手軽にできそうです。早速やってみます。

WebHookを作成する

上記の記事の通りに以下のコマンドをCloud Shellで実行します。

ci_cd_url=$(az webapp deployment container config --name <app-name> --resource-group <group-name> --enable-cd true --query CI_CD_URL --output tsv)

az acr webhook create --name <webhook-name> --registry <registry-name> --resource-group <group-name> --actions push --uri $ci_cd_url --scope '<image>:<tag>'

scopeの部分に何を設定すれば良いかわかりませんでしたが、image名:*で任意のタグでWebHookが起動するようです。

docs.microsoft.com

実際に作成してみると、以下のようにWebHookが作成されました。

f:id:miyohide:20210801140411p:plain

新しいバージョンにならない?

早速、新しいバージョンを作成してpushします。WebHookのログをみると、新しいバージョンを検知しているのですが、アプリは最新版になっていませんでした。

f:id:miyohide:20210801141236p:plain

Web Appsのデプロイログを見ると、WebHookの起動時刻である13:25(JST)(黒い画面では04:25(UTC))前後にDockerイメージが最新版かどうか見にいっているのですが、タグが古いままになっています(Web Appsのデプロイログでは0.0.14をみているが、WebHookでは0.0.15)。

f:id:miyohide:20210801141815j:plain

Azure Container Registryにpushしたときに発行されるWebHookにtagもついているのでAzure Web Apps側で見れないことはないと思うのですが、今のところ挙動としてはWebHook内のtagを反映してくれないようです。

docs.microsoft.com

対策

ということで、対策です。GitHub Actionsでpushしているバージョン番号付きのDockerイメージとは別にlatestとtagをつけたものを作成・pushすることにします。Azure Web Apps側ではlatestを見るようにします。

GitHub Actionsでの記述

GitHub Actionsでは以下の記述を追記します。

# 省略
# これまで設定していたバージョン番号付きのDockerイメージの生成
docker build -f Dockerfile.prd -t ${{ secrets.REGISTRY_SERVER }}/rails_template_sqlite3:$IMAGE_TAG .
docker push ${{ secrets.REGISTRY_SERVER }}/rails_template_sqlite3:$IMAGE_TAG
# latestタグをつける
docker tag ${{ secrets.REGISTRY_SERVER }}/rails_template_sqlite3:$IMAGE_TAG ${{ secrets.REGISTRY_SERVER }}/rails_template_sqlite3:latest
# latestタグをpushする
docker push ${{ secrets.REGISTRY_SERVER }}/rails_template_sqlite3:latest
# 省略

Azure Web Apps側の設定

タグをlatestに設定します。

f:id:miyohide:20210801142535j:plain

この時点で、Azure Container RegistryのWebHookが新しく作られました。先に作った二重起動になるので削除しておきます。

f:id:miyohide:20210801142736p:plain

再検証

ここまでできたので、再度新しいバージョンを作成して実行してみます。すると、Dockerイメージがpushされた時点でWebHookが起動されます。

f:id:miyohide:20210801142918p:plain

数秒後に、Azure Web Appsにおいて新しいバージョンがデプロイされたことを検知してイメージをpullしてくれました。

f:id:miyohide:20210801143054j:plain

もちろん、アプリも新しいバージョンに置き換わりました。

Azure Web Appsお勉強メモ(5)Azure Web AppsにてデプロイしたDockerイメージにSSH接続する

はじめに

先日からAzure Web AppsにRailsアプリを動かすことをやっています。昨日のエントリーでAzure Web Apps上でRailsアプリを動かす方法を記しました。

miyohide.hatenablog.com

無事、動かすことができたのですがデバッグなど何かとSSHができた方が嬉しいのでSSH接続する方法を記します。

昔「infrastructure as codeとかでマシンにSSHログインしたら負けと思え」と言われたことがあるのですが、あまり気にしないことにします。

これまでの内容は以下を参照してください。

参考となる資料

マイクロソフトが公開している以下のドキュメントに「SSHを有効にする」という記述があるのでこれを参考にします。

docs.microsoft.com

上記ドキュメントの記述内容はapkコマンドを使っていることからAlpine LinuxベースのDockerイメージを使ったものなので、バージョン番号しか書かれていなかったり、-slimとついているDockerイメージを使っている場合は若干コマンドが異なります。昨日のエントリーでの例もruby:3.0.2のDockerイメージを使っているので、上記のドキュメントから若干修正が必要となります。

設定

やるべきことは以下の5点です。

  • openssh-serverをインストールする
  • パスワードを変更する
  • SSH設定ファイル(sshd_config)を作成し、/etc/ssh/以下に格納する
  • SSHサーバーを起動する
  • ポート番号2222を開ける

一個ずつやっていきます。

openssh-serverをインストールする

Dockerfile内で以下の記述を追加するだけです。

RUN apt-get update && apt-get install -y openssh-server

パスワードを変更する

これはマイクロソフトが公開しているドキュメントに書いてあるコマンドをそのまま実行します。具体的にはDockerfile内で以下の記述を追加します。

RUN echo "root:Docker!" | chpasswd

SSH設定ファイル(sshd_config)を作成し、/etc/ssh/以下に格納する

これもマイクロソフトが公開しているドキュメントと同じようにDockerfileに記述します。プロジェクトのルートにsshd_configを作成し、中身をマイクロソフトが公開しているドキュメントからコピペ。Dockerfile内で以下の記述を追加します。

COPY sshd_config /etc/ssh/

SSHサーバーを起動する

Dockerfile内のENTRYPOINTで指定したシェルスクリプトentrypoint.shに以下の記述を追加します。

service ssh start

ポート番号2222を開ける

ポート番号2222をDockerfile内のEXPOSEに追記します。元々は

# 変更前
EXPOSE 3000

となっていたのを以下のようにするだけです。

# 変更後
EXPOSE 3000 2222

実行

ここまで設定できたら、あとはDockerイメージを作成してAzure Web Appsにデプロイします。デプロイが完了したら、Azureポータルから「開発ツール」の「SSH」から「移動」をクリックします。

f:id:miyohide:20210725163914p:plain

すると別のタブが開いて、SSH接続できます。

f:id:miyohide:20210725164124p:plain

Dockerイメージ内に入っているだけなので、ディレクトリ構成もDockerイメージと同じです。

f:id:miyohide:20210725164329p:plain

Azure Web AppsでRails 6.1アプリをproduction環境で動かす(2021年7月版)

はじめに

Azure Web Appsの勉強をしているときに、実際に動かすアプリが欲しかったのでRailsでアプリを動かそうとしたら微妙にハマったので備忘録として記します。

前提事項

RubyRailsのバージョンは以下のバージョンで検証しました。

Azure Web AppsはRubyを動かす環境が用意されていますが、実際に動くバージョンが2021年7月24日時点で2.6と古いです。

f:id:miyohide:20210724210055p:plain

最新版で動かそうとしたらDockerイメージを動かす方が良いでしょう。

docs.microsoft.com

Dockerfileを作成する

Dockerfileの書き方のサンプルはDockerのドキュメントとして以下に記述があるのですが、これも扱っているバージョンが古いです。

docs.docker.jp

今はWebpackerを使う関係上Node.jsが必要なのですが、Node.jsが必要なのはイメージを作成するだけなのでマルチステージビルドという機能を使います。

docs.docker.jp

結果として、以下の記述となりました。

FROM node:14.17.0-slim as node
FROM ruby:3.0.2

# NodeとYarnのインストール
ENV YARN_VERSION 1.22.5
RUN mkdir -p /opt

COPY --from=node /opt/yarn-v$YARN_VERSION /opt/yarn
COPY --from=node /usr/local/bin/node /usr/local/bin/
COPY --from=node /usr/local/lib/node_modules/ /usr/local/lib/node_modules/
RUN ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \
  && ln -s /opt/yarn/bin/yarn /usr/local/bin/yarnpkg \
  && ln -s /usr/local/bin/node /usr/local/bin/nodejs \
  && ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \
  && ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npx

WORKDIR /app

COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
COPY yarn.lock /app/yarn.lock
# developmentとtestのgemはインストールしない
RUN bundle config set --local without 'development test'
RUN bundle install
RUN yarn install

COPY . /app

RUN RAILS_ENV=production bin/rails assets:precompile

ENV RAILS_ENV=production

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD [ "rails", "server", "-b", "0.0.0.0" ]

許可するホスト名の設定

上記でRailsアプリをAzure Web Apps上で動かそうとするとBlocked host:と書かれたエラーメッセージが出ます。対応としては、以下のドキュメントにあるようにconfig.hostsにAzure Web Appsのドメインを追加するだけです。

guides.rubyonrails.org

具体的には、config/environments/production.rbRails.application.configure doの内側に以下の記述を追加します。

config.hosts << ".azurewebsites.net"

最初にピリオドをつけることで、すべてのサブドメインを許可することができます。

環境変数の設定

環境変数の設定も必要です。今回設定したのは以下のものです。

  • RAILS_LOG_TO_STDOUT
    • ログを標準出力に出力する。値は1でもtrueでも何でも良い。設定されていることが大事。
  • RAILS_MASTER_KEY
    • credentialファイルのマスターキー。ローカルにあるconfig/master.keyの中身の値を設定する。
  • RAILS_SERVE_STATIC_FILES
    • Railsに静的ファイルの配信をお願いする。値は1でもtrueでも何でも良い。設定されていることが大事。
  • WEBSITES_PORT
    • Railsアプリが開いているポート番号3000を指定。

少しハマったのは、RAILS_MASTER_KEYの設定です。これを設定してなかったので、アプリにアクセスしたときにAn unhandled lowlevel error occurred. The application logs may have details.と出てしばらく悩みました。credentialの設定はRails 4.1ぐらいからいろいろと変更されていたので、最新のRailsではどのような設定をするかよくわかりませんでした。

ここら辺は以下のRails Guideを参照するか

railsguides.jp

パーフェクトRuby on Rails 【増補改訂版】のP152ぐらいからの記述に詳しく書かれていますので、参照されることをお勧めします。

またWEBSITES_PORTは以下のドキュメントには指定する必要がある旨が書かれているので設定していますが、私の場合、設定しなくても動くことが多いです。必要な場合と不要な場合の条件についてはよくわかっていません。

docs.microsoft.com

結果としてAzure Web Appsの「アプリケーション設定」は以下のようになりました。

f:id:miyohide:20210724213006p:plain

上記の設定でRails 6.1で作られたアプリをAzure Web Appsで動かすことができました。

AWS DevAx::connect シーズン1「イベント駆動」が面白い

2021年6月よりAWSがDexAx::connect シーズン1「イベント駆動」というWebセミナーが開催しています。

pages.awscloud.com

毎週木曜日に2時間ほどの時間をかけて、「イベント駆動」を掘り下げて解説されているセミナーです。

この記事を書いている2021年7月23日時点ですでに6回のセッションが開催されていますが、過去のセッションはすべて動画&資料公開されていて、あとで見直すことができるものとなっています。

イベント駆動とは?

本Webセミナーの案内をいただいたとき『「イベント駆動って?」って何?』と思ったのが正直なところでした。少し調べたところ、AWSが以下のようなドキュメントを出しています。

aws.amazon.com

最初の一文に

An event-driven architecture uses events to trigger and communicate between decoupled services and is common in modern applications built with microservices.

とあるので、最近何かと話題なマイクロサービスでシステムを設計する上で欠かせないアーキテクチャのようです。

本当はこれを読み込んでから参加しようと思ったのですが、英語ということもあり、あまり読まずにとりあえず第1回のWebセミナーを受けました。

詳細は、上記イベントページから参加登録して過去発表を参照してほしいのですが、

  • ドメイン駆動設計の紹介
  • イベントの紹介
  • 分散システムにおける課題
  • 非同期化による応答性の改善と依存性の削減
  • イベント駆動デザインパターンの紹介と実装例
  • イベントドリブンアーキテクチャ選択における観点
  • etc

と盛りだくさん。2時間って長いなと思っていたのですが、質疑応答含めあっという間に見終えました。

その後もどんどん深掘り

仕事柄、数多くのセミナーを勉強がてら受けるのですが大抵2時間という枠でも用語定義や概要だけ伝えて終了となるものが多いと感じています。 それはそれで有益なのですが、実際に案件適用をしようとすると早々により深掘りした知識を求められることになります。

このセミナーは毎週2時間の枠で一つのテーマをじっくりと深掘りされるので、色々な観点から考えるきっかけとなります。当日の資料だけでなく動画も公開されるので後でじっくり見直すことができます。

例えば第2回は『「疎結合」を実現するメッセージングサービスの選択と利用』と題して数あるAWSのサービスの中から何をどのような観点で選べばいいのかということがわかりますし、第6回は『How to Test your Events?』と題してテストの方法についてじっくり解説していただいています。

クラウド上でシステム設計に携わる方は聴講するとよいWebセミナーだと感じています。

Azureリソースのネーミングルールのベストプラクティス

今日は小ネタ。ちょっとやっていたことがうまくいかなかったので小ネタに逃げます。

はじめに

Azure上で仮想マシンとかWebアプリとかを作っている際には名前をつける必要がありますが、適当に名前をつけると後で「この仮想マシンって何のために作ったんだっけ?」と分からなくなります。

そのためにネーミングルールを設けることが多いのですが、こんなもの誰かが整理しているでしょと思い色々と探していたら、マイクロソフトが公開していたので紹介します。

マイクロソフトが公開しているネーミングルール

その公開しているネーミングルールは以下のもの。

docs.microsoft.com

リソースの種類やアプリケーション名などを要素ごとに"-"で繋げる形ですね。なんとなくハンガリアン記法に似ている感じがします。

リソースの種類を表す省略形については以下のドキュメントを参照すると良いでしょう。

docs.microsoft.com

あとはこれに従ってリソースを作ればOK。ただ、az cliとかでリソースを作成するときにデフォルト値はこのネーミングルールに従ったリソースを作ってはくれないので、そこはちょっと注意かもしれません。

Azure Web Appsお勉強メモ(4)Azure Web AppsにてデプロイするDockerイメージをAzure DevOpsで生成してAzure Container Registryに登録する

はじめに

先日からAzure Web AppsにRailsアプリを動かすことをやっています。動かすことは簡単にできたのですが、色々と手作業が多かったのでちょっとでも自動化しようと試してみました。前回はGitHub Actionsを使ってやりましたが、最後のWebAppsへの反映がうまくできなかったので、今回は手を変えてAzure DevOpsを使ってみることにしました。ほら、同じマイクロソフトのプロダクトならいい感じに連携できているのかなと(GitHubマイクロソフト傘下とか...いやなんでもないです)。

これまでの内容は以下を参照してください。

Azure DevOpsとは

開発に必要な各種ツールをまとめて提供して、かつ無料から使い始めることができるサービスです。GitリポジトリやCI/CD基盤を持っています。詳細は以下を参照。

azure.microsoft.com

GitHub Actionsでも同様のことができますが、Azure DevOpsではサービスプリンシパルを明示的に用意する必要がなく、Service Connectionsを画面上で設定しておけば簡単に接続できます。

docs.microsoft.com

今回、きっと連携がうまいことできるであろうAzure DevOpsを使ってAzure Container Registoryにイメージをpushし、Azure Web Appsへのデプロイをしてみることにしました。

Docker Imageを作成してAzure Container Registoryにpushする

Azure DevOpsでCI/CDの機能を提供するのはAzure Pipelinesです。これを使うには、リポジトリazure-pipelines.ymlを記述します。

docs.microsoft.com

YAMLファイルを書くのは色々と調べないと大変なのですが、Azure Pipelines内では初回作成時におすすめの構成を提示してくれたりします。

f:id:miyohide:20210711181212p:plain

また、オンラインエディターがかなり充実しているので、それを利用するとあまり苦しまなくても実装できました。

docs.microsoft.com

今回、実装したazure-pipelines.ymlは以下の通り。

trigger:
- master

pool:
  vmImage: ubuntu-latest

steps:
- task: Gradle@2
  inputs:
    workingDirectory: ''
    gradleWrapperFile: 'gradlew'
    gradleOptions: '-Xmx3072m'
    javaHomeOption: 'JDKVersion'
    jdkVersionOption: '11'
    jdkArchitectureOption: 'x64'
    publishJUnitResults: true
    testResultsFiles: '**/TEST-*.xml'
    tasks: 'bootBuildImage'  # Spring BootでのDockerイメージ作成コマンド

- task: Docker@2
  inputs:
    containerRegistry: 'acr'    # service connectionの設定名
    repository: 'webapp'  # イメージ名
    command: 'push'
    tags: 'latest'

ここでは、Azure Web Appsへのデプロイは行いません。

Azure Web Appsへデプロイをする

できたDockerイメージをAzure Web Appsへデプロイするには、Azure Pipelinesのリリース機能を使います。Azure Pipelinesでもできそうですが、思想的にはリリース機能を使った方が良いかなと感じました。

docs.microsoft.com

以下のドキュメントにあるように、Azure Container Registryもトリガーにできそうです。

docs.microsoft.com

あらかじめデプロイ先のAzure Web Appsを作っておけば、項目をそれぞれ選択すれば設定は終わります。

f:id:miyohide:20210711183142j:plain

実際動かしてみると無事デプロイできたみたいです。

f:id:miyohide:20210711183246p:plain

Azure Web Apps上のデプロイセンターで確認してもAzure Pipelinesの内容が反映されました(デプロイ後すぐというわけではなく、5分ぐらい時間がかかりました)。

f:id:miyohide:20210711184943p:plain

ですが、実際にアプリにアクセスしてみるとアプリが動いていません。

f:id:miyohide:20210704164525p:plain

ログを見てみると、やはりDockerイメージの取得に失敗しているみたいです。

2021-07-11T08:12:25.960Z ERROR - DockerApiException: Docker API responded with status code=InternalServerError, response={"message":"Get xxxxxxxxxxxxxxxxxxxxx: unauthorized: authentication required, visit https://aka.ms/acr/authorization for more information."}
2021-07-11T08:12:25.963Z ERROR - Image pull failed: Verify docker image configuration and credentials (if using private repository)
2021-07-11T08:12:25.965Z INFO  - Stopping site miyoshisbapp because it failed during startup.
2021-07-11T08:15:46.854Z INFO  - Pulling image from Docker hub: miyohideacr.azurecr.io/webapp:latest

う〜んなんでだろう。

環境変数が設定されていない

色々と原因を探していたときに、ふと「アプリケーション設定」の「DOCKER_」で始まる環境変数の値を見てみると、適切な値が設定されていないことがわかりました。下図は「DOCKER_REGISTRY_SERVER_USERNAME」の値を見ていますが、何も値が設定されていません。

f:id:miyohide:20210711183820p:plain

なんじゃそら...と思いつつ、Azure Container Registryの管理者アカウントを有効にして「DOCKER_」の各種値を設定しておきます。

docs.microsoft.com

  • DOCKER_CUSTOM_IMAGE_NAME → デプロイしたいDockerイメージ名
  • DOCKER_REGISTRY_SERVER_PASSWORD → Azure Docker Registryの管理者アカウントのパスワード(どちらでもOK)
  • DOCKER_REGISTRY_SERVER_URL → https://名前.azurecr.io
  • DOCKER_REGISTRY_SERVER_USERNAME → Azure Docker Registryの管理者名

これを設定して、リロードするとアプリが動くことが確認できました。

再度Azure DevOpsで再度デプロイしても上記の環境変数が上書きされることはありませんでした。

ちなみに

Azure Web Apps for ContainerにてAzure Container Registryを参照する際、Admin権限が必要な状況については、以下のFeedbackが出ていて現在開発中のようです。

started
We welcome user feedback and feature requests!
  • 108 votes
  • 13 comments

Web App for Containers - ACR access requires admin account enabled on repository

It looks as though Web App for Containers requires the use of the admin account on the repository in ACR.

The notes on use of the admin account suggest to use that account only for testing purposes and describe some of the downsides to having it enabled.

Is there a plan to support Serv...

feedback.azure.com

Ruby/Railsの情報の探し方(2021年7月版)

はじめに

少し前に「技術系の情報をどう探すか」ということが私の周りで話題となりました。その場では「検索」が第一候補として上がったのですが、「なんかヒットしないんだよねぇ。」ということになりました。それはそれで正しいと思うのですが、世の中もっと信頼できる情報ソースがあるのにもったいないと思っています。ただその場ではうまく整理できなかったので、個人的にやっているRuby/Railsの情報の探し方を記します。

結論

はじめに結論ぽいものを。

  • 書籍は持っておく
  • RailsについてはRuby on Railsガイド
  • 細かいAPIの使い方などはgem serverでGemのRDocを見る
  • 公式サイト/Gemのソースが置いているGitHubに目を通す
  • やってみる
  • 最後に検索

書籍について

RubyRailsについては、日本語での情報がオンラインでも書籍でもたくさん出ています。個人的には「パーフェクト」シリーズを手元に置いていつでも目を通せるようにしています。

紙でも電子書籍でもどちらでもお好みで。

RailsについてはRuby on Railsガイド

体系的にRailsを学ぶのであればRuby on Railsガイドがよいと思います。はじめのうちは頭から読んでおくと良いかなと思います。

railsguides.jp

細かいAPIの使い方はgem server

細かいAPIの使い方はgem serverでドキュメントサーバーを立てておくところからスタートします。

guides.rubygems.org

あとはブラウザでlocalhost:8808にアクセスして調べます。

f:id:miyohide:20210707205820p:plain

個人的に良くやるのは、Railsでformを書くときにclass属性ってどうやって書くんだっけ?というときに調べます。この場合はactionview gemのActionView::Helpers::FormBuilderを見ればOK。ここら辺はある程度の経験が必要かもしれません。

f:id:miyohide:20210707210502p:plain

公式サイト/Gemのソースが置いているGitHubに目を通す

RubyならRubyの公式ページにあるドキュメントページからリンクが貼ってあるリファレンスマニュアルをみます。

www.ruby-lang.org

Gemでしたら、ソースが置いてあるGitHubの特にReadmeには目を通しておくとやりたいことが書かれていることが多いです。具体的にはRubyGemsにて調べたいGemのページを見つけ、「ホームページ」や「ソースコード」に書かれているページを見ると該当のものが見つかると思います。

f:id:miyohide:20210707212024p:plain

やってみる

私はドキュメントに書いてあることを読んだだけで理解できる人ではないので、たいてい手を動かしてみることにします。Rubyにはirbというコマンドがあるので、ちょっとしたお試しで処理内容を確認するにはいいかなと思います。

docs.ruby-lang.org

最後に検索

ここまでやっても見つからなかった場合は検索で。キーワードが悩みの種ですが、ここまで来ると自分がやりたいことが整理できていて、情報も探しやすいのかなと思ったりします。