今回達成すること
3つのファイルを作成し編集していきます。
- .gitignore
- .env
- docker-compose.yml
今回の作業ディレクトリはrootです。お間違えのないように!
必要なファイルたちを作成する
まずは作業ディレクトリに移動しましょう。
今、frontディレクトリにいる方は一個上のディレクトリに戻ります。
front $ cd ..
3つのファイルを作成します。
- .gitignore
- .env
- docker-compose.yml
root $ touch {.gitignore,.env,docker-compose.yml}
確認しておきましょう。
root $ ls -a
. .env .gitignore docker-compose.yml
.. .git api front
-a
オプション ... 隠しファイルも表示するオプション。
.gitignoreを編集する
Gitの管理下に置きたくないファイルやディレクトリを管理するためのファイルです。
ここに記述したファイルは、Gitのpushで公開できなくなり、ローカルだけで参照できるファイルとなります。
今回は「.env」のファイルを管理下に置かないよう指定します。
.gitignore
/.env
.envを編集する
「.env」は環境変数を管理するために使われるファイルです。
環境変数とは、開発・テスト・本番などの環境ごとに変化する値を入れる変数となります。
ただ今回は、環境変数を管理すると言うよりか「docker-composeファイル、Dockerfile、コンテナ間で共通する値を変数化してDocker管理を楽にする」ことを目的として.envファイルを使用します。
下記のように編集しましょう。
.env
# commons
WORKDIR=app
CONTAINER_PORT=3000
API_PORT=3000
FRONT_PORT=8080
# db
POSTGRES_PASSWORD=password
docker-compose.ymlを編集する
ちょっとまって!!docker-compose.ymlってなんだよ!という方はこちらを先にお読みください。
下記のように編集しましょう。
docker-compose.yml
version: '3.8'
services:
db:
image: postgres:12.3-alpine
environment:
TZ: UTC
PGTZ: UTC
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
volumes:
- ./api/tmp/db:/var/lib/postgresql/data
api:
build:
context: ./api
args:
WORKDIR: $WORKDIR
environment:
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
volumes:
- ./api:/$WORKDIR
depends_on:
- db
ports:
- "$API_PORT:$CONTAINER_PORT"
front:
build:
context: ./front
args:
WORKDIR: $WORKDIR
CONTAINER_PORT: $CONTAINER_PORT
command: yarn run dev
volumes:
- ./front:/$WORKDIR
ports:
- "$FRONT_PORT:$CONTAINER_PORT"
depends_on:
- api
docker-compose.ymlを一つ一つ説明するぞう
分かる方はすっ飛ばしてください。
version: '3.8'
Composeファイルのバージョンを指定しています。
ここのバージョンはdockerのバージョンに依存します。
3.8
の場合、必要なdockerのバージョンはv 19.03.0
以上です。ターミナルから確認しておきましょう。
root $ docker -v
Docker version 19.03.8
Composeファイルは、バージョンによって書き方が変わります。
バージョンを確認した上でリファレンスをお読みください。
services:
この下で各コンテナの設定を行います。
ちなみにdb
、api
、front
はサービス名と言います。
dbサービス
Railsに必要なDBコンテナを立ち上げています。
このコンテナは開発環境でしか利用しません。
本番環境ではHerokuのアドオンのPostgreSQLを使用します。
images: <ベースイメージ>
dbサービスはDockerfileを持っていませんので、ここでベースイメージを指定しています。
environment: <環境変数キー: 環境変数の値>
環境変数をキー: 値
で指定しています。
ここで指定した環境変数はコンテナ内に直接渡すことができます。
-
TZ: UTC
OSのタイムゾーンを指定しています。
PostgreSQLのタイムゾーンを指定しています。本番環境に合わせ世界標準時間を設定します。
Herokuが推奨しているタイムゾーンはUTC
-
PGTZ: UTC
PostgreSQLのタイムゾーンを指定しています。
PGTZ環境変数は、接続時にサーバにSET TIME ZONEコマンドを送信するために、libpqクライアントが使用します。
2020年12月09日 追記
PostgreSQLは、タイムゾーンが、コマンドオプション、もしくは「postgresql.conf」で指定されていない場合、OSの
TZ
環境変数を参照し、タイムゾーンを設定します。AlipneLinuxのPostgreSQLの場合、「postgresql.conf」内で
timezone = 'UTC'
と設定されているため、PGTZ
環境変数を設定しないとタイムゾーンを変更することができません。なお、デフォルトの値は
UTC
で変わりはないですが、第三者から見ても明示的になるよう、UTC
を設定しています。postgresql.confの確認方法
# コンテナに入る $ docker-compose run --rm db sh # postgresql.confのファイパスの検索 $ find . -name postgresql.conf => ./var/lib/postgresql/data/postgresql.conf # ファイル内容の確認 $ cat /var/lib/postgresql/data/postgresql.conf
本来TZ
だけでタイムゾーンが設定できるはずですが、うまくいかなかったのでPGTZ
も設定しています。PGTZ環境変数は、libpqクライアントが接続時にサーバにSET TIME ZONEコマンドを送信するために用いられます。つまり接続時にコマンドを実行してタイムゾーンを変更しているってことだね!(汗
libpq ... クライアントプログラムからPostgreSQLのバックエンドサーバに問い合わせを渡し、その結果を受け取るためのライブラリ関数の集合体のことです。
PostgreSQLにリクエストを渡す関数ってことかな?よく分からん!
-
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
POSTGRES_PASSWORDというキーはRails内でも使用するため、
environment
に指定してコンテナに渡しています。$POSTGRES_PASSWORDは
.env ファイルの値を展開しています。ここは「password」という値に展開されます。
volumes: <ローカルのパス : コンテナのパス>
ここでデータベースの値を永続化しています。
そもそもローカルマシン(PCを指す)とDockerコンテナは別空間にあります。
ですので、DBコンテナにデータを保存しても、コンテナを削除してしまえば保存したデータは全て消えてしまいます。
そこでデータベースの値やファイルなどのデータを永続化する仕組みがこのvolumes(ボリューム)
となります。
ボリュームで指定したデータはコンテナを削除しても消されることはなく、次コンテナが立ち上がったときに既存のデータをコピーします。
この仕組みのおかげでコンテナを削除しても続きから作業が行えるのですね。
参考
build: <Dockerfileパス>
サービスのベースイメージにDockerfileを指定する場合には、このbuild
を使用します。
ここには参照するDockerfileのパスを指定します。
本来build: ./api
という形で構いませんが、下で記述するargs
オプションを使用するのでcontext
でファイルパスを指定しています。
-
.
... ファイルパスを指定するピリオドは、docker-compose.ymlのあるディレクトリを表します。Dockerfileが同列にある場合は
.
のみの指定となります。
args: <変数キー: 変数の値>
ここにはDockerfileに渡す値を指定します。(正確にはDockerイメージをビルドする際に渡す引数)
ここで指定した値をDockerfileで受け取るにはARG
命令を使用します。
今回は下記の流れで環境変数を受け渡ししています。
1. .env
WORKDIR=app
2. docker-compose.yml
args:
WORKDIR: $WORKDIR
3. Dockerfile
ARG WORKDIR
RUN echo ${WORKDIR}
=> app
depends_on: - <依存先のサービス名>
サービスの依存関係を定義します。
ここで指定したサービスは、対象のサービスを起動すると自動で起動します。
例えば下記のケースだと、api
サービスを起動するとdb
サービスも連動して起動します。
また、「api
サービスより先にdb
サービスを起動してくれ」といった起動の順番も指定されます。
- 今回のComposeファイルの起動順序 ... 1. db => 2. api => 3. front
api:
...
depends_on:
- db
ports: - "ホストマシンのポート番号:コンテナのポート番号"
公開ポート番号を指定します。
下記の場合は「コンテナの3000ポートを、ブラウザ上で8080で参照する」という指定になります。
ports:
- "8080:3000"
-
注意点
YAMLファイルは
aa:bb
を時刻として解釈するので、必ずダブルクォーテーションで囲むようにしてください。と本にありましたが、実際囲まなくても正常に動きました。ただ囲んでおく方が間違い無いでしょう。
command: <コンテナで実行するコマンド>
コンテナに対して実行したいコマンドを記述します。
DockerfileのCMD
命令と同じ扱いです。
なぜfront
サービスだけ指定しているのか?
Nuxt.jsの場合は、開発環境と本番環境で起動コマンドが変わるためです。
-
開発 ...
$ yarn run dev
package.jsonの
nuxt
スクリプトが実行される -
本番 ...
$yarn run start
package.jsonの
nuxt start
スクリプトが実行される
本番環境の起動コマンドは、のちに出てくるheroku.ymlのrun
で指定します。
今回のまとめ
今回は3つのファイルを作成して編集しました。
- .gitignore
- .env
- docker-compose.yml
と同時にComposeファイルの記述方法も学べましたね。これで完璧!
いよいよ次回は!?
以上でDockerイメージを構築するファイル群が揃いました。
現在の作成ファイル
root
├── api
│ ├── Dockerfile
│ ├── Gemfile
│ └── Gemfile.lock
├── front
│ └── Dockerfile
├── .env
├── .gitignore
└── docker-compose.yml
次回はRailsアプリを作成します!!!
みなさんお楽しみの$ Rails new
〜!
修正情報
-
2020年12月09日
目次)#environment: <環境変数キー: 環境変数の値> の内容を一部修正、追記しました。