はじめに
社内研修で Rust を使って API サーバを構築する機会がありました
そのデプロイ先に AWS App Runner を用いたので,手順を備忘録として残してみます
App Runner の利用によって生じる料金について,公式の最新情報を参照してください
開発環境 / 使うもの
- Apple M1 Pro
- Rust v1.67
- Axum v0.7.2
手順
作業の流れ
- Docker イメージの作成
- ECR にイメージをプッシュ
- App Runner の設定・起動
0. 今回動かすコード
今回は Axum 公式の Hello World を参考に動かしてみます
コードと依存関係はこんな感じです
[package]
name = "app-runner-example"
version = "0.1.0"
edition = "2021"
[dependencies]
axum = "0.7.2"
tokio = { version = "1.35.0", features = ["full"] }
use axum::{routing::get, Router};
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(|| async { "Hello World!" }));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
1. Docker イメージの作成
Rust のコードを実行するためのイメージを作成します
上のコードを配置したディレクトリに,下記のような Dockerfile を配置します
FROM rust:1.67 AS builder
WORKDIR /usr/src/app
COPY . .
RUN cargo build --release
# ---
FROM gcr.io/distroless/cc-debian12:latest
COPY --from=builder /usr/src/app/target/release/app-runner-example .
ENTRYPOINT ["./app-runner-example"]
下記のコマンドでビルドします
ARM でビルドされたイメージは AppRunner では使えないようです
今回は ARM環境(M1 Mac) でビルドしたため,--platform
を指定して x86 対応を行っています
docker build -t app-runner-example --platform=linux/x86_64 .
一応ローカルで動作確認しておきます
docker run -dit -p 127.0.0.1:3000:3000 app-runner-example
curl localhost:3000 # Hello World! が出力されるはず
2. ECRへイメージをプッシュ
まず,AWS マネジメントコンソールから Elastic Container Registry
を開きます
Private registry / repositories
-> リポジトリを作成
へ進みます
作成したリポジトリ(app-runner-exaple
)をクリックして詳細を表示します
表示されたコマンドのうち,2番目を除いて実行していきます
(2番目のビルドは先述した手順で実行済みです)
コマンドを実行後,ページをリロードするとプッシュしたイメージが見れるはずです
3. App Runner の設定・起動
ここまでの手順で App Runner 上で動かすコードの準備が完了しました
ここから App Runner を設定していきます
AWS マネジメントコンソールから AWS App Runner
を開きます
サイドメニューの「サービス」->「サービスの作成」と進みます
「ソース」の欄を設定していきます
冒頭2項目はそのまま,「コンテナイメージのURI」の「参照」をクリックします
表示されたポップアップから,先ほど作成した ECR のリポジトリを選択し「続行」します
次に「デプロイ設定」を行います
デプロイトリガーは説明の通り,デプロイを手動で行うか自動化するかを選択する項目です
ここではイメージがプッシュされたら自動デプロイする「自動」を選択し,「次へ」をクリックします
動作テスト用なので,CPU,メモリは最小に設定しています
また,ポートを忘れずに 3000 番に指定します
残りの項目はデフォルト設定として「次へ」をクリックします
確認画面の「作成とデプロイ」を押してデプロイを開始します
Operation in progress
が Runnig
となるまで待ちます
表示されている「デフォルトドメイン」をクリックして Hello World!
が表示されたら成功です
3.1 自動デプロイのテスト
ついでなので,イメージがプッシュされた時に自動デプロイがされるかも試します
Hello World! ver2
と表示するように修正してみます
use axum::{routing::get, Router};
#[tokio::main]
async fn main() {
- let app = Router::new().route("/", get(|| async { "Hello World!" }));
+ let app = Router::new().route("/", get(|| async { "Hello World! ver2" }));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
ビルドしてプッシュします
docker build -t app-runner-example --platform=linux/x86_64 .
# ここから下は ECR の「プッシュコマンドの表示」を参照
docker tag app-runner-example:latest {AWS Account ID}.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-example:latest
docker push {AWS Account ID}.dkr.ecr.ap-northeast-1.amazonaws.com/app-runner-example:latest
イメージをプッシュすると,App Runner のデプロイが始まります
完了すると Hello World! ver2
に表示が変化していることが確認できます
4. リソースの削除
このままだと課金が続いてしまうので,作成したリソースを削除していきます
4.1 App Runner の削除
AppRunnerの詳細画面「アクション」から「削除」を選択し削除する
4.2 ECR の削除
先ほど作成したECRのリポジトリ一覧から,先ほど作成したリポジトリを削除する
最後に
かなり簡単に Rust 製の API をデプロイすることができました
GitHub Actions 等の利用でコードの更新時に自動デプロイを行うことも可能です
ARM の Docker イメージにも対応してくれると嬉しいなと思いました