Azure Functionsのお勉強メモ(4)RubyでHTTP Triggerを実装する

最近、Azure Functionsのお勉強をチマチマと始めました。色々と分からないことが多かったのでお勉強メモをまとめて記します。

どこまで続くかわからないお勉強メモ。今日は4回目です。今回はRubyです。過去のものは以下を参照。

Azure Functions上のアプリをRubyで作る

Azure Functionsでサポートしている言語は2021年3月末現在、以下のものに限られています。

詳細は以下のドキュメントに書かれています。

docs.microsoft.com

自分が得意なRubyが入っていない...。ただ、Dockerを使えば動かせるというようなことが以下のドキュメントに書かれています(ドキュメントはR言語の例)。

docs.microsoft.com

ここでは、Rubyで動くように実装してみることにします。

プロジェクトの作成と設定

とは言っても、ほとんど上のドキュメントに書かれていることを実行するだけです。

func initコマンドでプロジェクトを作成します。

func init プロジェクト名 --worker-runtime custom --docker

これでプロジェクト名のディレクトリが作成されるので、そのディレクトリに移動後、func newで関数の設定ファイルであるfunction.jsonを作成します。

cd プロジェクト名
func new --name Hello --template "HTTP trigger"

これでHelloディレクトリにfunction.jsonが生成されます。

function.jsonを開き、"authLevel"の値を"anonymous"に変えておきます。これはAPIアクセスの時にAPIキーを求めるかどうかの設定です。詳細は以下のドッキュメントにあるauthLevelの項を参照してください。

docs.microsoft.com

最後にhost.jsonの設定をします。"customHandler"の部分を以下のように修正します。

  "customHandler": {
    "description": {
      "defaultExecutablePath": "ruby",
      "workingDirectory": "",
      "arguments": ["app.rb"]
    },
    "enableForwardingHttpRequest": true
  }

私は"enableForwardingHttpRequest"の記述をすっかり見落としており、うまく動かなくてかなり悩みました。この項目の意味は以下のドキュメントを参照すると良いと思います。

docs.microsoft.com

アプリの実装

アプリはSinatraを使って実装します。リクエストがあったらテキストを返すだけの簡単なものでしたらRailsよりもSinatraのほうが楽でしょう。実装もこれだけです。

require 'sinatra/base'

class MyApp < Sinatra::Base
  configure do
    set :environment, :production
    set :port, ENV['FUNCTIONS_CUSTOMHANDLER_PORT']
  end
  get '/api/Hello' do
    'Hello Ruby World'
  end

  run! if app_file === $0
end

:portでリクエストを受け付けるポートを環境変数FUNCTIONS_CUSTOMHANDLER_PORTで指定する必要があるのが注意点といえば注意点かと思います。

Gemfileの準備

Gemfileにて利用するライブラリを記述します。単純なSinatraの機能しか使わないので、以下の記述になります。

source "https://rubygems.org"

gem 'sinatra', '~> 2.1.0'

Dockerfileの準備

ドキュメントによればAzure Functionsの環境として作成するにはベースイメージとしてmcr.microsoft.com/azure-functions/dotnet:3.0-appserviceを使う必要があるとのこと。

docs.microsoft.com

イメージの実装はこのリポジトリのようです。

github.com

Rubyを動かすためにはいろいろな方法があるかと思いますが、手っ取り早くまずはapt-get install rubyでインストールしてみます。ここでインストールされるRubyは2.5系だったので、gem i bunderも実行しています。

FROM mcr.microsoft.com/azure-functions/dotnet:3.0-appservice
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true

RUN apt update && \
    apt install -y \
    ruby \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /home/site/wwwroot

RUN gem install bundler --no-doc

COPY Gemfile /home/site/wwwroot/
RUN bundler install
COPY . /home/site/wwwroot/

実行

後は、docker buildでDockerイメージを作成し、docker runで動かした後にhttp://localhost:8080/api/Helloにアクセスすると、Hello Ruby Worldという文字列がブラウザ上に表示されます。

f:id:miyohide:20210404175651p:plain

コンソールログには以下のような文字列が出力されていました。Sinatraが出力しているログがfailになっているのがちょっと気になりますが、とりあえず動いているようです。

      Host lock lease acquired by instance ID '000000000000000000000000714A9D2E'.
info: Function.Hello[1]
      Executing 'Functions.Hello' (Reason='This function was programmatically called via the host APIs.', Id=66a1a41b-2d0c-4277-90d3-a5ef3990be81)
fail: Host.Function.Console[0]
      127.0.0.1 - - [01/Apr/2021:11:40:05 +0000] "GET /api/Hello HTTP/1.1" 200 16 0.0004
fail: Host.Function.Console[0]
      127.0.0.1 - - [01/Apr/2021:11:40:05 UTC] "GET /api/Hello HTTP/1.1" 200 16
fail: Host.Function.Console[0]
      - -> /api/Hello
info: Function.Hello[2]
      Executed 'Functions.Hello' (Succeeded, Id=66a1a41b-2d0c-4277-90d3-a5ef3990be81, Duration=66ms)

f:id:miyohide:20210404175720p:plain

Azure上で動かす

Azure上で動かしてみます。Dockerイメージをdocker pushでDocker Hubに格納したのち、Azure上で動かします。Azure Portal上で「関数アプリ」に必要な項目を入力し、作成。作成後、「デプロイセンター」から「完全なイメージの名前とタグ」を指定して保存すればAzure上で動かすことができました。

f:id:miyohide:20210404180822j:plain

ソース

現時点でのソースです。

github.com