2
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?

DockerComposeでElixirPheonixの開発環境を整える

Last updated at Posted at 2025-02-09

概要

DockerComposeを使用して、Phoenixプロジェクトの開発環境を構築します。ローカル環境で開発する場合にも、Dockerコンテナ内で開発する場合にも対応可能な設定を目指します。

この記事は、開発環境を構築する学習過程をまとめたものです。今回は、dev環境で正常に動作することを目標としています。

リポジトリは以下になります

環境

この記事では、以下の環境で開発を行っています。

  • PC: MacBook
  • OS: macOS 15.2

またElixir(Erlang)はasdf上で管理しています。
それぞれのバージョンは以下になります。

% asdf current
Name            Version         Source                                    Installed
elixir          1.18.2-otp-27   /Users/linsei/Docker/Qiita/.tool-versions true
erlang          27.2.2          /Users/linsei/Docker/Qiita/.tool-versions true
nodejs          19.3.0          /Users/linsei/.tool-versions              true

手順

DockerComposeを使用してPhoenixの開発環境を構築するために、以下の手順を進めます。

  1. Phoenixプロジェクトを作成し、Dockerファイルを準備する
  2. docker-compose.ymlを作成する
  3. dockerコマンドを使用してサービスを起動する

Phoenixプロジェクトを作成し、Dockerファイルを準備する

まず、Phoenixプロジェクトを作成します。データベースは特に指定していないので、デフォルトでPostgreSQLが使用されます。

$ mix phx.new tuto_docker

この時点で、プロジェクトのディレクトリ構成は以下のようになっています。

tuto_docker % tree -L 1
.
├── README.md
├── _build
├── assets
├── config
├── deps
├── lib
├── mix.exs
├── mix.lock
├── priv
└── test

Dockerfileを作成する

次に、Phoenixを起動するためのDockerfileを作成します。
下記コマンドを実行すると、リリース用のDockerfileが自動生成されます。

以下のコマンドを実行します

mix phx.gen.release --docker

これによりphoenixを起動するためのDockerfileが作成されます。

詳しくはこちらをご覧ください。

生成後、プロジェクトのディレクトリ構成は以下のようになります。

tuto_docker % tree -L 1
.
├── (省略)
├── Dockerfile
└── rel

Dockerfile.devの作成・編集

次に、生成されたDockerfileを編集し、開発用のDockerfile.devを作成します。
まず、元のDockerfileをコピーしてリネームしましょう。

そしたら、以下のようにファイルを編集します。

Dockerfile.dev
ARG ELIXIR_VERSION=1.18.2
ARG OTP_VERSION=27.2.2
ARG DEBIAN_VERSION=bullseye-20250203-slim

ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-debian-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="debian:${DEBIAN_VERSION}"

FROM ${BUILDER_IMAGE} as builder

- RUN apt-get update -y && apt-get install -y build-essential git \
-   && apt-get clean && rm -f /var/lib/apt/lists/*_*

+ RUN apt-get update -y && apt-get install -y build-essential npm inotify-tools git \
+   && apt-get clean && rm -f /var/lib/apt/lists/*_*

- WORKDIR /app これを削除

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

# これより下を削除

この編集により、Phoenixを起動するために必要なパッケージインストールのみに内容を絞っています。
このDockerfile.devは、後ほど作成するdocker-compose.ymlで使用します。

postgres

次に、PostgreSQLをサービスとして起動するためのイメージを探します。
PostgreSQLのDockerイメージは以下から確認できます。

現在の最新イメージは 15.10-alpine3.21 です。
これを後ほどdocker-compose.ymlで指定します。

docker-compose.ymlを作成する

Phoenixプロジェクト内にdocker-compose.ymlを作成します。

以下のように基本構成を記述しておきます。

services:
  web:
    (後で記述)
  db:
    (後で記述)  
volumes:
  dbdata:

ここで定義しているvolumesは、データ永続化のために使用する名前付きボリュームです。dbdataという名前で作成します。

webサービスの設定

webはPhoenixを起動するサービスです。次のように記述します。

  web:
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - .:/work
    working_dir: /work
    links:
      - db
    environment:
      DB_HOST: db
    ports:
      - 4000:4000
    command: tail -f /dev/null

各セクションの説明

  • build: Dockerfile.devをDockerfileに指定します
  • volumes: 現在のディレクトリをコンテナ内の/workにマウントします
    • コンテナ内でローカルと同じディレクトリを使用するために共有が必要です
  • working_dir: コンテナ内での作業ディレクトリを/workに設定します
  • links: dbサービスと通信できるようにリンクを設定しています
  • environment: 環境変数DB_HOSTにdbサービスのホスト名を設定します
  • ports: ホストのポート4000をコンテナ内の4000番ポートにマッピングします
    • config/dev.exsでサーバーに使用するポートと一致するようにしてください
  • command: コンテナが即時終了しないようにするコマンドを実行します

dbサービスの設定

dbサービスはPostgreSQLを起動するための設定です。以下のように記述します。

  db:
    image: postgres:15.10-alpine3.21
    volumes:
      - dbdata:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: postgres
    ports:
      - 5432:5432

各セクションの説明

  • volumes: コンテナ内の/var/lib/postgresql/dataをdbdataボリュームにマウントしています。これにより、データがコンテナを削除しても永続化されます。
  • environment: PostgreSQLの起動時に必要な環境変数を設定します
    • POSTGRES_PASSWORDは必須項目です
    • このパスワードはconfig/dev.exsの設定と一致させてください
  • ports: ホストのポート5432をコンテナ内の5432にマッピングしています
    • PostgreSQLのデフォルトポート番号は5432です

docker-compose.ymlの全文

最終的に記述を終えたdocker-compose.ymlの全体は、以下のリポジトリから確認できます。

dev.exsの設定を変更する

dev.exsファイルを編集し、データベースのホスト名とサーバーのIPアドレスを設定します。

import Config

# データベース設定
config :tuto_docker, TutoDocker.Repo,
  username: "postgres",
  password: "postgres",
- hostname: "localhost",
+ hostname: System.get_env("DB_HOST") || "localhost",
  database: "tuto_docker_dev",
  stacktrace: true,
  show_sensitive_data_on_connection_error: true,
  pool_size: 10

# サーバー設定
config :tuto_docker, TutoDockerWeb.Endpoint,
- http: [ip: {127, 0, 0, 1}, port: 4000],
+ http: [ip: {0, 0, 0, 0}, port: 4000],
  # 略

dockerコマンドでサービスを起動する

必要な設定が完了したら、以下のコマンドを実行してサービスを起動します。

% docker compose up -d
% docker compose exec web /bin/bash
root@コンテナID:/work# iex -S mix phx.server

最後のコマンドを実行すると、通常通りPhoenixサーバーのページを表示できるはずです。

コンテナから起動するメリット

コンテナからPhoenixアプリケーションを起動するメリットを説明します。

コンテナ内で環境変数を設定することで、ローカル環境に余計な環境変数を残さずに済みます。例えば、何のために設定したかわからない環境変数がローカルに残っていると管理が煩雑になります。
一方、コンテナでは環境変数をコンテナ内だけで適用し、不要なときは一括で削除できるため、開発環境をクリーンに保つことができます。

環境変数を使ったアプリケーション設定の例

例として、環境変数MYNAMEを使用する設定を例を示します。

config/config.exs

import Config

# 略

config :tuto_docker,
  myname: System.get_env("MYNAME") || "たぬき"

# 略
docker-compose.yml
    environment:
      DB_HOST: db
      MYNAME: "ブラックたぬたぬ"

環境に応じてhttp://localhost:4000/の表示は以下のように変化します。

  • ローカルで起動: I am たぬき.

  • コンテナで起動: I am ブラックたぬたぬ.

まとめ

ここまでの設定を行うことで、Phoenixプロジェクトをローカル環境でもコンテナ環境でも開発できるようになります。

おまけ

データベースをコンテナ内で作成することで、ローカル環境に不要なデータベースを作成せずに済むというメリットがあります。

curdブランチを用意しています。
以下の手順でローカルとコンテナ環境の違いを確認してみてください。

  1. コンテナでサーバーを起動し、CRUDページにデータを入力します
  2. サービスを停止し、ローカルでサーバーを起動します
  3. コンテナ内のデータがローカル環境には反映されていないことが確認できます
2
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
2
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?