はじめに
最近、山浦清透さんが運営されているプログラミング学習サービス「独学エンジニア」にてDockerについて学び始め、最後のセクションであるDocker Compose
について学び終わりましたので、備忘録も兼ねて自分なりにまとめていきたいと思います
今回の内容はDockerの基本操作を理解した上での記事となりますので、「Docker使えたら便利らしいけど、よく分からん!」って方は以前投稿した記事、「Docker基本操作Part1」「Docker基本操作Part2」「Dockerfileの書き方」を軽くご一読ください
(タコが複数のコンテナを持って考えてる・・・・・・)
(まさかお前、、、複数のコンテナをまとめて操作できるっていうのか!?)
タコ「そのとおーり」
(なんか喋った笑)
1. Docker Composeとは
- 複数のコンテナを定義し実行する Docker アプリケーションのためのツール
- YAMLファイルを使い、アプリケーションのサービスを設定し、コマンドを1つ実行するだけで、設定内容に基づいた全てのサービスを生成・起動
つまり要約すると、これまでコンテナ一つごとにコマンドを打って操作していたものを、Docker Compose
を用いることにより、複数のコンテナで構成されるアプリケーションについて、Dockerイメージのビルドや各コンテナの起動・停止などをより簡単に行えるようにするツールと言えます。
おそらく実際の開発現場では、コンテナ1つだけで開発するというのはほとんどなく、複数のコンテナを用いて開発するでしょうから、Docker Composeは必須といえるでしょうね。
2. DockerとDocker Composeの違い
Docker(Docker Engine) | Docker Compose | |
---|---|---|
役割 | Dockerコンテナを運用するためのプラットフォーム | 複数のDockerコンテナを一度にできるツール |
コンテナ操作 | 1度に1つずつしかDockerコンテナを操作できない | 1度に複数のDockerコンテナを操作可能 |
3. コンテナを起動するまでの流れ
-
DockerFileの作成
docker-compose.ymlファイルで直接イメージを指定すれば、Docker Composeでコンテナを起動するためのDockerfile
は必要ないですが、
既存のイメージに対して追加の設定やカスタマイズを行いたい場合は、Dockerfile
を作成し、それをdocker-compose.ymlから参照します。 -
docker-compose.ymlの作成
docker-compose.yml
とはDocker Composeの設定ファイルであり、これから作成するコンテナの初期状態を「ports:」「volumes:」などYAML形式を用いて定義されています。
また、このファイルは通常、プロジェクトのルートディレクトリに配置されるのが一般的です。ここで初登場した
docker-compose.yml
君を使用することで、複数のコンテで構成されるアプリケーションの全体像を一目で把握でき、さらに一つのコマンドで全てのコンテナを起動したり、停止したりすることができちゃいます。 -
docker-composeコマンドでコンテナ起動
docker-compose.ymlファイルが存在するディレクトリでdocker compose up
コマンドを実行すると、docker-compose.ymlファイルに記述された全てのサービス(コンテナ)をビルドし、起動することができます。
参考:「【初心者向け・図解】Docker Composeとは?Dockerとの違いを現役エンジニアがわかりやすく解説」より
4. docker-compose.ymlファイルの書き方
まずはdocker-compose.ymlファイルのサンプル(Railsの環境構築)を見て、よく使うものをピックアップしてそれぞれ理解していきましょう!
services: # (1)
db:
image: mysql:5.7 # (2)
volumes: # (4)
- db_data:/var/lib/mysql
restart: always
environment: # (6)
MYSQL_ROOT_PASSWORD: root_password
MYSQL_DATABASE: your_database
MYSQL_USER: user_name
MYSQL_PASSWORD: user_password
web:
build: ./rails_project # (3)
command: bundle exec rails s -p 3000 -b '0.0.0.0' # (9)
volumes: # (4)
- .:/myapp
ports: # (7)
- "3000:3000"
depends_on: # (8)
- db
volumes: # (5)
db_data:
(1)services
ここでは、作成したいサービス(コンテナ)を列挙します。
サンプルでは「web」と「db」という名前で2つのコンテナについて、それぞれ設定が記述されています。
services:
db: #サービス名
web: #サービス名
「web」や「db」以外の名前を付けるのはあり?
サービス名は任意のものなので、違う名前を付けるのもありです。
しかし、以下2点には気をつけましょう。
- そのサービスが何を示しているか理解しやすい名前を付けること
- サービス名を他のサービスから参照している場合があるので、変更する場合は参照されているサービス名も変更すること
※環境構築の際にチームメンバーへ共有したりすることを考えると、基本的には「web」や「db」など一般的に使われているサービス名にするのが無難でしょう。
(2)image
既存のイメージに対して追加の設定やカスタマイズを行う必要がない場合、image:
に続いてDockerイメージを指定することで、そのイメージよりビルドします。
image: mysql:5.7 # イメージ名:タグ
(3)build
image:
よりビルドするのではなく、用意したDockerfileよりビルドする場合、build:
へymlファイルが置いてあるディレクトリ(カレントディレクトリ)からDockerfileが置いてあるディレクトリへの相対パスを記述します。
build: ./rails_project # Dockerfileがあるディレクトリへの相対パス
(4)volumes【サービス内にある方】
volumes
はデータをコンテナの外に保存するための設定項目であり、ホストマシンにもデータを共有することでデータの永続性を可能にしています。これがないと、コンテナが削除されたときにそのコンテナ内にあった全てのデータが消えてしまい大変です
# (dbコンテナ)
volumes:
- db_data:/var/lib/mysql # ホストディレクトリ : コンテナ内ディレクトリ
# (webコンテナ)
volumes:
- .:/myapp # ホストディレクトリ : コンテナ内ディレクトリ
volumes
はホスト側のディレクトリとコンテナ内のディレクトリをマウント、要は結びつけをするために使われ、ホスト上でコードを変更を行うと、その変更がリアルタイムでコンテナ内に反映されます
(5)volumes【トップレベルで指定されている方】
ここでのvolumes
はDocker Composeにボリュームを作成するように指示します。
そしてここで定義されたボリュームはサービス内のvolumes
で使用することができ、サンプルにおいてもdbコンテナにおいて使用されています。
volumes:
db_data:
ボリュームを使うとデータはDockerコンテナの起動・停止のサイクルから独立して保存・管理できるため、コンテナが削除されてもボリュームに保存されたデータは保持されているので消したくないデータ等はボリュームに入れておくと、安心ですね
なぜdbコンテナ内でマウント先をホストマシンではなく、Dockerボリュームにしているの?
dbサービスでは、MySQLのデータが保存される/var/lib/mysqlディレクトリをDockerボリュームにマウントしています。これには主に以下の理由があります。
-
データの永続化
上記で述べている通り、コンテナの処理サイクルに関わらずデータを永続化することができます。 -
パフォーマンス面
Dockerボリュームはパフォーマンスが最適化されており、特にデータベースのようなI/O(インプットとアウトプットの繰り返し)が頻繁に発生するアプリケーションにとっては重要なってきます。 -
データの独立性
データベースのデータはアプリケーションコードとは異なり、開発者が直接操作するものではありません。
そのため、それらをホストマシンの特定のディレクトリにマウントする必要性は低く、またホスト側にマウントするとホストマシンのディレクトリ構造を複雑にする可能性があります。 -
バックアップ及び復元
Dockerボリュームはバックアップと復元が容易で、重要なデータベースデータの管理に適しています。
以上のような理由から、データベースデータの永続化にはDockerボリュームが一般的に推奨されます。
しかし、特定のケースや要件によってはホストのディレクトリを使用することもあります。
ボリュームについて「ん〜、よく分からん!」って方は以下の記事が参考になったので貼っておきますね
(6)environment
environment
は、Dockerのコンテナ内で使用される環境変数を設定するために使用します。
Dockerコンテナはホストマシンの環境と完全に分離されて動作するため、コンテナ内部で環境変数を設定する必要があります。
environment:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_DATABASE: your_database
MYSQL_USER: user_name
MYSQL_PASSWORD: user_password
(7)ports
ports
の設定では、ホストマシンとDockerコンテナ間でのネットワークポートのマッピングを指定します。
指定する形式はホストマシンのポート番号:コンテナのポート番号
となるので逆にならないように注意しましょう
ports:
- "3000:3000" # ホストマシンのポート番号:コンテナのポート番号
ports
の設定はDockerコンテナのアプリケーションがネットワークを通じて外部と通信するために必要な設定ですので、ネットワークを通じた外部とのやり取りがある場合は忘れずに設定しておきましょう
(8)depends_on
depends_on
はサービス間の依存関係を定義するために使用し、Docker Composeに指定したサービスが他の1つ以上のサービスに依存していることを伝えることができます。
その結果、Docker Composeは、そのサービスを開始する前に依存している全てのサービスが先に開始されていることを確認してくれます。
# (webコンテナ)
depends_on:
- db
上記の内容では、webコンテナがdbコンテナに依存しているので、dbコンテナが先に開始されることをDocker Composeは確認します。
(9)command
command
はサービスコンテナが起動したときに実行するコマンドを指定します。
command: bundle exec rails s -p 3000 -b '0.0.0.0'
設定項目はこの他にも多数ありますが、よく使うものはこの辺りで抑えられていると思いますので、知らない項目が出てきたらその都度調べるスタイルでもいいんじゃないかなと思います
ymlファイルに「version」が書かれているのよく見るけど、あれって書かなあかん?
結論、書かなくて大丈夫です。
Docker Composeの使用を定めている「compose-spec」より
The Compose file is a YAML file defining version (DEPRECATED), services (REQUIRED), networks, volumes, configs and secrets.
【日本語訳】
Composeファイルは、バージョン(非推奨)、サービス(必須)、ネットワーク、ボリューム、設定、シークレットを定義するYAMLファイルです。
との記載があるためです!!
「version」がなくても問題なく動作しますので、安心してくださいね(^^)
5. Docker Composeコマンドで操作する
docker-compose.ymlファイルが作成できたら、Docker Composeコマンドを用いて操作していきましょう
(1)up 【コンテナ作成・起動】
$ docker compose up # イメージが存在しないときはビルドする
オプションでは以下の2つがよく使われます。
-
--build
イメージをビルドした上でコンテナを作成・起動する -
-d
コンテナをバッググラウンドで起動させる(detach)
$ docker compose up --build
$ docker compose up -d
Dockerfileやdocker-compose.ymlファイルを修正し、改めてコンテナを立ち上げたい場合はイメージのビルドからしたいので--build
オプションが使われます
(2)ps 【コンテナ一覧表示】
停止中を含めたコンテナの一覧を表示させたい場合は、-a
オプションを付けます。
$ docker compose ps # コンテナの一覧を表示
$ docker compose ps -a #停止中を含めたコンテナの一覧を表示
(3)logs 【ログを表示】
logs
コマンドの後に、サービス名を指定することでログを表示させます。
$ docker compose logs web # サービス名を指定
(4)run 【コンテナ作成後、コマンド実行】
run
コマンドの後に、サービス名とコマンドを指定することで、コンテナを作成して1度だけコマンドを実行します。
$ docker compose run web ruby app.rb # サービスとコマンドを指定
(5)exec 【コマンド実行】
起動中のコンテナでexec
コマンドの後に、サービス名とコマンドを指定することでコマンドを実行します。
$ docker compose exec web /bin/sh # サービスとコマンドを指定
(6)down 【コンテナを停止・削除】
down
コマンドを付けるだけでup
コマンドで作成されたコンテナを停止・削除します。
$ docker compose down
おわりに
最後まで見ていただき、ありがとうございました!
少し長くなりましたが、これでDocker Compose
についてはある程度抑えられたのではないかなと思います
あとは実践あるのみですね
私はこれまでに学んだ知識を活かして、RailsをDocker上で環境構築できるように頑張っていきたいと思います
間違っている点などございましたら、遠慮なくご指摘いただければと思います
参考文献