AIチャットアプリを作ってみよう (インフラ構築編)
この記事は某有志アドベントカレンダー 2023の 21 日目の記事です。
「AIチャットアプリを作ってみよう」シリーズ
- 準備編
- AI チャット実装編
- インフラ構築編(この記事)
こんにちは。あべです。
前回に引き続き、AIチャットアプリのインフラの構築をしていこうと思います。
Dockerfileを書く
現状、ディレクトリ構成はこんな感じになっています
app
`- src/index.ts
`- package.json
`- bun.lockb
appの下にDockerfileを記述していきます
oven/bun:latest
というイメージが公開されていたので、今回はそれを利用します。
// app/Dockerfile
FROM oven/bun:latest AS build
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --production
FROM oven/bun:distroless AS runtime
COPY src /app/src
COPY --from=build --chown=nonroot:nonroot /app/node_modules /app/node_modules
USER nonroot
EXPOSE 3000
CMD ["run", "--hot", "/app/src/index.ts"]
CDKでECRを作成
本当はAppRunnerまでCDKで構築してみようと思ったのですが、
正式には L1 Constract しか用意されていないようで難易度が高く、、、断念しました。
なので今回はECRとimageのデプロイまでをCDK + スクリプトで、
AppRunnerの構築はAWSコンソール上で実施しようと思います。
cdk init
で初期化し、コンテナレジストリを作成していきます。
※CDKを初めて入れた環境では適宜cdk bootstrap
で初期化します
// cdk/lib/cdk-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ecr from 'aws-cdk-lib/aws-ecr';
export class CdkStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const repository = new ecr.Repository(this, 'ai-chat-app-repo', {
repositoryName: 'ai-chat-app-repo',
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteImages: true,
});
}
}
cdk deploy
を実行すると、コンテナレジストリがデプロイされます。
コンテナイメージのデプロイ
この辺りはこちらの記事を参考にさせていただきました🙏
現状ディレクトリ構造はこんな感じです。
/
`- app
`- src/index.ts
`- package.json
`- bun.lockb
`- cdk
`- lib
`- cdk-stack.ts
`- bin
`- (略)
ルートディレクトリにDockerイメージをpushするスクリプトを配置します。
※aws configure
は適宜設定してある前提です。まだの方は先に設定が必要になります。
// image_push.sh
#!/bin/bash
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
REGION=$(aws configure get region)
ECR_REPOSITORY_NAME=ai-chat-app-repo
ECR_REPOSITORY_URI=${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com/${ECR_REPOSITORY_NAME}
echo "Account ID: $ACCOUNT_ID"
echo "Region: $REGION"
echo "ECR Repository Name: $ECR_REPOSITORY_NAME"
echo "Building docker image..."
aws ecr get-login-password --region ${REGION} | docker login --username AWS --password-stdin ${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com
(cd app && docker build --platform linux/amd64 -f ./Dockerfile -t ${ECR_REPOSITORY_NAME} .)
docker tag ${ECR_REPOSITORY_NAME}:latest ${ECR_REPOSITORY_URI}:latest
docker push ${ECR_REPOSITORY_URI}:latest
echo "Docker image built and pushed to ECR repository: ${ECR_REPOSITORY_URI}"
これでECRにイメージをpushする準備ができました。
では早速実行してみます。
chmod -x image_push.sh
./image_push.sh
AWSコンソール側で確認してみましょう。
ちゃんとpushされていますね。
App Runnerのサービスを作成する
App Runnerが参照するコンテナレジストリのURLを設定しましょう。
URIはECRから取得できます。
必要に応じて、CPUはメモリ、オートスケーリングなどの設定が必要なりますが、
今回はお試しなので何も考えずにデフォルト設定でいきます。
次に実行時環境変数の設定をします。
今回はOPENAI_API_KEYが必要になるので設定しましょう。
後述する問題ではハマったのですが、なんとかデプロイ完了してAPIにアクセスできました。
複雑な設定なしですぐアクセスできるのも嬉しいですね。
ハマりポイント
App Runnerでコンテナの実行が失敗していました。
12-19-2023 10:07:50 PM exec /usr/local/bin/bun: exec format error
理由はシンプルで、Dockerイメージのビルド時に--platform
が未指定だったのが原因でした。
linux/amd64
に指定して解決しました
docker build --platform linux/amd64 -f ./Dockerfile -t ${ECR_REPOSITORY_NAME}
後片づけ
AppRunnerは停止していても課金されるようなので、削除しておきましょう。
CDKデプロイしたECRも破棄します
cdk destroy
(やっぱり後片付けが面倒なので、全部CDKでやればよかったですねー、、、)
まとめ
今回で一旦一区切りとなります(フロント構築編は気が向いたらやるかも、、、?)
App RunnerをCDKで構築したかったのですが、うまくいかなかったのが無念です、、、
L1 Constract ではなく、実験的L2 Constractの @aws-cdk/aws-apprunner-alpha
を利用した実装では以下の記事が参考になりました。 (今更ですが、こちらの実装の方がスマートですね、、、)
まぁ、周り道したなりに勉強になる点もあったのでよしとします。
お付き合いありがとうございました。
それではー。
Discussion