10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ElixirAdvent Calendar 2024

Day 5

Elixir / Phoenix 1.7でJavaScriptライブラリを軽量にインストールする (Dockerマルチステージビルド)

Last updated at Posted at 2024-12-17

この記事は Elixir Advent Calendar 2024 シリーズ1 5日目の記事です。

概要

Phoenix 1.7 (Phoenix 1.6 以降) では Node.js が同梱されていないため、Chart.js のような純粋な JavaScript ライブラリを静的アセットとして含めようとした際に、外部での Node.js を利用した処理が必要になります。

このようなケースで、Docker マルチステージビルドを利用して効率的かつ軽量に JavaScript ライブラリをインストールする方法をご紹介します。

マルチステージビルドとは?

マルチステージビルドとは、Dockerfile 内で複数のベースイメージを使用し、それぞれのステージで役割を分ける方法です。
これによって必要な部分だけを最終イメージに含めることができ、イメージを軽量化できます。

Dockerfile の例

Node.js だけを含む軽量な Alpine ベースイメージを使用して npm install し、その成果物を Elixir ベースイメージに統合します。

以下は、Chart.js のみをインストールするシンプルなマルチステージビルドの例です。

Dockerfile
# Stage 1: Node.js ベースイメージ (Alpine) で npm install を実行
FROM node:22-alpine AS node-builder

WORKDIR /app/assets

COPY assets/package*.json ./
RUN npm install chart.js

# Stage 2: Elixir ベースイメージでアプリケーションを構築
FROM elixir:1.17.3-slim

RUN apt-get update && apt-get install -y \
    inotify-tools

WORKDIR /app

COPY mix.exs mix.lock ./
COPY config config
RUN mix deps.get
RUN mix deps.compile

COPY lib lib
COPY priv priv
COPY assets assets
# node-builder で生成された node_modules を渡す
COPY --from=node-builder /app/assets/node_modules assets/node_modules

RUN mix do compile, phx.digest

CMD ["mix", "phx.server"]
  • ※ Phoenix のバージョンは mix.exs で指定

    mix.exs
    defp deps do
      [
        {:phoenix, "1.7.18"},
        ...
    

なぜマルチステージビルドか?

Node.js を利用するための方法として、ほかには nodenvn 等のバージョン管理ツールや apt-get を利用して Node.js をインストールする選択肢があります。しかし、これらの方法を検討する際には考慮すべき事項がそれぞれあり、一方マルチステージビルドを使うと嬉しいポイントがいくつかあります。

マルチステージビルドを使用するメリット

バージョン管理の柔軟性

  • Node.js の公式イメージを利用するため、必要に応じて特定のバージョンを簡単に指定できる
    • 例えば、node:22-alpine のように、最新バージョンの LTS Alpine ベースイメージを利用可能

軽量化

  • Elixir の最終イメージには Node.js を含めないため、イメージサイズが大幅に削減される
    • Node.js を利用するステージ(先ほどの例だと node-builder)は、アセットビルド専用の一時的ステージとしてのみ機能する

キャッシュの活用

  • COPY assets/package*.json ./ を実行することで、依存関係が変更されない限りは npm install の結果がキャッシュされるので、package.json に変更がなければ再ビルド時に npm install 再実行をする必要がなくなり、再ビルドの時間を短縮できる

責務の分離

  • Node.js を利用するのは JavaScript ライブラリのインストールに必要な第1ステージ (node-builder) のみであり、Node.js に関する処理を完全に分離することで、Elixir ベースのイメージはそのままの構成を維持でき、ビルドプロセス全体の構成管理がシンプルになる

おわりに

マルチステージビルドを使用することで、Node.js が必要な JavaScript ライブラリインストールの処理を独立させることができます。
Elixir ベースのイメージをシンプルに保ちながら軽量なビルドプロセス構成を実現できるので、ぜひ静的アセット管理での活用を検討してみてください。

10
1
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
10
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?