うさぎ好きエンジニアの備忘録

うさぎたちに日々癒されているエンジニアが業務で直面したもの & 個人的な学習メモを残していきます。

docker-compose.ymlを書けるようになる

Docker Composeが便利だったので適当に備忘録。

Docker Composeでは「docker-compose.yml」という定義ファイルに、システム内で稼働する複数のサーバ群の構成をまとめて定義する。 この定義ファイルはYAML形式で記述する。

定義ファイル内では、

  • services
  • networks
  • volumes

の3つを定義する。

また、定義ファイルはバージョンによって記述できる項目が異なる。 なお、今回は「3.3」をベースに使っていく。

Compose定義ファイル

以下の例では「webserver」と「redis」という2つのサービスを作成している。

# バージョンを指定
version: "3.3"

# サービスを定義
services:
  webserver:
    image: ubuntu
    ports:
      - 80:80
    networks:
      - webnet
  redis:
    image: redis
    network:
      - webnet

# ネットワーク定義
networks:
  webnet:

# データボリューム定義
volumes:
  data-volume:

イメージの指定

コンテナのもとになるベースイメージを指定するときは「image」を使う。 「image」にはイメージの名前もしくはイメージIDのいずれかを指定する。 上記の例だと、webserverという名前のイメージのベースにubuntuを指定している。なお、イメージのタグ指定も可能。

イメージのビルド

イメージの構成をDockerfileに記述し、それを自動でビルドしてベースイメージに指定することもできる。 この場合は「build」を使う。実際にdocker-compose.ymlを記述する際は以下のように書く。

services:
  webserver:
    build: .

このように記述すると、docker-compose.ymlのあるディレクトリをカレントディレクトリしたときのDockerfileの場所を指定することができる。 また、任意のDockerfileを指定するときは「dockerfile」を指定する。

services:
  webserver:
    # Dockerfileの置いてあるディレクトリや、GitリポジトリのURLを「context」で指定
    context: /dockerfiles
    # ビルドするDockerfileの名前を「dockerfile」で指定
    dockerfile: dockerfile-sample

また、Dockerイメージをビルドする際の引数を「args」として指定することが可能。

services:
  webserver:
    build:
      args:
        user: ponteru

コンテナ内で実行するコマンドの指定

コンテナ内で実行するコマンドは「command」で指定する。 もしベースイメージにおいて「command」が指定されている場合は、その内容を上書きしてしまうので注意。

command: /bin/bash

また「entrypoint」を上書きすることも可能。

entrypoint:
  - php
  - -d
  - memory_limit=1

コンテナ間の連携

別のコンテナと連携したい場合は「links」を利用する。 「logserver」という名前のコンテナとリンクさせたい時は以下のように記述する。

links:
  - logserver
  - logserver:logger01

また、コンテナメイトは別にエイリアス名を付けたい場合には「サービス名:エイリアス名」を設定する。 例えば以下のようなdocker-compose.ymlがあった場合、「webserver」コンテナか らdb:27017 または database:27017 を使用して「db」コンテナにアクセスすることができる。

db:
  image: mongo
  ports:
    - "27017:27017"
webserver:
  build: .
  command: bundle exec rails s -p 3000 -b '0.0.0.0'
  ports:
    - "3000:3000"
  links:
    - db
    - db:database

コンテナ間の通信

コンテナが公開するポートは「ports」で指定する。 指定する方法としては、 * 「ホストマシンのポート番号:コンテナのポート番号」を指定する * コンテナのポート番号のみを指定する の2通りがある。「コンテナのポート番号のみを指定」した場合、ホストマシンのポートはランダムな値が設定される。

ports:
  # 記述する際は必ずダブルクォートで囲み、文字列として定義すること。
  - "3000"
  - "8000:8000"
  - "127.0.0.1:8080:8080"

また、ホストマシンへはポートを公開せず、リンク機能により連携するコンテナ間でのみポートを公開する場合は「expose」を使用する。

expose:
  - "3000"
  - "8080"

サービスの依存関係の定義

複数のサービスの依存関係を定義する時は「depends_on」を指定する。 例えば、「webserver」コンテナを開始する前に「db」コンテナと「redis」コンテナを開始したい時は以下のように定義する。

services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

ここで注意しなければならないのが、depends_onは「コンテナの開始の順序を制御するだけであり、コンテナ上のアプリケーションが利用可能になるまで待つという制御を行うわけではない」ということ。 つまり接続したいデータベースが準備できていないのに、先にアプリケーションが立ち上がるという問題も可能性としてはあり得る。

コンテナの環境変数の指定

コンテナ内の環境変数を指定する時は「environment」を指定する。

# 配列形式での記述
environment:
  - HOGE=fuga
  - FOO=bar

# ハッシュ形式での記述
environment:
  HOGE: fuga
  FOO: bar

また、設定したい環境変数が多い場合などは別ファイルに環境変数を定義し、それを読み込むことも可能。 この際は「env_file」を指定する。

$ cat envfile
HOGE=fuga
FOO=bar
env_file: envfile

なお、env_fileは複数読み込むことも可能。この際は配列形式で読み込む。

env_file:
  - ./envfile1     # 相対パスでの指定が可能
  - /tmp/envfile2  # 絶対パスでも指定も可能

コンテナの情報設定

Docker Composeで生成されるコンテナに名前をつける時は「container_name」を指定する。 例えば「webserver」という名前で定義したコンテナに「web-container」という名前を付けたい時は、以下のように記述する。

container_name: web-container

また、コンテナにラベルをつける時は「labels」を指定する。

# 配列形式での記述
labels:
  - "jp.co.ponteru.sample.description=Sample Application"
  - "jp.co.ponteru.sample.department=Platform"
# ハッシュ形式での記述
labels:
  jp.co.ponteru.sample.description: Sample Application
  jp.co.ponteru.sample.department: Platform

ちなみに設定したラベルを確認する時は、docker-compose config を実行する。

コンテナにボリュームをマウントする

コンテナにボリュームをマウントするときは「volume」を指定する。 以下の例では /var/lib/mysql をマウントしている。 また、ホスト側でまうとするパスを指定する場合は「ホストのディレクトリ:コンテナのディレクトリ」を指定する。

volumes:
  - /var/lib/mysql
  - cache/:/tmp/cache

ちなみに、以下のように :ro を末尾に追記することでボリュームをread-onlyにすることができる。

volumes:
  - /var/lib/mysql:ro

別のコンテナから、あるコンテナにマウントされているボリュームをマウントする場合には「volumes_from」を指定する。

volumes_from:
  - target

上記の例だと「target」コンテナにマウントされているボリュームをマウントする。