docker composeでphoenixアプリを立ち上げるまで
表題の通り、docker composeを利用してphoenixアプリを立ち上げるまでの備忘録です。
立ち上げるまでの流れとか確実に忘れるだろうなあと思ったので記憶定着も兼ねて書いてみました。
最低限ではありますがvscodeのremote-containersでの設定ファイルも載せてあります。
「そこ違うよ」や「こうした方が良い」などあれば教えて頂けると幸いです。
環境
- mac OS
- Docker Desctop for Mac
- vscode
作るコンテナ
- phoenix
- postgresql
ディレクトリ構成
├── .devcontainer
│ └── devcontainer.json <- vscode用docker設定ファイル
│
├── .docker-config // dockerfileを置くディレクトリ
│ ├── app
│ │ └── Dockerfile
│ └── db
│ └── Dockerfile
├── db
│ └── data // DBマウント用のディレクトリ
│
├── .env <- docker-composeで使う環境変数
│
└── docker-compose.yml
Dockerfileは.docker-configディレクトリに入れてまとめてあります。
.envにはdocker-compose.ymlで使用する環境変数などを書くんですが、vscodeで使う際には『COMPOSE_PROJECT_NAMEが書かれた.envファイルはプロジェクトのrootディレクトリ直下に配置してください』と言われているのでプロジェクトのrootディレクトリに置いています。
その関係で、.envと同じ階層に置かないといけないdocker-compose.ymlもプロジェクトのrootディレクトリに置いています。ファイル設定
phoenix用Dockerfile
FROM elixir:1.13.1-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 do \
local.hex --force, \
local.rebar --force, \
archive.install --force hex phx_new
RUN apt-get...
で必要そうなものをインストール。
RUN mix do...
でphoenix関連のライブラリの更新。
DBサーバー用Dockerfile
FROM postgres:14.1-alpine
ENV LANG ja_JP.utf8
docker-compose.ymlと.envファイル
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:
ざっくりとした説明
app, db
: サービス名(任意の名前)
build
: Dockerfileが置かれているディレクトリを指定(context)
ports
: {ホスト側のポート}:{コンテナ側のポート}
command
: コンテナを立ち上げた時のデフォルトのコマンド
volumes
: 大体はホスト側とコンテナ側のディレクトリをマウントするときに使う
buildやvolumesで指定するパスはdocker-compose.ymlを基準とする相対パスです。
node_modulesのマウントを避けるためにvolumesを別途指定しています。(node_modules:/workspace/assets/node_modules
の部分)
COMPOSE_PROJECT_NAME=phx_docker_sample
APP_PORT=4000
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_PORT=5432
コンテナ名が分かりやすくなるのでCOMPOSE_PROJECT_NAMEをちゃんと定義しておきます。
(コンテナ名:{COMPOSE_PROJECT_NAME}{サービス名}{連番})
docker-compose.yml内でcontainer_nameを設定することで直接コンテナ名を指定することもできます。
devcontainer.json
{
// vscode上での表示名
"name": "phoenix app",
// devcontainer.jsonから見たときのdocker-compose.ymlの場所
"dockerComposeFile": "../docker-compose.yml",
// docker-compose.ymlで指定したサービス名
"service": "app",
// vs codeで開くディレクトリ
"workspaceFolder": "/workspace",
}
実行の流れ
各種設定ファイルを書き終えたら
プロジェクト作成 -> ファイルを少し編集 -> DB作成 -> サーバー立ち上げ
の流れで進んでいきます。
0. 動作確認
とりあえず各コンテナが動作するか確認。
> docker compose run --rm app mix --version
...
Erlang/OTP 24 [erts-12.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]
Mix 1.13.1 (compiled with Erlang/OTP 24)
> docker compose run --rm db psql --version
psql (PostgreSQL) 14.1
1. プロジェクト作成
確認ができたらプロジェクトを作成します。今回はmyapp
というアプリ名で作ります。(本当ならCOMPOSE_PROJECT_NAMEと同じ名前の方が良さそう)
> docker compose run --rm app mix phx.new . --app myapp
yes/noを聞かれるのでyesで答えていきます。
プロジェクト作成時のディレクトリ構成
.
├── .devcontainer
├── .docker-config
├── .env
├── .formatter.exs
├── .gitignore
├── README.md
├── _build
├── assets
├── config
├── db
├── deps
├── docker-compose.yml
├── lib
├── mix.exs
├── mix.lock
├── priv
└── test
2. ファイル編集
2.1. IPアドレスの設定
まずはconfig/dev.exsを編集します。
デフォルトだとhttp: [ip: {127, 0, 0, 1}, port: 4000]
になっているので、docker経由で接続できるようにhttp: [ip: {0, 0, 0, 0}, port: 4000]
に変更します。
...
config :mayapp, MyappWeb.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: {0, 0, 0, 0}, port: 4000],
check_origin: false,
code_reloader: true,
...
2.2. DBの設定
同じくconfig/dev.exs内のDBの接続情報を編集します。
...
config :myapp, Myapp.Repo,
username: "postgres", # 編集 (POSTGRES_USER)
password: "postgres", # 編集 (POSTGRES_PASSWORD)
hostname: "phx_docker_sample_db_1", # 編集 (コンテナ名)
database: "myapp_dev",
show_sensitive_data_on_connection_error: true,
pool_size: 10
...
usernameとpasswordはdocker-compose.ymlの部分で設定したものにします。
hostnameはdbのコンテナ名を設定してください。
上手いこと設定できているとサービス名("db")で大丈夫な気もするんですが、自分の環境だとコンテナ名にしないと繋がりませんでした。 ->サービス名でも繋がったので下で紹介します。
hostnameに関してはここで議論されています。
3. DB作成
hostnameをコンテナ名にした場合
> docker compose run --rm mix ecto.create
4. 立ち上げ
> docker compose up -d
よく見る画面が出てきたら成功です🎊
VSCodeで作業するとき
とりあえず起動してるコンテナを消去。
> docker compose down
プロジェクトをvscodeで開くとReopen in Container?
と聞かれるので選択。もしくは左下にある><
が重なったマークのボタンを押してReopen in Container
を選択。
そうするとdocker compose upを実行してくれた状態でappコンテナの中に入れます。
この時点では、devcontainer.jsonに設定をほとんど書いていないためコンテナ内にElixirLSなどの拡張機能が入っておらず、拡張機能の恩恵が得られない状態になっています。なので横のタブの拡張機能のところから自分の使いたい拡張機能をポチポチ選択して入れていきましょう。
詳しくは公式のリファレンスをば。
extenstionsとsettingsあたりは設定しておくと便利そう。
ちなみに、vscodeのremote containers機能を使えるようになるタイミングですが、docker compose run mix phx.new ...
でプロジェクトを作った後になります。(プロジェクトを作らないとdocker-compose.ymlで設定したコマンドmix phx.server
が実行できない)
プロジェクトを作った段階でremote containersを起動し、mix ecto.create
などの作業を進めた方が楽かもしれません。
追記1 hostnameをサービス名にした場合
docker compose up
によってコンテナを立ち上げた状態であればlocalhostをサービス名("db")に設定した状態でも通りました。
...
config :myapp, Myapp.Repo,
username: "postgres",
password: "postgres",
hostname: "db", # 変更
database: "myapp_dev",
...
> docker compose up -d
> docker compose exec app bash -c "mix ecto.create"
Compiling 14 files (.ex)
Generated myapp app
The database for Myapp.Repo has already been created
追記2 docker composeコマンドを使いたくない人向け
おそらくこっちの方が楽なので書いておきます。
変更は以下の通りで、docker-compose.yml内のcommandを消してttyをtrueに設定します。
version: "3"
services:
app:
build: ./.docker-config/app
ports:
- ${APP_PORT}:4000
- command: mix phx.server
+ tty: true
volumes:
...
これでphoenixのプロジェクトがない状態でもremote-containersを使えるようになります。
ディレクトリ構成は同じでDockerfile、docker-compose.yml、.env、devcontainer.jsonが書けたらvscodeでremote-containersを起動します。
あとはコンテナの中でmix phx.new ...
やらmix create.ecto
やらを実行できます。
config/dev.exs
の編集は2.ファイル編集の項と同じように行なってください。
このときDBのhostnameはサービス名("db")で大丈夫でした。
最後にmix phx.server
でサーバーを立ててサイトが見られれば完了です。
雑感
docker composeについて少しだけ理解できたので、これからはもっと積極的に使っていきたい。
Discussion