SPA を Docker でホストするときによく思うことが、Environment Variables をSPA に渡したい!と思うことだ。例えば、バックエンドサーバーの URL 等だ。実際にこれは出来ない。なぜかというと、動作するのはあくまでユーザのブラウザ上だからだ。通常は、CIでそれらをインジェクトしてデプロイする。
そのインジェクションを Docker build の時にやってしまいたいので、そういうコードを書いてみた。
環境変数のビルド時におけるインジェクション
インジェクト用のシェルファイル
例えば Angular だったら、src/environments/environment.ts
等を書きかえる。
environment.ts
export const environment = {
production: false,
backendUrl: "https://somethingfunctionapp.azurewebsites.net/api/SomeStatus"
};
これをFUNCTION_NAME
という環境変数で上書きされるようにスクリプトを書いておく。ここでポイントは、正規表現の記述が /
ではなく |
を使っていること。これは、somethingfunctionapp/$FUNCTION_NAME
だと、ディレクトリ名と区分けがつかなくなり、somethingfunctionapp//somename
などに変換されるため。
inject.sh
# !/bin/sh
grep -l 'somethingfunctionapp' src/environments/*.ts | xargs sed -i.bak -e "s|somethingfunctionapp|$FUNCTION_NAME|g"
Dockerfile
通常だと、実行しているシェルの環境変数は引き継がれない。ARG
を用いる。
FROM node:8-alpine AS build
WORKDIR /usr/src/app
RUN npm i -g @angular/cli
COPY . .
ARG FUNCTION_NAME
RUN sh inject.sh
RUN npm install --silent
RUN npm run build
FROM nginx:1.13.12-alpine
WORKDIR /app
RUN rm -rf /usr/share/nginx/html
# COPY ./dist /usr/share/nginx/html # Useful for local builds
COPY --from=build /usr/src/app/dist /usr/share/nginx/html
こうしておくと実行時に次のようにして環境変数を渡すことができる。
docker build --build-arg FUNCTION_NAME="$FUNCTION_NAME" . -t abc
あとはこの docker build
を実行すると無事に実行時すれば完了。
あとがき
ちなみに、これを作り終えてから気が付いたが、このファイル書き換えの方法をスタートアップスクリプトを作って、それが環境変数をインジェクトするようにすると、docker コンテナの環境変数でもインジェクトできることに気が付いた。こんかいのユースケースではそこまで不要なのでやってないが、そっちのほうがカッコいいかも。