LoginSignup
9
5

docker composeを始めよう(メリットとよく使う設定)

Last updated at Posted at 2023-12-06

前回は「今日から始めるDocker入門(必要性を理解してから動かす)」ということで、docker composeを使わずにdockerを動かす方法、またその必要性について解説させていただきました
たくさんの方にいいねやストックいただけて大変嬉しいです、ありがとうございます!

今回は、より実践的な内容にしたく、docker composeについて色々解説していきたいと思います

docker composeとは

まずは公式の説明を引用します

Compose とは、複数のコンテナを定義し実行する Docker アプリケーションのためのツールです。Compose は YAML ファイルを使い、アプリケーションのサービスを設定します。コマンドを1つ実行するだけで、設定内容に基づいた全てのサービスを生成・起動します。Compose の機能一覧について学ぶには、 機能一覧 をご覧ください。

若干分かりずらいと思いますので、簡単に説明すると
「YAMLファイルに起動のための設定を記述することによって、複数のDockerコンテナをひとつのコマンドで立ち上げることができる」という感じです

なにが嬉しいのか

docker composeを理解するためにも、「docker composeを導入するとなにが嬉しいのか」を考えてみましょう

こちらのページにある公式サンプルを例に考えてみます(記事内でwebコンテナはnginxを利用する都合でコンテナポートを5000から80に変更しています)

まずはdocker composeでやると

webコンテナとredisコンテナを作成しようとしていて、webはredisに対してネットワーク上で接続している状態となります
また、webコンテナはlogvolume01という名前のボリュームを別にもっていますね

compose.yaml(webサービスには別途Dockerfileの用意が必要となりますね)

version: "3.9"  # v1.27.0 からはオプション
services:
  web:
    build: .
    ports:
      - "8000:80"
    volumes:
      - .:/code
      - logvolume01:/var/log
    links:
      - redis
  redis:
    image: redis
volumes:
  logvolume01: {}

起動するには

% docker compose build
% docker compose up

これだけでOK!

docker composeでやってくれることをdockerコマンドだけでやろうとした場合

起動するには

まず、webイメージをビルドする

% docker build -t qiita-docker-compose-nginx -f Dockerfile ./
// docker build -t qiita-docker-compose-nginx ./ と一緒

ネットワーク作る

% docker network create -d bridge qiita-docker-compose-network

次にボリューム作る

% docker volume create logvolume01

redisコンテナ立ち上げる

% docker run -dit --name qiita-docker-compose-redis --network qiita-docker-compose-network -d redis

webコンテナを立ち上げる

docker run -dit --name qiita-docker-compose-nginx -p 8000:80 -v logvolume01:/var/log --network qiita-docker-compose-network qiita-docker-compose-nginx

どう考えたって、引数いくつもあるコマンドを何個も順々に実行してくより、設定はファイル化してあってコマンド一発で実行できるほうがいいに決まってる

比べてみてどうでしょう?

READMEとかに、これらのdockerコマンドの記載があって、上から順にコマンドを実行していけばもちろんできますが、いちいち一個ずつコピペするのは面倒ですし、ひとつひとつが独立したコマンドのため、いつかどこかで整合性がとれなくなるタイミングがありそうな気がします

一方、docker composeを利用していれば、「そこにcompose.yamlがあるなら、そこでdocker compose upを実行すれば良い」ということになります
どこに手順あるかなーなんて悩む必要がないというわけです
さらに、docker composeという世間一般のルールの中で環境を運用できるので、困ったら世の中にドキュメントがたくさんあります

使い所は?

「開発者に展開するローカル開発環境として」という用途が主になるかと思います
共通の開発環境などとしてAWS EC2とかで利用することもできなくないですが、ネットワーク設定などはAWSの機能を利用して設定するべきだと思うし、1つのEC2の中に複数のサービスを立ち上げることは最近の動向を考えるとあまり得策だとは言えないのだと思います

もし使うとしたら多少の不完全さやリスクを承知してAWS運用費を抑えたいとかそういう要望がある場合かと思います
その場合はぜひこの辺の設定も確認してみましょう!

シンプル構成でdocker composeを作ってみよう

officialの内容で作ってみようをやってみるのはつまらないので、もう少し普段使いそうな内容に寄せてdocker composeを作って動かしてみましょう

今回題材に使用する資材はこちらにpushしておきました!

フォルダ構成考える

以下の構成でいこうと思います
app: アプリケーションのルートディレクトリを想定してます
docker: docker関連のファイルを集めた箇所とします

dockerフォルダ配下はそれぞれdocker composeに記載するサービス名に合わせてフォルダを切っていくのが良いのかなと思います
.envはdockerコンテナに渡す環境変数を定義します
Dockerファイルは、各コンテナのビルドスクリプトを記述したものとなり、イメージの元となります

.
├── .env
├── app
│   └── index.html
├── compose.yaml
└── docker
    ├── apache
    │   └── Dockerfile
    └── db
        └── my.cnf

docker composeファイルを用意する

docker composeはcompose.yamlファイルを用意して、build/up するのみなので、すごく簡単です
dompose.yamlの書き方については覚える必要がありますが、大体使うものは限られてくるので、ひとつずつ地道に学んでいきましょう

version: "3"
services:
  web:
    container_name: qiita-docker-compose-web
    build: 
      context: .
      dockerfile: ./docker/apache/Dockerfile
    ports:
      - "8000:80"
    volumes:
      - ./app:/usr/local/apache2/htdocs:delegated
    depends_on:
      db:
        condition: service_healthy
        restart: true
  db:
    container_name: qiita-docker-compose-db
    image: mysql:8.2
    command: --default-authentication-plugin=mysql_native_password
    env_file: .env
    volumes:
      - ./docker/db/my.cnf:/etc/mysql/conf.d/my.cnf
    healthcheck:
     test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$MYSQL_ROOT_PASSWORD"]
     timeout: 20s
     retries: 5

webサービス

container_name

コンテナ名は通常、「ルートディレクトリ名 + サービス名 + n(数字)」で命名され、今回のケースだと「qiita-docker-compose-web-1」として設定されます
ですが、こちらの設定を利用すると、別名をつけることができます

build

Dockerfileの場所などを指定できます

ports

ホスト側ポートと、コンテナ側のポートを接続する設定になります
apacheのデフォルトポート80番とホスト側ポート8000番を接続することによって、 localhost:8000 でアクセスできるようになります

volumes

ホストのディレクトリをコンテナのファイルシステムにマウントする設定です
これにより、ホストPC内にあるリソース(主に変更のかかるソースファイルなど)をコンテナ内に共有できます

depends_on

サービス間の依存関係を設定します
今回のケースだと、webサービスがdbサービスを依存先として指定している形となり、コンテナ間で接続も可能となります

dbサービス

container_name、volumesは説明を割愛します
リファレンスの詳細リンクも割愛しますので、こちらから検索してみてください

image

buildではDockerファイルを指定して、それによってできたイメージをコンテナとしてupしますが、こちらはイメージそのものを指定できます
docker hubにあるイメージなどが代表的です
今回ではmysqlの8.2タグをイメージとして指定してます

command

Dockerfile内のCMD命令を上書きできます

※ CMDはDockerfile内で1度しか利用できないというルールがあるため、「CMDが複数ある場合はどうなんだ」という疑問は的外れになります

env_file

「変数=値」形式で記述されたファイルを読み込み、コンテナ内の環境変数として設定します

healthcheck

起動するコンテナが現在正常かどうかをどう確認するかを指定します
今回なぜ指定しているかというと、webコンテナの起動はdbコンテナ内のmysql起動が完了したタイミングで立ち上げたいためです
depends_onの設定のみだとdbコンテナの起動までしか待ってもらえず、mysqlの起動完了を待てないという都合があります
それをhealthcheckとdepends_on.conditionを使って要件を実現しようというとこです

よくある質問

compose.yamlファイルを修正したら再度ビルドが必要?

不要です!
ただし、Dockerfileを修正した場合にはビルドが必要になります

docker compose up -dで立ち上げたコンテナ達はどのように停止するの?

そもそも「- d」オプションとは、バックグラウンドでコンテナを実行するオプションとなりますが、そうすると、「ctrl + C」でコンテナを停止るすことができなくなります

その場合は以下のコマンドでコマンドを停止しましょう

% docker compose stop

yamlのファイル名って結局なにが正しいの

今回の記事を書くにあたって私自身も知識をアップデートしたのですが、現状公式が推奨しているファイル名は「compose.yaml」みたいですね

以下も許されているみたいです

  • compose.yml
  • docker-compose.yaml(下位互換性のため
  • docker-compose.yml(下位互換性のため

そう言えば、コマンドもいつの間にか「docker-compose」から「docker compose」に変わりましたね
ハイフン繋ぎなくしたいのかな?

Tips

awesome-compose

docker composeは公式で以下のgithubリポジトリを提示しています
ここには、docker composeの活用例がたくさんあります
是非学習や、自身のプロジェクトに役立ててください!(私もまだちゃんと見れてないのでみてみよーっと)

フォルダ構成について

最近はこういう構成もよく目にします
appはバックエンドアプリケーション、フロントエンドアプリケーションなどの単位で括られることがほとんどだと思いますがそれぞれのフォルダにDockerfileが存在する構成はデプロイの単位を考えると合理的な気がしますね!
こうしておくといざappのみ切り出して別のプロジェクトに転用したいときも楽そうです

.
├── .env
├── app
│   └── Dockerfile
├── docker-compose.yml
└── local
    └── db
        └── my.cnf
9
5
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
9
5