LoginSignup
3
2

More than 3 years have passed since last update.

[備忘録] [初心者] Docker Compose / Rails(公式doc.)について自分用補足#2 (docker-compose.yml)

Last updated at Posted at 2020-07-06

はじめに

前回の投稿、
[備忘録] [初心者] Docker Compose / Rails(公式doc.)について自分用補足#1 (Dockerfile, entrypoint.sh)
に続き、Docker + Raislの公式チュートリアルの内容を丁寧に追って理解を試みる取り組みのアウトプットです。

あくまで学習過程の私的なアウトプットなので、信頼性の高い情報は、各リンク先を参照していただければと思います。

本編

クィックスタート: Compose と Rails | Docker ドキュメント
上記のチュートリアルで扱われる、docker-compose.ymlの理解のためのメモです。
一部、深掘りのために、PostgreSQL関連や、公式イメージのDockerfileの内容も扱います。

docker-compose.ymlの概観理解に役立ったリンク例

docker-compose.yml

docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

version:

使用するDocker Composeのバージョン

services:

#サービス設定リファレンス | Compose ファイル バージョン 3 リファレンス | Docker ドキュメント
アプリケーションを構成する各サービスのコンテナを設定します。
今回扱うチュートリアルでは、2つのサービスdb, webによってサービス全体を構成しています。

  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

db:

任意のサービスの名称として"db"が付けられています。
公式のサンプルでは、下位にimage, volumes, environmentの設定項目が続きます。

    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
image:
image: postgres

#image | Compose ファイル バージョン 3 リファレンス | Docker ドキュメント

コンテナを起動させるイメージの設定とあります。
今回は、PostgreSQLのDocker公式イメージを用います。
デフォルトのコンテナOSは、Debian:stretch、オプションでAlpineも選択できるようです。

volumes:
volumes:
  - ./tmp/db:/var/lib/postgresql/data

#volumes | Compose ファイル バージョン 3 リファレンス | Docker ドキュメント

マウントホストパスや名前つきボリュームを、サービスに対するサブオプションとして指定します。

まず、マウントという言葉もピンときていなかったのですが、下記の質疑がとても分かりやすかったです。
filesystems - understanding "mount" as a concept in the OS - Unix & Linux Stack Exchange
What is a mount point in Linux/Unix? - The Linux Juggernaut
特に、耕地の管理とディスクドライブの管理とのアナロジーを示した例え話はとても面白いと感じました。
各パーティション内のデータにアクセスするための"門"を設けることがマウントであるということに納得しました。

また、ボリュームの概念が分かっていないので調べました。
 ボリュームの利用 | Docker ドキュメント

ボリュームとは、Docker コンテナーにおいて生成され利用されるデータを、永続的に保持する目的で利用される仕組みです。

このように、システムを終了してもデータが消失しないような仕組みを設けることを永続化と呼ぶようです。(不揮発性メモリへの保存、回復可能にしておくなど)
 永続性 - Wikipedia
 What Is Persistent Data? - DZone Database

では、volumeに設定されている./tmp/db:/var/lib/postgresql/dataとはどういうディレクトリなのでしょうか。
ボリュームの利用 | Docker ドキュメントには、設定の書式として、[SOURCE:]TARGET[:MODE]という書式が適用されることが説明されています。
この書式にあてはめると、下記表の対応となります。

書式 記述例 意味
[SOURCE:] ./tmp/db: ホストのパスあるいはボリューム名
TARGET /var/lib/postgresql/data ボリュームがマウントされているコンテナのパス
[:MODE] none 読み込み専用ro, 読み書き可能rw. デフォルトは後者

つまり、コンテナから見たとき、/var/lib/postgresql/dataの中身として、ホストOS上の./tmp/dbを見ている状態になります。

これはこういうものだと、割り切ってしまうのもひとつかもしれません。
ただ、もう少し自分の中で具体的根拠を伴った意味付けが欲しいと思いました。

/var/lib/postgresql/dataとは何か

このディレクトリについては、PostgreSQLのリファレンスに説明がありました。

データベースの物理的な格納 - PostgreSQL 8.0.4 文書

データベースクラスタで必要となる全てのデータは、クラスタのデータディレクトリ内に格納され、通常 PGDATA として参照されます。 (そのディレクトリを定義するために使用できる環境変数名です。) 通常の PGDATA の位置は /var/lib/pgsql/data です。

データベースクラスタはPostgreSQL独自の用語らしいです。
 第18回 データベースクラスタ - OSS-DB道場
 sql - What's a PostgreSQL "Cluster" and how do I create one? - Stack Overflow

PostgreSQLでは、1つのサーバインスタンス上に複数のデータベースを構成することができ、PostgreSQLで言う"クラスタ"とは、そうした1つ以上のデータベースの集合体を含む共有ディレクトリを管理する仕組みであると解釈しました。
そして、それらに関わるデータが格納される場所がPGDATAの環境変数で参照され、その保存先が通常では/var/lib/pgsql/dataに指定してあると。

/var/lib/という階層の意味 : ファイルシステム階層標準 (FHS)

他でもよく見る/var/libについても意味を把握しておこうと思いました。
LinuxやUnix系のOSのディレクトリの階層は、ファイルシステム階層標準によって定められていることを知りました。
Filesystem Hierarchy Standard - Wikipedia(JP)

Filesystem Hierarchy Standard(ファイルシステム・ヒエラルキー・スタンダード、FHS、ファイルシステム階層標準)は、Linuxを含むUNIX系オペレーティングシステムでの主なディレクトリとその内容を定めたものである。

2020-07現在の最新版はFHS 3.0で、下記リンクからHTMLやPDFなどの形式で閲覧することが出来ます。

/varは、動的に変化する変数データファイルを格納するもので、、ネットワーク上で他のコンピュータと共有されないもの。
/var/libは、アプリケーションやシステムに関連する状態情報を保持。

FHSの解説では、アプリケーションは/var/libのサブディレクトリを使用しなければならない、とあるので、/var/lib/pgsqlはその規則に則ったPostgreSQL用のデータ格納先であることが伺えます。

PostgreSQLの公式イメージにおける/var/lib/postgresql/dataの扱い

PostgreSQLの公式DockerイメージDockerfileを見てみます。
下記の2行に/var/lib/postgresql/dataの記述を見つけました。(ディレクトリの生成も含めれば3行)
登場するDockerのENVVOLUMEの命令は、この親投稿では触れなかったものなので、調べてみます。

postgres/Dockerfile-debian.template#L181
ENV PGDATA /var/lib/postgresql/data

#ENV | Dockerfile リファレンス | Docker ドキュメント

環境変数 <key><value> という値を設定します。

つまり環境変数PGDATA/var/lib/postgresql/dataを設定しています。
PostgreSQLの公式リファレンスでは、pgsqlというデフォルトのディレクトリ名が、Dockerの公式イメージでは postgresqlとなっています。

postgres/Dockerfile-debian.template#L184
VOLUME /var/lib/postgresql/data

#VOLUME | Dockerfile リファレンス | Docker ドキュメント

VOLUME 命令は指定された名前を使ってマウントポイントを生成します。 そして自ホストまたは他のコンテナーからマウントされたボリュームとして、そのマウントポイントを扱います。

荒い解釈ではありますが、/var/lib/postgresql/dataをめぐる流れとしては、下記のように整理できると思いました。
 1. ホストOSのローカルに/var/lib/postgresql/dataを生成
  (postgres/Dockerfile-debian.template#L21)
 2. PostgreSQLがサービスのデータを参照するための環境変数PGDATA/var/lib/postgresql/dataを設定
  (postgres/Dockerfile-debian.template#L181)
 3. Composeの起動時にPostgreSQLのサービスが/var/lib/postgresql/dataをマウントできるようにマウントポイントを生成
  (postgres/Dockerfile-debian.template#L184)
 4. $ docker compose run ~でコンテナを起動したらマウントポイントの/var/lib/postgresql/dataをマウントしてサービス側から使用できるようにする
  (チュートリアルのdocker-compose.ymlのdb: volume:設定行)

environment:
environment:
  POSTGRES_PASSWORD: password

#environment | Compose ファイル バージョン 3 リファレンス | Docker ドキュメント
環境変数を追加します。

web:

任意のサービスの名称として"db"が付けられています。
公式のサンプルでは、下位にbuild, command, volumes, ports, depends_onの設定項目が続きます。

    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
build:
build: .

#build | Compose ファイル バージョン 3 リファレンス | Docker ドキュメント

build の指定方法の 1 つは、ビルドコンテキストへのパスを表わす文字列を指定します

ビルドコンテキスト?
Docker Tips: All About the Build Context - Better Programming - Medium

The build context is the set of files located at the specified PATH or URL. Those files are sent to the Docker daemon during the build so it can use them in the filesystem of the image.

指定されたURLやPATHにあるファイル一式。これらのファイルはDockerのデーモンに送られビルド中にイメージのファイルシステムで使用できるようになる。
今回では、webサービスのイメージでbuildのPATHに.を指定しているので、 /var, /myappなどの全ての階層とファイルがwebサービスイメージのファイルシステムで使用できるようになっています。

command:
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"

#command | Compose ファイル バージョン 3 リファレンス | Docker ドキュメント
コンテナ起動時にデフォルトで実行されるコマンド。

bash -c

bash(1): GNU Bourne-Again SHell - Linux man page
-cは後に続く文字列をコマンドとして実行するので、bash -c "<command>"はBashシェルでを実行する意味になります。

volumes:
volumes:
  - .:/myapp

再掲:#volumes | Compose ファイル バージョン 3 リファレンス | Docker ドキュメント
ホストOS上のパスである.を、コンテナ上の/myappへ専用のボリュームとしてマウントします。

ports:
ports:
  - "3000:3000"

#ports | Compose ファイル バージョン 3 リファレンス | Docker ドキュメント
公開するポートをHOST:CONTAINERで指定します。

depends_on:
depends_on:
  - db

#depends_on | Compose ファイル バージョン 3 リファレンス | Docker ドキュメント
サービスの依存関係を指定します。複数ある場合は順番に起動。
ただ、依存サービスの「準備」状態を待たずに当サービスの起動を実行するため、ちゃんと依存関係にあるサービスの「準備」を待ちたいなら、別途コマンドにより待機させる工夫が必要です。


後書き

Docker + Raislの公式チュートリアルについては今回で一旦終了です。
DeepL頼みなことが多いですが、海外の記事やリファレンスを抵抗なく触れられるようになったことは、自身として少しは進歩しているのかなと感じます。

理解が荒い部分も多いので、このような調査とアウトプットを継続して、正しい理解に近づくように取り組んでいきます。

また、英語だと教育資料や初心者向けの教材なども簡単にヒットするので、様々な情報源から学びを得られるように独力で英文を読む能力も鍛えていきたいと思いました。

次は、CircleCIの設定ファイルについて学習します。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2