16
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ElixirAdvent Calendar 2022

Day 14

AWS Copilot で Phoenix Framework の本番環境を構築する リリース用ビルド編

Last updated at Posted at 2022-06-08

はじめに

AWS Copilot で Phoenix Framework の本番環境を構築するシリーズです

実装したサンプルはこちらに格納しています

Elixir のリリース手順

以前の記事では mix phx.server を実行し、 Elixir の開発環境でそのまま Phoenix を起動していました

しかし、本番環境にはソースコードも Elixir も不要です

セキュリティやコンテナ軽量化のため、不要なものは何もない状態が理想です

そこで、 mix release を実行してビルドした実行可能ファイルのみを本番環境コンテナに配置します

release.drawio.png

Docker のマルチステージビルド

ビルド用コンテナでビルドして、リリース用コンテナにビルド結果をコピーするので、
Docker のマルチステージビルドを利用します

Dockerfile 内で複数回 FROM 句を書けばマルチステージビルドになります

実装例

###################### ここからビルド用コンテナ ######################
# ビルド用とリリース用は同じ OS でなければならない
# リリース用は軽くしたいので alpine にする
FROM elixir:1.13.4-alpine AS build

ARG SECRET_KEY_BASE

ENV MIX_ENV="prod"
ENV SECRET_KEY_BASE=${SECRET_KEY_BASE}

# ビルドに必要なパッケージをインストールする
RUN apk add --no-cache build-base git npm yarn python3

RUN mix local.hex --force && \
  mix local.rebar --force

# ソースコードをコピーする
COPY ./react_chat /app

WORKDIR /app

# 依存パッケージの取得など
RUN mix deps.get --only prod
RUN cd assets && yarn install
RUN mix assets.deploy
RUN mix phx.gen.release

# リリース用にビルドする
RUN mix release

###################### ここまでビルド用コンテナ ######################
###################### ここからリリース用コンテナ #####################
FROM alpine:3.15.4 AS app

ENV MIX_ENV="prod"
ENV HOME=/app
ENV PHX_SERVER=true

# 運用等に必要なパッケージをインストールする(curl や jq はクラスタリングに使用)
RUN apk add --no-cache openssl ncurses-libs curl jq libstdc++

WORKDIR /app

RUN chown nobody:nobody /app

USER nobody:nobody

# ビルド用コンテナからビルド結果をコピーする
COPY --from=build --chown=nobody:nobody /app/_build/${MIX_ENV}/rel/react_chat ./

# mix release で作られた実行可能ファイルから Phoenix を起動する
CMD ["bin/react_chat", "start"]
###################### ここまでリリース用コンテナ #####################

マルチステージビルドのポイント

  • ビルド用コンテナとリリース用コンテナの OS は同じにする
  • リリース用を軽量にしたいので Alpine Linux を指定する

  • FROM elixir:1.13.4-alpine AS build というように別名を付ける
  • COPY --from=build というようにビルド用コンテナの別名を指定してリリース用コンテナにコピーする

参考記事:

AWS Copilot の設定

リリース用の Dockerfile を Dockerfile_release とした場合、
AWS Copilot の manifest.yml では以下のように指定します

name: lb-svc # サービス名
type: Load Balanced Web Service

http:
  path: '/'

image:
  build:
    dockerfile: Dockerfile_release # Dockerfile の指定
    context: .
    args: # ビルド引数の指定
      SECRET_KEY_BASE: ${SECRET_KEY_BASE}
  port: 4000

cpu: 256
memory: 512
count:
  spot: 2
exec: true

# リリース用コンテナに渡す環境変数
variables:
  SECRET_KEY_BASE: ${SECRET_KEY_BASE}

manifest.yml では ${環境変数} でローカルの環境変数を渡すことができます

SECRET_KEY_BASE に任意の値を設定してから copilot svc deploy を実行してください

まとめ

かつては開発用EC2でビルドした結果を GitHub のリリースにアップロードして、
本番用EC2は GitHub のリリースからダウンロードする、
というややこしい手順を Ansible で実行していました

Docker のマルチステージビルドであれば、
ビルドからデプロイまで Dockerfile 内で定義でき、
非常に分かりやすいです

16
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?