きっかけ
ECSは起動時、コンテナに環境変数を受け渡すことが可能です。
Next.jsをECSで動かす際に、必要な環境変数をこの機能で受け渡そうとしたのですが、うまくいきませんでした。
原因
NEXT_PUBLIC_から開始される環境変数については、ビルド時に設定されるものなので、コンテナ起動後に使用されるタスク定義で環境変数を設定しても使用できません。
npm build
したタイミングで.env.production
にある必要があるんですね。。。
よく考えたらそれはそうです。
上記記事ではAWS Codeシリーズを使った対策が記載されていますが、あいにく私はコードシリーズが大の苦手なのです・・・。できればDockerfileだけで完結させたい・・・。
対応
を使いました。
これはgoで書かれたパッケージで、ParameterStoreにある環境変数を取得し展開します。
.env.production
に展開するのであればこんな感じ
aws-env --format=dotenv > .env.production;
Dockerfileでビルド時に上記コマンドを実行し、環境変数を展開します。
FROM node:latest
ARG ENV=dev
ENV ENV=${ENV}
ARG AWS_ACCESS_KEY_ID
ARG AWS_SECRET_ACCESS_KEY
ARG AWS_REGION
ARG AWS_ENV_PATH
WORKDIR /code
COPY . .
RUN if [ "$ENV" = "prod" ]; then \
wget https://github.com/Droplr/aws-env/raw/master/bin/aws-env-linux-amd64 -O /bin/aws-env && \
chmod +x /bin/aws-env && \
AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
AWS_REGION=$AWS_REGION \
AWS_ENV_PATH=$AWS_ENV_PATH \
aws-env --format=dotenv > .env.production; \
fi
RUN npm update -g npm && \
npm install && \
npm run build
EXPOSE 3000
CMD "sh" "-c" "npm run start"
GitHubActionsでbuildする時は以下のようにアクセスキーを渡しつつ実行します。
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \
--build-arg AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} \
--build-arg AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} \
--build-arg AWS_REGION=ap-northeast-1 \
--build-arg AWS_ENV_PATH=${{ secrets.AWS_ENV_PATH }} \
--build-arg ENV=prod \
.
IAMポリシーは参照するParameterStoreのパスに対して以下のように設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "ssm:GetParametersByPath",
"Resource": "arn:aws:ssm:ap-northeast-1:235087485205:parameter/path/to/parameter/*"
}
]
}
結論
シンプルな分すごい使いやすいパッケージですね。
サーバーサイドの環境変数であればeval $(aws-env)
を実行するだけで展開可能です。
ECSの環境変数でParameterStoreのパスとリージョンを設定し、コンテナ起動時のコマンドをbash -c "eval $(aws-env) && npm start"
のようにうまく上書きします。