Quantcast
Channel: ほりひログ
Viewing all articles
Browse latest Browse all 44

Azure Container AppsでオレオレCodespacesを作る

$
0
0

GitHub Codespaces便利。

そんな便利なGitHub Codespacesのオレオレ版をAzure Container Appsを使って作ってみた。

GitHub Codespaces自体のソースコードは公開されていないので、code-serverというオープンソース版を使ってみる。

github.com

ちゃんとコンテナーイメージも公開されているから試すのもカンタン。

Azure Container Appsにデプロイしてみる

動かしてみるのは簡単。

Container Appリソースを作ってコンテナーイメージの設定に👆で公開されているイメージを設定して、ターゲットポートに8080を設定するだけ。

Container Appリソース作成&コンテナーイメージ設定

コマンドだとこれ一発であっさり起動する。

az containerapp create \
  --name $CONTAINERAPPS_NAME --resource-group $RESOURCEGROUP_NAME \
  --environment $ENVIRONMENT_NAME --ingress external \
  --image docker.io/codercom/code-server:$TAG --target-port 8080

Container AppリソースができたらURLにアクセスしてみると起動したのがわかる。

パスワード認証を無効にする

デフォルトでパスワード認証が有効なので、必ず認証画面 /loginにリダイレクトされ、パスワード入力画面が表示される。
このパスワード認証は無効にできるので、Azure Container Apps自体の認証機能など別の仕組みで認証する場合は無効にした方がいい。

無効の仕方は、

  1. 👆のスクショに書かれている設定ファイル /home/coder/.config/code-server/config.yamlに書く
    or
  2. コンテナーの起動時にオプションとして渡す

のどちらか。

設定ファイルはコンテナの一部になっていて、サクッと試すには手間なので、今回はコンテナー起動時にオプションを使ってみる。

以下のコマンドで組み込み認証を無効にする。

az containerapp update \
  --name $CONTAINERAPPS_NAME --resource-group $RESOURCEGROUP_NAME \
  --args="--auth=none"

これでお馴染みの画面が出てくる。

--argsオプション追加の顛末はこちら割とハマったのが--argsオプションの追加。

他のコマンド同様 --args "--auth=none"とみたいにスペースで区切ると、--authの方も別オプションとして認識されてしまい「そんなオプションはない」と怒られる。

あと--auth=noneの方も、ローカルのDockerで試した時は--auth noneとスペース区切りで指定しても問題なくパスワード認証が無効にできたけど、Container Appリソース上のコンテナー起動の引数として渡す時は=で繋げないとダメだった。

いくつかパターンを試した結果、--args="--auth=none"に落ち着いた。
引数の処理が違うんだろうか。

このあともう一回ハマる。

code-serverコンテナーを増やしてみる。

想定しているのは、複数のユーザーが同時に使うシーン。
なので、増やすといってもスケールアウトさせるのではなく、Container Appsリソースを増やして、そのユーザー専用code-serverにする、という構成。

参考にするのはこの公式ブログ。

techcommunity.microsoft.com

このブログで紹介されている下図の構成、

https://techcommunity.microsoft.com/t5/image/serverpage/image-id/556918i3D08A0DC4DDC2FF5/image-dimensions/2500?v=v2&px=-1

この図のフロントエンド(nginxを動かすContainer Appリソース&ingressはexternal)はそのまま拝借。
その後ろのバックエンドapp1appNのContainer Appリソース(ingressはinternal)がcode-server1~code-serverNになり、それぞれユーザー毎のcode-serverが動く感じ。

WebSocketが動かない???

👆のブログ内に構成する手順が書いてあるので、まずはこれを参考にフロントエンドのnginxの設定を試してみる。

events {
}

http {
    server {
        listen 80;
        location /code-server1/ {
            proxy_http_version 1.1;
            proxy_pass http://${CODE_SERVER1_NAME}/;
        }
    }
}

フロントエンドの/code-server1/というパスへのリクエストを、バックエンドのContainer Appリソース${CODE_SERVER1_NAME}フォワードする、いわゆるリバースプロキシ用設定。
これをフロントエンドのContainer Appリソースのnginxに適用して、実際にアクセスしてみると、、、

はい、エラー。ですよね。
そう簡単にいかないのは重々承知。

エラーメッセージはWebSocketが繋がっていない、って言ってるので、「nginx リバースプロキシ websocket」で検索。
出てくる情報は「nginxでクライアントとバックエンドのWebSocket通信を仲介する時はリクエストヘッダーを追加しよう」的なもの。

これを基にnginx.confを修正したのがこちら。

events {
}

http {
    server {
        listen 80;
        location /code-server1/ {
            proxy_http_version 1.1;
            proxy_pass http://${CODE_SERVER1_NAME}/;
            # 以下を追加
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        }
    }
}

${CODE_SERVER1_NAME}はバックエンドのContainer Appリソース名に適宜置き換えてもらって。

追加したのはUpgradeConnectionのヘッダー。
これでうまくいけば、と祈りつつ再びアクセスしてみると、、、

ダメ。エラー変わらず。

この後「proxy_ssl_server_name on;を付けるとうまくいく」的情報を見つけて試してみるもエラーは変わらず。

いろいろ試すのに疲れたので、初心に返って「バックエンドにつながってエラーになってるのか、フロントエンドでブロックされてるのか」というところから確認。

Azure Container Appsの標準出力はAzureポータルのLog Streamで確認できるので、code-serverがデバッグログを出すよう、起動時の引数に--verboseを追加。

※再び--verbose追加の顛末はこちら--auth=none--verboseの両方を設定しないといけなかったので、まずは--args="--auth=none --verbose"とやってみたけどダメだった。

他にも、--args="--auth=none""--verbose"とか--args=["--auth=none","--verbose"]とか、雰囲気で複数指定できそうなパターンをいくつか試したものの、片方しか効かない、とか、両方とも効かない、とか。

結局az containerapp update一発でやるのは諦めて、

  1. az containerapp showでARMテンプレートを取得
  2. テンプレート内の引数 argsに相当する箇所を修正 3.az containerapp updateでテンプレートを丸ごと適用

という手順で何とかパスワード認証無効&デバッグログ出力できた。

にしても、公式ドキュメントには、

コンテナーのスタートアップ コマンド引数の一覧。 スペース区切りの値 (例: "-c""mycommand")。

とあるけど全然効かない。
未だに正しい指定方法がわからない。

learn.microsoft.com

大量に出てきたエラーがこちら。

debug host "(バックエンドのContainer App名)" does not match origin "(フロントエンドのホスト名)"; blocking request to /stable-c26ac35b25b09e9d58e6716f2aae41d8d1dfbb6c?reconnectionToken=b6a8c9eb-6f4f-448a-bb0c-faabe3efef0d&reconnection=false&skipWebSocketFrames=false

あ、originがあってない、ってことね。
ていうか、origin見てるのね。

というわけで、Originヘッダーを追加。

events {
}

http {
    server {
        listen 80;
        location /code-server1/ {
            proxy_http_version 1.1;
            proxy_pass http://${CODE_SERVER1_NAME}/;
            # 以下を追加
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            # さらに以下を追加
            proxy_set_header Origin http://${CODE_SERVER1_NAME};
        }
    }
}

${CODE_SERVER1_NAME}はバックエンドの(以下略)。

これをフロントエンドのnginxに反映すると、無事nginx経由でバックエンドのcode-serverを開くことに成功🎉🎉

やっぱりログ重要。

今後やらんといかん事

今回はとりあえず動いたことを確認したまで。

けど実際使うとしたらいろいろやること、確認すること多そう。

例えば、

  • ファイルの永続化どうする?
  • 勝手にZero scaleするんじゃない?
  • そもそもコスト的にどうなん?
  • サーバーアプリのデバッグできる?(GitHub Codespacesならできる)

などなど。

時間見つけてやっていこう。


Viewing all articles
Browse latest Browse all 44

Trending Articles