App Service for Linux の Node.js ランタイムでサポートされていないバージョンを実行してみる

2022.11.06

いわさです。

Azure App Service では Node.js ランタイムを選択することが出来ます。
その際にバージョンを指定することが出来るのですが現状は以下がサポートされています。

% az webapp list-runtimes --os-type=linux
[
  "DOTNETCORE:7.0",
  "DOTNETCORE:6.0",
  "DOTNETCORE:3.1",
  "NODE:18-lts",
  "NODE:16-lts",
  "NODE:14-lts",
  "PYTHON:3.10",
  "PYTHON:3.9",
  "PYTHON:3.8",
  "PYTHON:3.7",
  "PHP:8.1",
  "PHP:8.0",
  "PHP:7.4",
  "RUBY:2.7",
  "JAVA:17-java17",
  "JAVA:11-java11",
  "JAVA:8-jre8",
  "JBOSSEAP:7-java11",
  "JBOSSEAP:7-java8",
  "TOMCAT:10.0-java17",
  "TOMCAT:10.0-java11",
  "TOMCAT:10.0-jre8",
  "TOMCAT:9.0-java17",
  "TOMCAT:9.0-java11",
  "TOMCAT:9.0-jre8",
  "TOMCAT:8.5-java11",
  "TOMCAT:8.5-jre8",
  "GO:1.19",
  "GO:1.18"
]

上記のように LTS を指定出来るのですが、対象メジャーバージョンの中の最新バージョンが利用出来るというわけではなさそう。
App Service for Windows の場合は v18.3.0 で、 App Service for Linux の場合は v18.2.0 でした。

マネージドコンテナで動作するのでマイナーバージョンはおまかせするべきだと思いつつも、無理やり上げてみました。 サポート対象云々も無視です。動作検証も十分しているわけではなくアップグレードのアプローチとして出来るのかどうか試してみたという内容です。

サンプルアプリの用意

サンプルの Node.js アプリケーションは Microsoft 公式ドキュメントでも案内されています。

% npx express-generator myExpressApp --view ejs
Need to install the following packages:
  express-generator
Ok to proceed? (y) 
npm WARN deprecated mkdirp@0.5.1: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)

   create : myExpressApp/
   create : myExpressApp/public/
   create : myExpressApp/public/javascripts/
   create : myExpressApp/public/images/
   create : myExpressApp/public/stylesheets/
   create : myExpressApp/public/stylesheets/style.css
   create : myExpressApp/routes/
   create : myExpressApp/routes/index.js
   create : myExpressApp/routes/users.js
   create : myExpressApp/views/
   create : myExpressApp/views/error.ejs
   create : myExpressApp/views/index.ejs
   create : myExpressApp/app.js
   create : myExpressApp/package.json
   create : myExpressApp/bin/
   create : myExpressApp/bin/www

   change directory:
     $ cd myExpressApp

   install dependencies:
     $ npm install

   run the app:
     $ DEBUG=myexpressapp:* npm start

% cd myExpressApp && npm install

added 54 packages, and audited 55 packages in 2s

1 critical severity vulnerability

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
% DEBUG=myexpressapp:* npm start

> myexpressapp@0.0.0 start
> node ./bin/www

  myexpressapp:server Listening on port 3000 +0ms
GET / 200 8.176 ms - 207
GET /stylesheets/style.css 200 4.115 ms - 111
GET /favicon.ico 404 7.196 ms - 1223

http://localhost:3000 へアクセスします。

普通に確認

サーバー環境の Node.js バージョンを確認出来る状態にして App Service for Linux へデプロイしてみたいと思います。

myExpressApp/views/index.ejs

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1><%= title %></h1>
    <p>Welcome to <%= title %></p>
    <p><%= process.version %></p>
  </body>
</html>

作成時のランタイムは Node 18 LTS です。

Visual Studio Code のデプロイ機能でサッとデプロイ出来ます。
このあたり本当に楽です。

デプロイ出来たらアクセスしてみましょう。

v18.2.0 でした。

2022 年 10 月に v18.12.0 でコードネーム「Hydrogen」の長期サポート (LTS) が開始されたので v18.12.0 以降を使いたいところです。

パラメータでどうにかやってみるが出来ない

App Service のドキュメントでは以下のコマンドで細かいバージョンを指定出来るとされています。
こちらを使うと環境変数が設定されます。

% az webapp config appsettings set -g 20221106 -n hoge1106node --settings WEBSITE_NODE_DEFAULT_VERSION=18.12.0
[
  {
    "name": "WEBSITE_NODE_DEFAULT_VERSION",
    "slotSetting": false,
    "value": "18.12.0"
  }
]

が、このパラメータは App Service for Linux ではサポートされていないようでした。

ちなみに App Service for Windows でもサポートされていないマイナーバージョンを指定することは出来ませんでした。
指定した上で追加の手順が必要なのかもしれませんが、Linux でそもそもサポートされていないようなのでこの方向での検討はやめました。

スタートアップスクリプトで無理やりやる

App Service for Linux はマネージドコンテナでアプリケーションが実行されるのですが、スタートアップコマンドを指定することが出来ます。
こちらを利用して PHP 8 ランタイムで Niginx のデフォルトドキュメントをカスタマイズする方法を以前紹介したことがあります。

本日は同じようにスタートアップコマンドを利用し、Node.js のバージョンを変更してみます。

スタートアップ用のスクリプトファイルを用意します。
導入方法は色々あると思うのですが、ここでは簡単な n を使って stable をインストールしてみます。

hoge.sh

npm install -g n
n stable
npm start

このファイルをデプロイモジュールに含めて、App Service のアプリケーション設定からスタートアップコマンドとして指定します。

デプロイ出来たらアクセスしてみましょう。

本日時点の LTS である v18.12.1 が適用されていました。

さいごに

本日は App Service for Linux の Node.js ランタイムでサポートされていないバージョンを実行してみました。

対応はしてみましたが、とりあえずバージョンアップしただけで動作検証などは不十分です。
アプリケーションが立ち上がるごとにバージョンアップを行うことになるのでそのあたりのオーバーヘッドが気になります。

また、そもそもサポートされていないランタイムを使いたい場合はカスタムコンテナを導入するべきかなという所感です。