Docker / Docker Compose を使って開発環境を用意するときの Tips

この記事は「ウィルゲート Advent Calendar 2023」の 1 日目の記事です。

adventar.org

こんにちは、ウィルゲート開発室の岡田/おかしょい(@okashoi)です。

ウィルゲートでは開発環境の構築に Docker と Docker Compose を使っています。 ホストマシンの影響を(あまり)受けることなく共通の開発環境を提供することができるのが便利ですね。

www.docker.com

本記事では、そんな Docker と Docker Compose を使った開発環境を構築してチームに提供する際に気をつけているちょっとしたポイントを挙げていきます。

docker-compose.yaml ではなく compose.yaml

少し前までは設定ファイル名のデフォルトは docker-compose.yaml でしたが、2023 年 12 月現在では compose.yaml を使うことが「好ましい(preferred)」とされています。

後方互換を保つために docker-compose.yaml でもまだ動きますが、見かけたら compose.yaml にリネームしてあげるとよいでしょう。

The default path for a Compose file is compose.yaml (preferred) or compose.yml that is placed in the working directory.

docs.docker.com

.env を使って公開ポート番号等をカスタマイズできるようにする

例えば compose.yamlports 要素によって公開ポートを指定できますが、これをハードコーディングしてしまうと人(環境)によってはポート番号が衝突してしまう可能性があります。

compose.yaml では変数を展開することができ、同階層に .env ファイルを設置することで変数の値を指定できます。 この仕組みを使えば、Git 管理された同一の compose.yaml ファイルを使いつつ、起動する人自身の手によって環境をカスタマイズできます。

.env

HTTP_PORT=8080

compose.yaml

services:
  web-server:
    image: nginx:1.25.3
    ports:
      - 127.0.0.1:${HTTP_PORT}:80

docs.docker.com

このあたりは The Twelve-Factor App の「設定を環境変数に格納する」の考え方にも通じますね。

12factor.net

プロジェクト名を指定する

1 つの compose.yaml ファイルは「プロジェクト」という概念に結びつきます。

docs.docker.com

プロジェクト名は Docker コンテナ、Docker イメージ等のデフォルト名の一部に付けられます(コンテナ名なら<プロジェクト名>_<サービス名>_<連番>)。 そして、デフォルトでは compose.yaml ファイルが置かれているディレクトリ名が設定されます。

その結果、ディレクトリ構成によっては docker とか develop みたいな情報の少ない名前になってしまうなんてケースが発生しかねません。

プロジェクト名は compose.yaml 内の name 要素や COMPOSE_PROJECT_NAME 変数によって指定できるので、プロダクト名などのわかりやすい名前をつけてあげましょう。

docs.docker.com

depends_on, healthcheck を使ってサービスの起動タイミングを制御する

「Web アプリケーションのコンテナを起動する前に、データベースのコンテナが起動している」のように、コンテナの起動順を指定したケースもあるでしょう。

depends_on 要素を指定すると「そのサービス(ここではコンテナ、と読み替えて OK)より先に depends_on に指定したサービスを立ち上げる」という形で起動順序(依存関係)を定義できます。

services:
  webapp:
    image: php:8.2.12-apache
    depends_on:
      - database

  database:
    image: mysql/mysql-server:8.2.0

ただし、単にサービス名を指定しただけでは「コンテナが起動しているか」しか見られていないため、「目的のサービスが利用可能な状態か」までは判断してくれません。

それを解決するには healthcheck 要素の指定と、depends_oncondition 指定を組み合わせて使います。

services:
  webapp:
    image: php:8.2.12-apache
    depends_on:
      database:
        condition: service_healthy
  database:
    image: mysql/mysql-server:8.2.0
    healthcheck:
      test: mysqladmin ping -h 127.0.0.1 -u${MYSQL_USER} -p${MYSQL_PASSWORD}
      interval: 1s
      timeout: 4s
      retries: 20
      start_period: 10s

docs.docker.com

目的に応じて設定ファイルを分割する

先述のとおりデフォルトでは設定ファイルとして compose.yaml を読み取りますが、-f オプションを指定してファイル名を明示できます。 複数指定もできます。

docker compose -f <設定ファイル名1> -f <設定ファイル名2> ...

「開発用の環境」「自動テストの実行環境」といったように目的ごとに環境の設定や、必要なサービスが異なることもあるでしょう。

そんなときには「compose-common.yaml に共通の設定を書き、開発環境用の設定を compose-dev.yaml に、テスト用実行の設定を compose-test.yaml に書きわける」というように運用できます。

docs.docker.com

.dockerignore を指定して余計なファイルを Docker イメージに含めない

Docker イメージビルドの際、DockerfileCOPY 命令によってホストマシン上のファイルを Docker イメージに含めることがあります。

この際 .dockerignore というファイルによって、イメージビルドに「含めない」ファイルやディレクトリを指定できます。 ファイル形式はおなじみ .gitignore と同じです。

例えば node_modules のような依存パッケージが格納されるディレクトリについて、「ホストマシン上のものを渡すのではなく、イメージビルドの過程でインストールさせる」といったことを実現できます。

docs.docker.com

おわりに

いずれも細かい部分ではありますが、知っていると開発環境をちょっと便利にできる Tips をご紹介しました。

設定内容やオプションはまだまだたくさんあるので、改めて公式ドキュメントを眺めてみるのもいいかもしれませんね!

docs.docker.com

そして「ウィルゲート Advent Calendar 2023」、明日は佐々木さんによる「PHP Generatorを活用してメモリを節約しよう」です。 お楽しみに!