【2023年版】DockerでElixir/Phoenix1.7系の環境を立ち上げる

# 前提
- Dockerはすでにインストール済みとします。

# 準備: ファイル構成
まずはdockerコマンドを実行する上で必要になるディレクトリとファイルを作成しましょう。
```:ファイル構成
├── .devcontainer
│   └── devcontainer.json  <- vscode用docker設定ファイル
│
├── .docker-config  // dockerfileを置くディレクトリ
│   ├── app
│   │   └── Dockerfile
│   └── db
│       └── Dockerfile
├── db
│   └── data  // DBマウント用のディレクトリ
│
├── .env  <- docker-composeで使う環境変数
│
└── docker-compose.yml
```

## Dockerfile
Phoenixサーバ用のDockerfile
```dockerfile:.docker-config/app/Dockerfile
FROM elixir:1.15.4-slim

WORKDIR /workspace

RUN apt-get update && apt-get install -y \
    inotify-tools \
    git \
    npm \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

RUN mix local.hex --force && \
	mix archive.install hex phx_new 1.7.7 --force && \
	mix local.rebar --force
```

DBサーバ用のDockerfile
```dockerfile:.docker-config/app/Dockerfile
FROM postgres:14.1-alpine

ENV LANG ja_JP.utf8
```

## docker-compose.yml
```yaml:docker-compose.yml
version: "3"

services:
  app:
    build: ./.docker-config/app
    ports:
      - ${APP_PORT}:4000
    command: mix phx.server
    volumes:
      - .:/workspace
      - node_modules:/workspace/assets/node_modules

  db:
    build: ./.docker-config/db
    environment:
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    ports:
      - ${POSTGRES_PORT}:5432
    volumes:
      - ./db/data:/var/lib/postgresql/data

volumes:
  node_modules:
```

## 環境変数ファイル
```:.env
COMPOSE_PROJECT_NAME=phx_docker_sample # ここで指定した名前でイメージで作成される

APP_PORT=4000

POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_PORT=5432
```

# 実施: 立ち上げ
必要なファイルが準備できたら、いよいよdockerコマンドを叩いてコンテナを立ち上げていきましょう。

## Phoenixプロジェクト作成
まずはPhoenixプロジェクトを以下のコマンドで作成していきましょう。
```shell
cd プロジェクトディレクトリ # 先ほどプロジェクトの準備したルートディレクトリに移動
docker compose run --rm app mix phx.new . --app アプリ名
```
「アプリ名」は任意で構いません。
このアプリ名はPhoenixプロジェクト内の名前空間として利用されます。
この後の作業でも使いますので覚えておくと良いでしょう。

## Phoenixサーバの設定を変更
初期状態では、「Phoenixサーバへのアクセス」と「DBサーバへの接続」ができないので、できるように設定を変更していきます。
Phoenixでは`config`ディレクトリに設定関連のファイルがまとめてあり、今回は開発環境に関する設定を行うため`dev.exs`ファイルを変更していきます

### IPアドレスを更新
「Phoenixサーバへのアクセス」を可能にするための変更です。
`http: [ip: {127, 0, 0, 1}, port: 4000]`を`http: [ip: {0, 0, 0, 0}, port: 4000]`に変更しましょう。

:::note warn
「アプリ名」のところは、先ほどのPhoenixプロジェクト作成でつけた名前になってますので気をつけてください
:::

```diff_elixir:config/dev.exs
...
config :アプリ名, アプリ名.Endpoint,
  # Binding to loopback ipv4 address prevents access from other machines.
  # Change to `ip: {0, 0, 0, 0}` to allow access from other machines.
-  http: [ip: {127, 0, 0, 1}, port: 4000],
+  http: [ip: {0, 0, 0, 0}, port: 4000],
  check_origin: false,
  code_reloader: true,
...
```

### データベースの接続設定を変更
こちらも`config/dev.exs`の変更です。

:::note warn
例に漏れず「アプリ名」に依存します。
自分の環境の手元のコードも参考にしながら進めてみてください。
:::

```diff_elixir:config/dev.exs
- config :アプリ名, アプリ名.Repo,
-   username: "postgres",
-   password: "postgres",
-   hostname: "localhost",
-   database: "アプリ名_dev",
-   stacktrace: true,
-   show_sensitive_data_on_connection_error: true,
-   pool_size: 10
+ config :アプリ名, アプリ名.Repo,
+	username: "postgres", # 編集 (POSTGRES_USER)
+	password: "postgres", # 編集 (POSTGRES_PASSWORD)
+	hostname: "db", # 編集 (コンテナ名orサービス名)
+	database: "アプリ名_dev",
+	show_sensitive_data_on_connection_error: true,
+	pool_size: 10
```

## データベースを作成
必要な設定が全て完了したらDBサーバに接続できるようになっているはずなのでデータベースを作成していきます。
以下のコマンドを連続で実行してください。
```shell
docker compose run --rm app mix --version
docker compose run --rm db psql --version
docker compose up -d
docker compose run --rm app mix ecto.create #DBを作成
```

# 動作確認
`http://localhost:4000/`にアクセスしてください。

http://localhost:4000/

![スクリーンショット 2023-08-29 16.44.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195078/a9683105-802e-ef81-10af-338425a053a8.png)
上記のような画像が表示されたらOKです！
お疲れ様でした。

# 参考
- [docker composeでphoenixアプリを立ち上げるまで(Zenn) by tnkaさん](https://zenn.dev/tnka122/articles/abb6149f5a5f6c)