概要
ほとんど個人的メモです
自身でよく構築することの多い以下の環境を毎度、調べながら作るのが面倒なのでまとめたって感じです
- React(front end)
- phoenix(backend, elixir web framework)
- postgres(open source database)
毎度悩むのが、dockerのimageをpullしてきたけど、どの場所、どのタイミングでcreate-react-app
なりmix phx.new ...
を実行するかなといったところ
個人的なベストプラクティスとしてはlocal環境で作成して依存環境ガァ^〜で何度も怒られてつらい思い出があるので
作成したcontainerの内部で上記のコマンドを実行してプロジェクトを作成し
生成されたプロジェクトをcontainerからlocal環境にコピーしてくるという方針を採用してみた
プロジェクトの生成環境が実行環境と同じになるというメリットがあるが、準備に多少の手間が発生する
しかしながら、やることは毎度同じなので大した苦労ではないなーと感じている(まだ2回しか作ってないけど)
やってることは色んな記事からアイディアをパクってまとめただけです
記事の一番最後にreferenceをまとめているのでご参照下さい
共通作業
pathはどこでも構わないので適当にdocker-composeをwrapするディレクトリを生成しておきます
$ mkdir react-phoenix-postgres
$ cd react-phoenix-postgres
以下の作業は全て、このディレクトリ内で行います
ちなみにDockerとdocker-composeについてはinstall済みという前提で進めていますのでお願いします
React環境の構築とcreate-react-appの実行
まずはReactのための環境から。node imageをbaseにした環境を用意して、そこでReactのプロジェクトを作成します
さっそくReactのためのディレクトリとDockerfileを生成
$ mkdir frontend
$ cd frontend
$ touch Dockerfile
続いて最低限の設定をDockerfileに記述
FROM node:12.2.0-alpine
RUN mkdir /app
WORKDIR /app
# nodeとnpmがinstallされているか確認用。省略しても問題なし
RUN node -v && npm --version
このDockerfileを使ってcontainerを作成します
-t というオプションの後に記述されているのは割り当てるタグと呼ばれるものです
後にタグを使ってコマンドを実行するので視認性のあるものにしておくと良いかと思います
$ docker build -t react_test:dev .
このコマンドを実行することで手元のDockerfileを元にcontainerが作成されます
メッセージログが流れてしまったので恐縮ですが
RUN node -v && npm --version
12.2.0
6.xx
Successfully built **containerID**
のようなメッセージが出ていればnode環境の作成は完了です
次にcreate-react-app
を実行するための用意をします
create-react-app
のコマンドは一度しか使用しないので、dockerのcontainerにaccessして、直接installします
まずはcontainerにaccessするためにdockerのcontainerを立ち上げます
以下オプションの詳細ですが、無視してコマンドを打って頂いて構いません。一応書いておきました
- d -> backgroundでdocker daemonを実行
- t -> tty true -> docker containerを立ち上げたままにしておく
- p -> spec port -> 立ち上げるportとexposeするportの指定
- name -> containerに名前を割り当てる(タグとは別で実行中のみ有効と判断しています)
- react_test:dev 先ほど付与したタグ名
cotainerを立ち上げます
$ docker run -dt --name react_train -p 3000:3000 react_test:dev
よくあるミスとしては以下が候補に上がります
- すでにportが使用されている(別のportにするか重複元の環境を停止させる)
- 同盟の--nameが割り当てられたcontainerがすでにUPされている(docker stop containerIDで停止させる)
問題なく進められていれば先ほど立ち上げたcontainerにashを使ってアクセスします
なんでash?ってなりますけど、alpineではshellにashが使われているそうで、bashやらにすると怒られます
$ docker exec -it react_train ash
無事にアクセスができるとroot#containerID
のようなプロンプトが立ち上がります
まずは適当にnode.jsとnpmのversionでも確認しておきます
node -v && npm --version
12.2.0
6.x.x
無事にinstallされているようなので、次にcreate-react-app
コマンドが使いたいのでnpm経由でinstallします
ここは-gをつけてglobal installにしておいてください。package.jsonファイルが現状のディレクトリにないので-gをつけないと怒られます
ついでにcreate-react-app
も実行します
$ npm i -g create-react-app && create-react-app app-name
Happy Hacking!と準備できたからserver立てれるよって文言が表示されていればOKです
これでプロジェクトの生成は完了です。あとはこの作成したプロジェクトをlocal環境にcopyしてあげるのみ
exit
と入力し現在、アクセス中のcontainerから離脱します
続いて、以下コマンドを使ってlocal環境にプロジェクトをcopyします
$ sudo docker cp react_train:/app/app-name .
これでlocal環境に生成したプロジェクトがcopyされた
しかしながらcopyされたプロジェクトの権限をl
コマンドで確認してみるとオーナーがrootになっていることがある
そのためchown
を使ってオーナーを変更しておきます(後にハマってだるいことになったので
sudo chown -R login-user-name app-name
再びl
コマンドで確認してオーナーが自身のユーザーネームになっていればOKです
これでReactのプロジェクトの生成は完了です
phoenix(Elixir)環境の構築とmix phx.newでのプロジェクト作成
やることはReact環境を用意した時と全く同じです。まずはディレクトリとDockerfileを用意します
$ mkdir backend
$ cd backend
$ touch Dockerfile
やはり最低限の設定をDockerfileに記述
FROM elixir:alpine
WORKDIR /app
RUN yes | mix local.hex
RUN yes | mix archive.install https://github.com/phoenixframework/archives/raw/master/phx_new.ez
RUN mix local.rebar --force
# elixirがinstallされているかの確認用(省略可)
RUN elixir -v
先ほど同様に作業を進めていきます
$ docker build -t elixir_test:div .
$ docker run -dt --name elixir_train -p 8080:8080 elixir_test:dev
$ docker exec -it elixir_train ash
これでphoenixのプロジェクトの作成準備は整いましたので早速...
mix phx.new backend
これでphoenixのプロジェクトが生成されたので同様にlocal環境にcopyします
$ sudo docker cp elixir_train:/app/backend .
phoenixのプロジェクトの生成は以上ですが、database設定を行う必要があるためdocker-composeの設定と共に行なっていきます
docker-compose.ymlの作成とdatabaseの設定
これまで行なってきたdocker runをdocker-composeを使ってまとめてできるようにしてあげます
記述量は若干ありますが、どれも1つずつ見るとやっていることは大したことではないのでご心配なく
レゴを積み上げるようなノリで記述出来ます
version: "3"
services:
frontend:
build:
context: test # buildしたいDockerfile(node)が格納されているディレクトリ
dockerfile: Dockerfile
container_name: react_frontend # cotainerに命名
volumes:
- "./test:/app/test" # 先ほど作成したreactプロジェクトのディレクトリ名
ports:
- "3001:3000" # 内部ポートと外部ポートをexpose
environment:
- NODE_ENV=development
tty: true # 起動を継続するように指定
working_dir: "/app/test" # マウントしたプロジェクトのディレクトリを指定(package.jsonがあるため)
command: "npm run start" # 起動時に実行させるcommand
backend:
build:
context: elixir
dockerfile: Dockerfile
volumes:
- "./elixir/backend:/app/backend"
container_name: elixir_backend
ports:
- "8080:4000"
tty: true
working_dir: "/app/backend"
command: ash -c "mix deps.get && mix phx.server"
depends_on: # databaseを使いたいので下記記述のdbに連携しておく
- db
db:
image: postgres:12.0 # ymlの中でimageを指定
container_name: postgres_for_phoenix
tty: true
volumes:
- "./postgres/lib:/var/lib/postgres"
environment:
- MYSQL_ROOT_PASSWORD=rootpassword
- POSTGRES_USER=root
- POSTGRES_PASSWORD=root_password
- POSTGRES_INITDB_ARGS="--encoding=UTF-8"
- POSTGRES_HOST=db
ports:
- "5432:5432"
やっていることはかなり共通事項が多いので特に難しくないです
インフラを構築する才能がないねーと言われた僕ですら書けるのがdocker-composeです。最高か
postgresのマウント用に指定したディレクトリが現在ない状態ですので、作っておきます
$ mkdir -p mysql/lib
configディレクトリ内部のdev.exsの最下部を編集します
先ほどdocker-compose.ymlに環境変数として用意したものに値を変更します
./project-name/config/dev.exs
config :backend, Backend.Repo,
adapter: Ecto.Adapters.Postgres,
username: "root",
password: "root_password",
database: "backend_dev",
hostname: "db",
pool_size: 10
準備も完了したのでcontainer達を立ち上げてみます
$ docker-compose up --build
frontendとdatabaseは特に問題なく立ち上がるかと思いますが、backendのcontainerはdatabase is not exist
的なmessageを出し続けているかと思います
なので接続するためのdatabaseを作ってあげましょう
先ほどdocker-compose up --build
でcontainerを立ち上げているので、postgresのimageをbuildして生成されたcontainerが立ち上がっているはずです
docker ps
で確認します
$ docker ps
9f676931727a postgres:12.0 "docker-entrypoint.s…" 2 days ago Up 49 seconds 0.0.0.0:5432->5432/tcp postgres_for_phoenix
立ち上がっているのが確認できたら、このcontainerにアクセスして、内部にdatabaseを作成します
postgresのプロンプトを立ち上げる
$ docker exec -it container-id /bin/bash
psql
root=#
先ほど./project-name/config/dev.exsに指定した名前のdatabaseを作成します
root=# create database backend_dev;
CREATE DATABASE
l
で作成したdatabaseが存在していることを確認できたらdatabaseの作成は完了です
これで全作業が終了
Reactとphoenixのそれぞれのプロジェクトに対してdocker-compsoe.ymlで設定したportにアクセスしてみて下さい
でそれぞれ、welcomeページが表示されていれば成功です(phx->no-webpackを指定し忘れてcssが読み込まれていない)
docker ps
で確認すると3つのcontainerが立ち上がっているはずです
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a9457b933808 react_train_frontend "npm run start" 52 seconds ago Up 49 seconds 0.0.0.0:3001->3000/tcp react_frontend
a80a6a939350 react_train_backend "ash -c 'mix deps.ge…" 2 days ago Up 47 seconds 0.0.0.0:8080->4000/tcp elixir_backend
9f676931727a postgres:12.0 "docker-entrypoint.s…" 2 days ago Up 49 seconds 0.0.0.0:5432->5432/tcp postgres_for_phoenix
containerを終了したい時はdocker-compose down
とすればOKです
参考文献