
さくらのクラウドで AppRun(β)の基本機能を使ってみた
いわさです。
先日、さくらのクラウドで AppRun へのデプロイを行いましたがうまく動きませんでした。
今回はその問題に対処し、AppRun が動作するようになったのでいくつかの基本機能を試してみましたので紹介します。
AppRun は x86_64 アーキテクチャで動作する
まず、私の用意したコンテナイメージだと起動に失敗していましたので、この問題を解決したいと思います。
前提としてコンテナイメージを用意した私のクライアントは M1 Mac です。
Apple シリコン搭載 Mac のため ARM ベースであることに注意してイメージを用意する必要があります。
一方で AppRun のアーキテクチャについは FAQ ページで言及されており x86_64 です。
よって x86 のイメージを用意する必要があります。
Apple シリコンで Docker をお使いの方はみなさんご存知だと思いますがdocker buildx
で x86 プラットフォームを指定する必要があります。
FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /source
COPY *.csproj .
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app
FROM --platform=$TARGETPLATFORM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /app .
ENV ASPNETCORE_URLS=http://+:80
EXPOSE 80
ENTRYPOINT ["dotnet", "MinimalApiServer.dll"]
% docker buildx build --platform linux/amd64 -t minimal-api-server .
[+] Building 25.1s (15/15) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 778B 0.0s
:
=> [build 6/6] RUN dotnet publish -c Release -o /app 18.1s
=> [stage-1 2/3] WORKDIR /app 0.1s
=> [stage-1 3/3] COPY --from=build /app . 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:9d0f3dbc5439c3610c51e4710524b619dbe93af5bad31625a2cdb1fc84944da3 0.0s
=> => naming to docker.io/library/minimal-api-server 0.0s
作成したイメージをコンテナレジストリにプッシュし、AppRun へデプロイしてみましょう。
すると今回はステータスが正常になりました。良かった。
失敗した環境のログなどを確認する方法がわからなかったので、当てずっぽうでまずは CPU アーキテクチャの変更からやってみましたがいきなり動作したので良かったです。
起動ログなどを確認する方法は調べてみます。コントロールパネル上で見当たらなかったです。
リクエストを送ってみます。
% curl https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast -v
* Host app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp:443 was resolved.
* IPv6: (none)
* IPv4: 219.111.240.173
* Trying 219.111.240.173:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / x25519 / id-ecPublicKey
* ALPN: server accepted h2
* Server certificate:
* subject: CN=ingress.apprun.sakura.ne.jp
* start date: Feb 12 01:15:00 2025 GMT
* expire date: May 13 01:14:59 2025 GMT
* subjectAltName: host "app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp" matched cert's "*.ingress.apprun.sakura.ne.jp"
* issuer: C=US; O=Let's Encrypt; CN=E5
* SSL certificate verify ok.
* Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384
* Certificate level 1: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
* Connected to app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp (219.111.240.173) port 443
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp]
* [HTTP/2] [1] [:path: /weatherforecast]
* [HTTP/2] [1] [user-agent: curl/8.12.1]
* [HTTP/2] [1] [accept: */*]
> GET /weatherforecast HTTP/2
> Host: app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp
> User-Agent: curl/8.12.1
> Accept: */*
>
* Request completely sent off
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
< HTTP/2 200
< content-type: application/json; charset=utf-8
< date: Sun, 23 Mar 2025 09:44:29 GMT
< server: envoy
< x-envoy-upstream-service-time: 45
< via: 1.1 sac-elb
<
* Connection #0 to host app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp left intact
[{"date":"2025-03-24","temperatureC":-2,"summary":"Mild","temperatureF":29},{"date":"2025-03-25","temperatureC":19,"summary":"Hot","temperatureF":66},{"date":"2025-03-26","temperatureC":38,"summary":"Scorching","temperatureF":100},{"date":"2025-03-27","temperatureC":22,"summary":"Bracing","temperatureF":71},{"date":"2025-03-28","temperatureC":42,"summary":"Hot","temperatureF":107}]
アプリケーションが生成したデータを取得することが出来ました。
TLSはv1.3
ですね。
.NET イメージの Web サーバーは Kestrel なのですが、このレスポンスを見る限りリバースプロキシは Envoy が使われているようです。
バージョンとトラフィック管理機能を使ってみる
無事 AppRun 上でコンテナを起動することが出来たので、コントロールパネルから確認できるいくつかの機能も触ってみます。
どうやらブルー/グリーンデプロイ的なことが出来そうで、複数バージョンでトラフィックを切り替えたり、トラフィックの一部だけ別バージョンに流すことなどができるようです。
dotnet new
で作成したデフォルトのコードをデプロイしていましたが、summaries の定数値を変更したバージョンを作成します。
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
var summaries = new[]
{
"Freezing2", "Bracing2", "Chilly2", "Cool2", "Mild2", "Warm2", "Balmy2", "Hot2", "Sweltering2", "Scorching2"
};
:
前述の手順のとおりこちらをビルドしてプッシュします。
そして、AppRun メニューのコンテナの構成情報から新しいイメージタグを指定します。
「更新する」ボタンの上に「このバージョンをすぐに利用する」というチェックがありますね。
デフォルトはオフなのですが、どうやらこちらをオンにすると新しいバージョンにすぐにトラフィックが流れるようです。オフの場合は今までどおりのバージョンにトラフィックが流れるようです。なるほど。
今回はオフでデプロイしてみました...が、新しくデプロイしたバージョンにトラフィックが流れるようになってしまいました。
デフォルトのバージョンが「最新のバージョン」になっている
AppRun のトラフィック管理画面を見てみると、そこで指定されているバージョンが「最新のバージョン」であることに気が付きました。どうやらこれがデフォルト値のようでこちらが選択されている場合は先ほどの「このバージョンをすぐに利用する」の設定にかかわらず最新バージョンにトラフィックが流れる仕組みのようです。そういうことか。
試しに最新バージョンのひとつを明示的に指定してみましょう。
その状態で新しいバージョンをデプロイしたところ、今度は古いバージョンへのトラフィック設定が残ったまま新しいバージョンをデプロイすることが出来ました。
このバージョン管理機能、トラフィックを最新バージョンに流したり、問題発生時に切り戻したりが楽そうで使いやすそうです。
複数バージョンにトラフィック割合を分けてみる
このトラフィック管理機能、どのバージョンかを指定する以外に、そのバージョンにトラフィックの何%を流すかを指定することが出来ます。カナリアリリース的な使い方が出来そうですね。
試しに別のバージョンを追加して 50% づつで設定してみました。
リクエストを複数流してみたところ次のような挙動をしていました。毎回ではなく複数回ごとに転送先が切り替わってます。
ヘッダーに何か振り分けている情報が含まれている感じではなかったのでセッション固定されている様子もなかったです。
% curl https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast
[{"date":"2025-03-24","temperatureC":-10,"summary":"Warm3","temperatureF":15},{"date":"2025-03-25","temperatureC":2,"summary":"Cool3","temperatureF":35},{"date":"2025-03-26","temperatureC":3,"summary":"Cool3","temperatureF":37},{"date":"2025-03-27","temperatureC":43,"summary":"Chilly3","temperatureF":109},{"date":"2025-03-28","temperatureC":49,"summary":"Cool3","temperatureF":120}]
% curl https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast
[{"date":"2025-03-24","temperatureC":-4,"summary":"Chilly3","temperatureF":25},{"date":"2025-03-25","temperatureC":-15,"summary":"Balmy3","temperatureF":6},{"date":"2025-03-26","temperatureC":52,"summary":"Balmy3","temperatureF":125},{"date":"2025-03-27","temperatureC":44,"summary":"Chilly3","temperatureF":111},{"date":"2025-03-28","temperatureC":-11,"summary":"Chilly3","temperatureF":13}]
% curl https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast
[{"date":"2025-03-24","temperatureC":31,"summary":"Balmy3","temperatureF":87},{"date":"2025-03-25","temperatureC":40,"summary":"Cool3","temperatureF":103},{"date":"2025-03-26","temperatureC":-11,"summary":"Warm3","temperatureF":13},{"date":"2025-03-27","temperatureC":-5,"summary":"Sweltering3","temperatureF":24},{"date":"2025-03-28","temperatureC":27,"summary":"Freezing3","temperatureF":80}]
% curl https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast
[{"date":"2025-03-24","temperatureC":13,"summary":"Warm3","temperatureF":55},{"date":"2025-03-25","temperatureC":47,"summary":"Freezing3","temperatureF":116},{"date":"2025-03-26","temperatureC":-10,"summary":"Warm3","temperatureF":15},{"date":"2025-03-27","temperatureC":40,"summary":"Chilly3","temperatureF":103},{"date":"2025-03-28","temperatureC":15,"summary":"Mild3","temperatureF":58}]
% curl https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast
[{"date":"2025-03-24","temperatureC":7,"summary":"Hot2","temperatureF":44},{"date":"2025-03-25","temperatureC":37,"summary":"Hot2","temperatureF":98},{"date":"2025-03-26","temperatureC":0,"summary":"Chilly2","temperatureF":32},{"date":"2025-03-27","temperatureC":51,"summary":"Chilly2","temperatureF":123},{"date":"2025-03-28","temperatureC":-12,"summary":"Chilly2","temperatureF":11}]
% curl https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast
[{"date":"2025-03-24","temperatureC":36,"summary":"Balmy2","temperatureF":96},{"date":"2025-03-25","temperatureC":24,"summary":"Hot2","temperatureF":75},{"date":"2025-03-26","temperatureC":-7,"summary":"Bracing2","temperatureF":20},{"date":"2025-03-27","temperatureC":31,"summary":"Chilly2","temperatureF":87},{"date":"2025-03-28","temperatureC":16,"summary":"Sweltering2","temperatureF":60}]
% curl https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast
[{"date":"2025-03-24","temperatureC":42,"summary":"Balmy2","temperatureF":107},{"date":"2025-03-25","temperatureC":-12,"summary":"Freezing2","temperatureF":11},{"date":"2025-03-26","temperatureC":0,"summary":"Hot2","temperatureF":32},{"date":"2025-03-27","temperatureC":1,"summary":"Balmy2","temperatureF":33},{"date":"2025-03-28","temperatureC":54,"summary":"Bracing2","temperatureF":129}]
% curl https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast
[{"date":"2025-03-24","temperatureC":19,"summary":"Sweltering3","temperatureF":66},{"date":"2025-03-25","temperatureC":29,"summary":"Sweltering3","temperatureF":84},{"date":"2025-03-26","temperatureC":31,"summary":"Scorching3","temperatureF":87},{"date":"2025-03-27","temperatureC":50,"summary":"Chilly3","temperatureF":121},{"date":"2025-03-28","temperatureC":-18,"summary":"Balmy3","temperatureF":0}]
% curl https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast
[{"date":"2025-03-24","temperatureC":-3,"summary":"Sweltering3","temperatureF":27},{"date":"2025-03-25","temperatureC":34,"summary":"Cool3","temperatureF":93},{"date":"2025-03-26","temperatureC":3,"summary":"Chilly3","temperatureF":37},{"date":"2025-03-27","temperatureC":-20,"summary":"Hot3","temperatureF":-3},{"date":"2025-03-28","temperatureC":18,"summary":"Cool3","temperatureF":64}]
% curl https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast
[{"date":"2025-03-24","temperatureC":4,"summary":"Scorching3","temperatureF":39},{"date":"2025-03-25","temperatureC":39,"summary":"Cool3","temperatureF":102},{"date":"2025-03-26","temperatureC":50,"summary":"Freezing3","temperatureF":121},{"date":"2025-03-27","temperatureC":29,"summary":"Balmy3","temperatureF":84},{"date":"2025-03-28","temperatureC":48,"summary":"Scorching3","temperatureF":118}]%
パケットフィルター
最後に、パケットフィルターも試してみます。
これは非常に使いやすそうな機能で、要は IP アドレス制限です。
利用設定を「利用する」にすると有効化され、許可した送信元 IP アドレス以外からはアクセスできなくなります。
許可する IP アドレスは最大 5 つまで指定が可能で、CIDR での指定となります。
許可されたアクセス元、許可されてないアクセス元からのそれぞれのレスポンス結果は次のようになりました。
# 許可されたアクセス元
% curl https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast
[{"date":"2025-03-24","temperatureC":-9,"summary":"Sweltering3","temperatureF":16},{"date":"2025-03-25","temperatureC":37,"summary":"Scorching3","temperatureF":98},{"date":"2025-03-26","temperatureC":-16,"summary":"Mild3","temperatureF":4},{"date":"2025-03-27","temperatureC":-18,"summary":"Bracing3","temperatureF":0},{"date":"2025-03-28","temperatureC":51,"summary":"Hot3","temperatureF":123}]
# 許可されてないアクセス元
% curl https://app-61c8f7d3-4240-49ea-b536-e27e35407a3a.ingress.apprun.sakura.ne.jp/weatherforecast
Forbidden
さいごに
本日はさくらのクラウドで AppRun(β)の基本機能を使ってみました。
先日の記事でも記載していますがβ期間中は無償で利用できますが、様々な制限事項があります。
また、βも始まったばかりでこれから機能強化されていくでしょうから、いまのうちから機能要望などフィードバックをたくさんしていきたいですね。
ちなみにフィードバックはコントロールパネルのメニューにある「フィードバック」ボタンから簡単に行うことが出来ます。