概要
ほとんど個人的メモです
自身でよく構築することの多い以下の環境を毎度、調べながら作るのが面倒なのでまとめたって感じです
- 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 # cotainerIDが表示され、terminalが入力可能状態になれば成功
よくあるミスとしては以下が候補に上がります
- すでに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でも確認しておきます
# dockerのcontainer内部 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します
# 現在のカレントディレクトリにプロジェクトを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のプロジェクトの作成準備は整いましたので早速...
# dockerのcontainer内部(phoenixの生成に関するオプションは適宜、自身で付与してください(no-webpackを打ち忘れたorz))
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: # reactへのsetting 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 # phoenixへのsetting(ほとんどReactと同じ) 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 # postgresへのsetting db: image: postgres:12.0 # ymlの中でimageを指定 container_name: postgres_for_phoenix tty: true volumes: - "./postgres/lib:/var/lib/postgres" # postgres用の環境変数をset 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
phoenixのdatabase設定
configディレクトリ内部のdev.exsの最下部を編集します
先ほどdocker-compose.ymlに環境変数として用意したものに値を変更します
./project-name/config/dev.exs
config :backend, Backend.Repo, adapter: Ecto.Adapters.Postgres, username: "root", # POSTGRES_USER password: "root_password", # POSTGRES_PASSWORD database: "backend_dev", # ecto.createコマンドを使わないので変更しても良いし、しなくても良い hostname: "db", # service名 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です