AWS Copilot CLI を使って AWS App Runner にデプロイしてみた
Author : 苅野 秀和
この記事は AWS App Runner Advent Calendar 2022 の 12 月 22 日の記事になります。
コンテナが好きな皆さんこんにちは。ソリューションアーキテクトの苅野です。 AWS App Runner Advent Calendar 2022 22 日目の記事をお届けします。
この記事では App Runner 環境を AWS Copilot CLI で構築しアプリケーションをデプロイしてみようと思います。App Runner はコンテナを動かすマネージドなプラットフォームで足回りのことを極力意識せずにみなさんの大切なアプリケーションをデプロイすることができます。AWS Copilot CLI は AWS にあまり詳しくない方でも対話的なコマンドでインフラを構築して開発者の皆さんがアプリ開発に集中する手助けをしてくれるツールです。そして AWS Copilot CLI から App Runner 環境を構築してアプリをデプロイすることが可能です。
AWS Copilot でインフラ部分を対話的に簡単に作れて、App Runner に簡単にデプロイできると嬉しいですよね。カレーが好きでうどんも好きならカレーうどんももちろん好きなのと同じように、AWS Copilot と App Runner を組み合わせることで簡単かつ柔軟にアプリケーションをデプロイすることができます。
App Runner とは
AWS 上でコンテナ化されたアプリケーションを簡単に構築・運営できるフルマネージドサービスです。こちらのスライド にあるようにオーケストレーションワークフローや CI/CD の整備を App Runner に任せて、利用者はアプリケーション開発に集中することができます。
ソースコードかコンテナイメージを用意するだけでアプリケーションをクラウドにデプロイできるので、ベストプラクティスに基づいた出来合いのインフラでいいからクラウド上にアプリケーションを展開したい場合におすすめのサービスです。
App Runner はとても簡単に設定することができますが、それでもコンテナに割り当てるリソースだったり環境変数の設定だったりと最低限の設定は必要です。また特にコンテナイメージからデプロイする場合は Amazon ECR リポジトリを作成する必要があります。さらに 2022 年のアップデートでネットワーク周りが強化されており、お客様の VPC にアウトバウンドのトラフィックを流したり、お客様の VPC からのアクセスのみにインバウンドのトラフィックを制限できるようになりました。こうした機能を使う場合は App Runner の設定を追加する必要があります。すると App Runner の設定も色々項目が増えてきてコード管理したくなってくると思います。App Runner は CDK や Terraform に対応しておりこれらを活用いただくでも構いませんが、せっかく App Runner は簡単に構築することができるので同じように簡単に操作できる AWS Copilot CLI と連携してみましょう。
AWS Copilot CLI とは
AWS Copilot CLI は主に Amazon ECS 上でアプリケーションを動かす際のインフラ構築を手助けしてくれる OSS の CLI ツールです。GitHub 上 で開発が活発に行われています。
AWS Copilot の特徴を一言で言うと「アーキテクチャに基づいて対話的に環境を構築できる」ことです。インターネットからトラフィックを受けてレスポンスを返すアプリケーションや、バックエンドで処理を行うアプリケーションなどいくつかのパターンに基づいて必要なリソースを作成することができます。このパターンには App Runner も含まれています(Request-Driven Web Service と言います)。このパターンは Manifest ファイルという yaml ファイルで定義されていてこのファイルを元に関連するリソースが作成されます。
AWS Copilot の考え方
AWS Copilot ではリソースをいくつかのグループに抽象化して扱います。
まず Application。これは後述する Environment と Service をまとめて管理する論理グループです。AWS Copilot でプロジェクトを始めるときはまずこの Application を初期化します。
次に Environment。これは Service を動かすのに必要なインフラで VPC や ECS クラスターをまとめたものです。みなさんがアプリケーションを開発するときに開発環境や本番環境を作成しますよね?その時の環境のようなものだとお考えください。1 つの Application の中に複数の Environment を含めることができます。
最後に Service 。これは Manifest ファイルを元に作成されるいろいろなワークロードです。例えばロードバランサー配下でコンテナを動かしてレスポンスを返したり、SQS のメッセージをポーリングして処理するアプリケーションを動かすことができます。詳しくは こちらのドキュメント をご確認ください。
クリックすると拡大します
他にも CI/CD パイプラインをコマンドひとつで作れるのが個人的な推しポイントです。今回は AWS Copilot CLI を使って App Runner 環境を構築してアプリケーションをデプロイしていきます。
AWS Copilot CLI で App Runner 環境を構築する
IAM の設定
ドキュメント に書いているように AWS Copilot を使う時は IAM ユーザーを使用します。まずはこの IAM の認証情報を登録しましょう。copilot-user という名前の IAM ユーザーを作成しそのアクセスキーIDとシークレットアクセスキーを登録します。
$ aws configure
AWS Access Key ID [None]: <アクセスキーID>
AWS Secret Access Key [None]: <シークレットアクセスキー>
Default region name [None]: <使用するリージョン>
Default output format [None]: json
$ aws sts get-caller-identity
{
"Account": <アカウントID>,
"UserId": <ユーザーID>,
"Arn": "arn:aws:iam::<アカウントID>:user/copilot-user"
}
AWS Copilot のインストール
ドキュメント に書いているようにお使いの OS ごとにインストールすることができます。例えば MacOS の場合以下のようにインストールできます (今回は記事執筆時点での最新バージョンの v1.24 を使用します)。
$ curl -Lo copilot https://github.com/aws/copilot-cli/releases/download/v1.24.0/copilot-darwin && chmod +x copilot && sudo mv copilot /usr/local/bin/copilot && copilot --help
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 41.1M 100 41.1M 0 0 105M 0 --:--:-- --:--:-- --:--:-- 105M
👩✈️ Launch and manage containerized applications on AWS.
Commands
Getting Started 🌱
init Create a new ECS or App Runner application.
docs Open the copilot docs.
Develop ✨
app Commands for applications.
Applications are a collection of services and environments.
env Commands for environments.
Environments are deployment stages shared between services.
svc Commands for services.
Services are long-running ECS or App Runner services.
job Commands for jobs.
Jobs are tasks that are triggered by events.
task Commands for tasks.
One-off Amazon ECS tasks that terminate once their work is done.
Release 🚀
pipeline Commands for pipelines.
Continuous delivery pipelines to release services.
deploy Deploy a Copilot job or service.
Extend
storage Commands for working with storage and databases.
secret Commands for secrets.
Secrets are sensitive information that you need in your application.
Settings ⚙️
version Print the version number.
completion Output shell completion code.
Flags
-h, --help help for copilot
-v, --version version for copilot
Examples
Displays the help menu for the "init" command.
`$ copilot init --help`
デプロイするアプリのクローン
今回は簡単のために サンプルアプリ を git clone してきて AWS Copilot を使って App Runner にデプロイします。もちろんみなさんお手製のアプリをデプロイすることも可能です。
$ git clone https://github.com/aws-containers/hello-app-runner.git
$ cd hello-app-runner
AWS Copilot Application を初期化する
まず最初に AWS Copilot Application を初期化します。copilot app init を実行しましょう。Application 名を聞かれるので my-app-runner-application と答えます。
$ copilot app init
Application name: my-app-runner-application
✔ Proposing infrastructure changes for stack my-app-runner-application-infrastructure-roles
- Creating the infrastructure for stack my-app-runner-application-infrastructure-roles [create complete] [52.1s]
- A StackSet admin role assumed by CloudFormation to manage regional stacks [create complete] [21.7s]
- An IAM role assumed by the admin role to create ECR repositories, KMS keys, and S3 buckets [create complete] [20.7s]
✔ The directory copilot will hold service manifests for application my-app-runner-application.
Recommended follow-up action:
- Run `copilot init` to add a new service or job to your application.
AWS Copilot は AWS CloudFormation を用いてリソースの管理を行います。CloudFormation のコンソールに移動してみると以下のようにスタックが 1 つ作成されていることがわかります。
もし AWS Copilot を使っていてエラーが出力されたときは CloudFormation の画面も見てみると原因究明がしやすいと思います。
クリックすると拡大します
また AWS Copilot は Application や Environment の情報を AWS Systems Manager Parameter Store で管理しています。Parameter Store の画面に移動してみるとこちらのように my-app-runner-application というパラメータが作成されています。Parameter Store で管理しているおかげで別の端末からも既存 Application を選択して操作することができます。手動ではこのパラメータに触らないようにしましょう。
クリックすると拡大します
AWS Copilot Environment を作成する
次に AWS Copilot Service が動くインフラ部分の Environment を作成します。AWS Copilot のコマンドはヘルプメッセージが充実しているのでまずは --help フラグをつけて実行してみましょう。
$ copilot env init --help
Creates a new environment in your application.
Usage
copilot env init [flags]
Common Flags
-a, --app string Name of the application. (default "my-app-runner-application")
--aws-access-key-id string Optional. An AWS access key.
--aws-secret-access-key string Optional. An AWS secret access key.
--aws-session-token string Optional. An AWS session token for temporary credentials.
--default-config Optional. Skip prompting and use default environment configuration.
-n, --name string Name of the environment.
--profile string Name of the profile.
--region string Optional. An AWS region where the environment will be created.
Import Existing Resources Flags
--import-cert-arns strings Optional. Apply existing ACM certificates to the internet-facing load balancer.
--import-private-subnets strings Optional. Use existing private subnet IDs.
--import-public-subnets strings Optional. Use existing public subnet IDs.
--import-vpc-id string Optional. Use an existing VPC ID.
Configure Default Resources Flags
--internal-alb-allow-vpc-ingress Optional. Allow internal ALB ingress from port 80 and/or port 443.
--internal-alb-subnets strings Optional. Specify subnet IDs for an internal load balancer.
By default, the load balancer will be placed in your private subnets.
Cannot be specified with --default-config or any of the --override flags.
--override-az-names strings Optional. Availability Zone names.
(default 2 random AZs)
--override-private-cidrs strings Optional. CIDR to use for private subnets.
(default 10.0.2.0/24,10.0.3.0/24)
--override-public-cidrs strings Optional. CIDR to use for public subnets.
(default 10.0.0.0/24,10.0.1.0/24)
--override-vpc-cidr ipNet Optional. Global CIDR to use for VPC.
(default 10.0.0.0/16)
Telemetry Flags
--container-insights Optional. Enable CloudWatch Container Insights.
Examples
Creates a test environment using your "default" AWS profile and default configuration.
`$ copilot env init --name test --profile default --default-config`
Creates a prod-iad environment using your "prod-admin" AWS profile and enables container insights.
`$ copilot env init --name prod-iad --profile prod-admin --container-insights`
Creates an environment with imported resources.
`$ copilot env init --import-vpc-id vpc-099c32d2b98cdcf47 \`
`--import-public-subnets subnet-013e8b691862966cf,subnet-014661ebb7ab8681a \`
`--import-private-subnets subnet-055fafef48fb3c547,subnet-00c9e76f288363e7f \`
`--import-cert-arns arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012`
Creates an environment with overridden CIDRs and AZs.
`$ copilot env init --override-vpc-cidr 10.1.0.0/16 \`
`--override-az-names us-west-2b,us-west-2c \`
`--override-public-cidrs 10.1.0.0/24,10.1.1.0/24 \`
`--override-private-cidrs 10.1.2.0/24,10.1.3.0/24`
丁寧に実行例まで書いてくれていてわかりやすいですね !
Environment を初期化する時にはデフォルトの CIDR 設定で初期化することもできますし、CIDR を少しカスタマイズすることもできますし、既存の VPC をインポートすることもできます。Environment を作成するのは AWS クレデンシャルに記載されたアカウントのリージョンなので、別リージョンでも別アカウントでも同じように Environment を作成することができます。VPC の設定項目にこだわりがなければ AWS Copilot のデフォルト設定で初期化する、細かい要件があったり VPC Peering している既存 VPC を使用したいといったネットワーク要件があれば既存 VPC をインポートして使うといった使い分けが可能です。
今回は新しく VPC を作るところから始めましょう。質問には以下のように答えます。最後の質問で No, I'd like to import existing resources と答えると現在のリージョンにある VPC 一覧からインポートする VPC を選ぶことができます。
- Environment name: dev と入力して Enter
- Credential source: [profile default] を選択して Enter
- Default environment configuration? : Yes, use default. を選択して Enter
$ copilot env init
Environment name: dev
Credential source: [profile default]
Default environment configuration? Yes, use default.
✔ Wrote the manifest for environment dev at copilot/environments/dev/manifest.yml
- Update regional resources with stack set "my-app-runner-application-infrastructure" [succeeded] [0.0s]
- Update regional resources with stack set "my-app-runner-application-infrastructure" [succeeded] [131.5s]
- Update resources in region "us-east-1" [create complete] [128.0s]
- KMS key to encrypt pipeline artifacts between stages [create complete] [121.4s]
- S3 Bucket to store local artifacts [create complete] [2.1s]
✔ Proposing infrastructure changes for the my-app-runner-application-dev environment.
- Creating the infrastructure for the my-app-runner-application-dev environment. [create complete] [51.9s]
- An IAM Role for AWS CloudFormation to manage resources [create complete] [20.1s]
- An IAM Role to describe resources in your environment [create complete] [19.9s]
✔ Provisioned bootstrap resources for environment dev in region us-east-1 under application my-app-runner-application.
Recommended follow-up actions:
- Update your manifest copilot/environments/dev/manifest.yml to change the defaults.
- Run `copilot env deploy --name dev` to deploy your environment.
コマンドの実行後は何やら CloudFormation を使ってリソースが作成されていますね。注意していただきたいのはこの瞬間にクラウド上に VPC が作成されているわけではないという点です。copilot/environments/dev/manifest.yml という Environment を定義した Manifest ファイルがローカルに作成されて Environment を操作する IAM Role などが作成されただけで、クラウド上にまだ VPC は作成されていません。必要であればこの Manifest ファイルを編集した上で copilot env deploy コマンドを実行して初めてクラウド上に VPC などのリソースが作成されます。
$ copilot env deploy
コマンドが完了したら CloudFormation の画面を見てみましょう。dev Environment が作成されていることがわかります。
クリックすると拡大します
また Parameter Store の画面に映ってみると新たに dev Environment に関するパラメータが作成されていることがわかります。
クリックすると拡大します
そしておまちかねの VPC の画面を見てみると copilot-<application 名>-<environment 名> という名前の VPC が作成されています。
クリックすると拡大します
今回作成する Service は Request-Driven Web Service つまり App Runner で動くものなのであまり VPC を意識する必要はありません。しかし VPC Connector を使って VPC 内部のリソースにアクセスする場合や VPC Endpoint 経由のみにアクセスを制限したい場合は AWS Copilot で Environment を管理すると便利でしょう。
Request-Driven Web Service の作成
Application, Environment が準備できたのでいよいよ Service を作成しましょう。途中の質問には以下のように回答します。
- Service type: Request-Driven Web Serviceを選択して Enter
- Service name: frontendと入力して Enter
- Would you like to accept traffic from your environment or the internet?: Internet を選択して Enter
- Which Dockerfile would you like to use for hello-app-runner-service? ./Dockerfile を選択して Enter
$ copilot svc init
Note: It's best to run this command in the root of your workspace.
Service type: Request-Driven Web Service
Service name: frontend
Reachable from: Internet
Dockerfile: ./Dockerfile
✔ Wrote the manifest for service hello-app-runner-service at copilot/hello-app-runner-service/manifest.yml
Your manifest contains configurations like your container size and port (:8000).
- Update regional resources with stack set "my-app-runner-application-infrastructure" [succeeded] [15.5s]
- Update resources in region "us-east-1" [update complete] [11.2s]
- ECR container image repository for "hello-app-runner-service" [create complete] [2.6s]
Recommended follow-up actions:
- Update your manifest copilot/hello-app-runner-service/manifest.yml to change the defaults.
- Run `copilot svc deploy --name hello-app-runner-service --env test` to deploy your service to a test environment.
このコマンドを実行すると裏側で App Runner 用の ECR リポジトリを作成してくれます。痒いところに手が届いて便利ですね。
copilot/frontend/manifest.yml を開いてみましょう。このファイルで Service を定義していて、ドキュメント にあるようにさらに細かく設定することもできます。App Runner は十分シンプルなサービスではありますが割り当てる CPU などのリソース定義や環境変数など最低限の設定は必要です。これにさらに VPC Connector の設定などが増えてくるとどこかで IaC の管理をしたくなってくるでしょう。そういった時に AWS Copilot は選択肢の 1 つになります。
では早速この Service をデプロイしましょう。
$ copilot svc deploy
(省略)
✔ Deployed service frontend.
Recommended follow-up action:
- You can access your service at <App Runner のエンドポイント> over the internet.
コンテナイメージのビルド、ECR へのプッシュ、App Runner サービスの作成を AWS Copilot がやってくれて最終的に App Runner のエンドポイントが表示されます。これにアクセスするとアプリケーションが元気に動いていることがわかります。
クリックすると拡大します
お片付け
今回作成したリソースを全て削除するには copilot app delete を実行します。本当に削除しますかと聞かれるので Y と入力して Enter を押しましょう。
$ copilot app delete
Are you sure ~ ?: Y
まとめ
今回は AWS Copilot CLI を使って App Runner にアプリケーションをデプロイしてみました。App Runner 環境を構築する場合の中でも特に VPC Connector を使って VPC 内部のリソースにアクセスする場合など App Runner だけで完結しないワークロードにはぴったりなのではないでしょうか ? また AWS Copilot CLI に興味を持った方は合わせて こちらのワークショップも ご覧になってください。
筆者プロフィール
苅野 秀和
アマゾン ウェブ サービス ジャパン合同会社 ソリューションアーキテクト
飛行機の勉強をしていたのが気づいたらなんやかんやあって AWS に入社してました。現在はウェブ系のお客様の技術支援を行いながら AWS Copilot などのコンテナツールを広めています。
週末は美味しいクロワッサンを求めてパン屋を探訪しています。
AWS を無料でお試しいただけます