先日 AWS に App Runner という新サービスがリリースされました。
Fargate をさらに抽象化したようなサービスで、使い勝手は Heroku のような PaaS に近いです。
そんな App Runner ですが、
- ECR と連携して、別途自作したコンテナイメージを使用
- GitHub と連携して、自動でコンテナイメージを作成して使用
という 2 パターンの使い方があります。
後者の GitHub と連携して自動でコンテナイメージを作成してくれるパターンについては、現状では Node.js と Python しかサポートされていません。
Dockerfile を書かなくてもコンテナイメージが自動で作成されてデプロイされるというのはかなり楽なので、他の言語でも似たようなことをしてみたいです。
そこで、コンテナイメージの作成を自動でやってくれる Cloud Native Buildpacks と GitHub Actions を使って、Dockerfile を書かずに App Runner で Ruby のアプリケーションを起動してみようと思います。
※ サンプルとして Ruby を使いますが、他の言語でも同様のことができるはずです。
つまり…
やりたいことを簡単に整理すると、
- GitHub Actions で Cloud Native Buildpacks を使ってイメージをビルドし、ECR に push
- ECR と連携した App Runner に自動でデプロイされる
というイメージです。
セットアップ
では、セットアップしていきます。
手順は 6 ステップあるので多く見えますが、1 つ 1 つは簡単です。
1. サンプルアプリケーションの実装
Ruby のサンプルということで、今回は簡単に用意できる Sinatra を使うことにしました。
GitHub にリポジトリを作成し、
- Gemfile
- app.rb
- config.ru
の 3 ファイルを以下のように作成します。
Gemfile
# frozen_string_literal: true
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
gem "sinatra", "~> 2.1"
app.rb
require 'sinatra'
get '/' do
'Hello world!'
end
config.ru
require './app'
run Sinatra::Application
コードは以下からも確認できます。
このコードが動くかローカルで動作確認したい場合は、Cloud Native Buildpacks の pack コマンドと Docker をインストールして、以下のようなコマンドを実行します。
$ pack build myapp --builder paketobuildpacks/builder:base
$ docker run --rm -e PORT=8000 -p 8000:8000 myapp
2. ECR リポジトリの作成
次に、AWS にログインし、ECR のリポジトリを作成します。
ECR のリポジトリ名は、GitHub のリポジトリ名と同じにしました。
3. IAM ユーザの作成
GitHub Actions から ECR に push するには、IAM ユーザのアクセスキー・シックレットアクセスキーを使う必要があります。
※ もしアクセスキー・シークレットアクセスキーを使いたくない場合は、GitHub Actions ではなく AWS CodeBuild を使いましょう。
専用の IAM ユーザを作成し、ECR にイメージを push するための権限を与えます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GetAuthorizationToken",
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken"
],
"Resource": "*"
},
{
"Sid": "AllowPush",
"Effect": "Allow",
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload"
],
"Resource": "arn:aws:ecr:ap-northeast-1:{AWSアカウントID}:repository/{リポジトリ名}"
}
]
}
※ {AWSアカウントID} と {リポジトリ名} は読み替えが必要です。
4. IAM ユーザのアクセスキー・シークレットアクセスキーを GitHub に設定
上記の IAM ユーザのアクセスキー・シークレットアクセスキーを払い出したら、GitHub のリポジトリの設定画面から、「Settings」>「Secrets」と進み、
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
という名前でそれぞれ登録します。
5. GitHub Actions のワークフロー設定
以下の内容で、.github/workflows/main.yaml というファイルを作成します。
name: main
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
- uses: aws-actions/amazon-ecr-login@v1
id: login-ecr
- uses: asdf-vm/actions/setup@v1
- run: |
asdf plugin-add buildpack
asdf install
pack build $ECR_REGISTRY/$ECR_REPOSITORY:latest --builder paketobuildpacks/builder:base
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: ${{ github.repository }}
ここでは pack コマンドのインストールに asdf を使っていますが、Cloud Native Buildpacks 側が提供しているアクション で pack コマンドをインストールしてもいいと思います。
この YAML ファイルを GitHub に push すれば、GitHub Actions が動き出し、ECR にイメージが push されます。
6. App Runner でサービスの作成
あとは App Runner でサービスを作成するだけです。
マネジメントコンソールから作成する場合は、雰囲気でぽちぽちすればいけます。
ちなみに、ポート番号はなんでも大丈夫です。 (App Runner はポート番号を PORT という環境変数でコンテナに渡してくれて、かつ、Ruby のコンテナ側は PORT という環境変数を使うようになっているため)
起動を待てば、問題なくアクセスできます。
$ curl https://<ドメイン>
Hello world!
まとめ
Cloud Native Buildpacks と GitHub Actions を使って、Dockerfile を書かずに App Runner で Ruby のアプリケーションを起動することができました。
App Runner のロードマップには Ruby のサポートや、Cloud Native Buildpacks のサポートも挙げられています。
- Ruby support · Issue #27 · aws/apprunner-roadmap
- Buildpack support · Issue #11 · aws/apprunner-roadmap
ゆくゆくは、自前で GitHub Actions や Cloud Native Buildpacks を使う必要はなくなるかもしれません。