LoginSignup
101
86
お題は不問!Qiita Engineer Festa 2023で記事投稿!

Docker Composeについてざっくり理解する【概要 / ymlファイル書き方 / コマンド操作】

Last updated at Posted at 2023-06-18

はじめに

最近、山浦清透さんが運営されているプログラミング学習サービス「独学エンジニア」にてDockerについて学び始め、最後のセクションであるDocker Composeについて学び終わりましたので、備忘録も兼ねて自分なりにまとめていきたいと思います:muscle:
今回の内容はDockerの基本操作を理解した上での記事となりますので、「Docker使えたら便利らしいけど、よく分からん!」って方は以前投稿した記事、「Docker基本操作Part1」「Docker基本操作Part2」「Dockerfileの書き方」を軽くご一読ください:bow_tone2:

docker-compose-tako.png

(タコが複数のコンテナを持って考えてる・・・・・・:eyes:
(まさかお前、、、複数のコンテナをまとめて操作できるっていうのか!?:neutral_face:

タコ:rage:「そのとおーり」

(なんか喋った笑)

1. Docker Composeとは

  • 複数のコンテナを定義し実行する Docker アプリケーションのためのツール
  • YAMLファイルを使い、アプリケーションのサービスを設定し、コマンドを1つ実行するだけで、設定内容に基づいた全てのサービスを生成・起動

「Docker公式ドキュメント」より

つまり要約すると、これまでコンテナ一つごとにコマンドを打って操作していたものを、Docker Composeを用いることにより、複数のコンテナで構成されるアプリケーションについて、Dockerイメージのビルドや各コンテナの起動・停止などをより簡単に行えるようにするツールと言えます。

おそらく実際の開発現場では、コンテナ1つだけで開発するというのはほとんどなく、複数のコンテナを用いて開発するでしょうから、Docker Composeは必須といえるでしょうね。

2. DockerとDocker Composeの違い

Docker(Docker Engine) Docker Compose
役割 Dockerコンテナを運用するためのプラットフォーム 複数のDockerコンテナを一度にできるツール
コンテナ操作 1度に1つずつしかDockerコンテナを操作できない 1度に複数のDockerコンテナを操作可能

3. コンテナを起動するまでの流れ

  1. DockerFileの作成
    docker-compose.ymlファイルで直接イメージを指定すれば、Docker Composeでコンテナを起動するためのDockerfileは必要ないですが、
    既存のイメージに対して追加の設定やカスタマイズを行いたい場合は、Dockerfileを作成し、それをdocker-compose.ymlから参照します。

  2. docker-compose.ymlの作成
    docker-compose.ymlとはDocker Composeの設定ファイルであり、これから作成するコンテナの初期状態を「ports:」「volumes:」などYAML形式を用いて定義されています。
    また、このファイルは通常、プロジェクトのルートディレクトリに配置されるのが一般的です。

    ここで初登場したdocker-compose.yml君を使用することで、複数のコンテで構成されるアプリケーションの全体像を一目で把握でき、さらに一つのコマンドで全てのコンテナを起動したり、停止したりすることができちゃいます。

  3. docker-composeコマンドでコンテナ起動
    docker-compose.ymlファイルが存在するディレクトリでdocker compose upコマンドを実行すると、docker-compose.ymlファイルに記述された全てのサービス(コンテナ)をビルドし、起動することができます。

image.png
参考:「【初心者向け・図解】Docker Composeとは?Dockerとの違いを現役エンジニアがわかりやすく解説」より

4. docker-compose.ymlファイルの書き方

まずはdocker-compose.ymlファイルのサンプル(Railsの環境構築)を見て、よく使うものをピックアップしてそれぞれ理解していきましょう!

Sample
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
services: 
  db: #サービス名
    
  web: #サービス名

「web」や「db」以外の名前を付けるのはあり?
サービス名は任意のものなので、違う名前を付けるのもありです。
しかし、以下2点には気をつけましょう。

  • そのサービスが何を示しているか理解しやすい名前を付けること
  • サービス名を他のサービスから参照している場合があるので、変更する場合は参照されているサービス名も変更すること

※環境構築の際にチームメンバーへ共有したりすることを考えると、基本的には「web」や「db」など一般的に使われているサービス名にするのが無難でしょう。

(2)image

既存のイメージに対して追加の設定やカスタマイズを行う必要がない場合、image:に続いてDockerイメージを指定することで、そのイメージよりビルドします。

image
  image: mysql:5.7 # イメージ名:タグ

(3)build

image:よりビルドするのではなく、用意したDockerfileよりビルドする場合、build:へymlファイルが置いてあるディレクトリ(カレントディレクトリ)からDockerfileが置いてあるディレクトリへの相対パスを記述します。

build
  build: ./rails_project # Dockerfileがあるディレクトリへの相対パス

(4)volumes【サービス内にある方】

volumesはデータをコンテナの外に保存するための設定項目であり、ホストマシンにもデータを共有することでデータの永続性を可能にしています。これがないと、コンテナが削除されたときにそのコンテナ内にあった全てのデータが消えてしまい大変です:scream:

volumes
  # (dbコンテナ)
  volumes:
      - db_data:/var/lib/mysql  # ホストディレクトリ : コンテナ内ディレクトリ
  # (webコンテナ)
  volumes: 
      - .:/myapp  # ホストディレクトリ : コンテナ内ディレクトリ  

volumesはホスト側のディレクトリとコンテナ内のディレクトリをマウント、要は結びつけをするために使われ、ホスト上でコードを変更を行うと、その変更がリアルタイムでコンテナ内に反映されます:ok_hand:

(5)volumes【トップレベルで指定されている方】

ここでのvolumesはDocker Composeにボリュームを作成するように指示します。
そしてここで定義されたボリュームはサービス内のvolumesで使用することができ、サンプルにおいてもdbコンテナにおいて使用されています。

volumes
   volumes: 
      db_data:

ボリュームを使うとデータはDockerコンテナの起動・停止のサイクルから独立して保存・管理できるため、コンテナが削除されてもボリュームに保存されたデータは保持されているので消したくないデータ等はボリュームに入れておくと、安心ですね:blush:

なぜdbコンテナ内でマウント先をホストマシンではなく、Dockerボリュームにしているの?

dbサービスでは、MySQLのデータが保存される/var/lib/mysqlディレクトリをDockerボリュームにマウントしています。これには主に以下の理由があります。

  • データの永続化
    上記で述べている通り、コンテナの処理サイクルに関わらずデータを永続化することができます。

  • パフォーマンス面
    Dockerボリュームはパフォーマンスが最適化されており、特にデータベースのようなI/O(インプットとアウトプットの繰り返し)が頻繁に発生するアプリケーションにとっては重要なってきます。

  • データの独立性
    データベースのデータはアプリケーションコードとは異なり、開発者が直接操作するものではありません。
    そのため、それらをホストマシンの特定のディレクトリにマウントする必要性は低く、またホスト側にマウントするとホストマシンのディレクトリ構造を複雑にする可能性があります。

  • バックアップ及び復元
    Dockerボリュームはバックアップと復元が容易で、重要なデータベースデータの管理に適しています。

以上のような理由から、データベースデータの永続化にはDockerボリュームが一般的に推奨されます。
しかし、特定のケースや要件によってはホストのディレクトリを使用することもあります。

ボリュームについて「ん〜、よく分からん!」って方は以下の記事が参考になったので貼っておきますね

(6)environment

environmentは、Dockerのコンテナ内で使用される環境変数を設定するために使用します。
Dockerコンテナはホストマシンの環境と完全に分離されて動作するため、コンテナ内部で環境変数を設定する必要があります。

environment
  environment: 
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_DATABASE: your_database
      MYSQL_USER: user_name
      MYSQL_PASSWORD: user_password

(7)ports

portsの設定では、ホストマシンとDockerコンテナ間でのネットワークポートのマッピングを指定します。
指定する形式はホストマシンのポート番号:コンテナのポート番号となるので逆にならないように注意しましょう:ok_hand:

ports
    ports: 
      - "3000:3000" # ホストマシンのポート番号:コンテナのポート番号

portsの設定はDockerコンテナのアプリケーションがネットワークを通じて外部と通信するために必要な設定ですので、ネットワークを通じた外部とのやり取りがある場合は忘れずに設定しておきましょう:wink:

(8)depends_on

depends_onはサービス間の依存関係を定義するために使用し、Docker Composeに指定したサービスが他の1つ以上のサービスに依存していることを伝えることができます。
その結果、Docker Composeは、そのサービスを開始する前に依存している全てのサービスが先に開始されていることを確認してくれます。

depends_on
   # (webコンテナ)
   depends_on: 
     - db

上記の内容では、webコンテナがdbコンテナに依存しているので、dbコンテナが先に開始されることをDocker Composeは確認します。

(9)command

commandはサービスコンテナが起動したときに実行するコマンドを指定します。

command
    command: bundle exec rails s -p 3000 -b '0.0.0.0' 

設定項目はこの他にも多数ありますが、よく使うものはこの辺りで抑えられていると思いますので、知らない項目が出てきたらその都度調べるスタイルでもいいんじゃないかなと思います:point_up:

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コマンドを用いて操作していきましょう:raised_hands:

(1)up 【コンテナ作成・起動】

$ docker compose up  # イメージが存在しないときはビルドする

オプションでは以下の2つがよく使われます。

  • --build イメージをビルドした上でコンテナを作成・起動する
  • -d コンテナをバッググラウンドで起動させる(detach)
$ docker compose up --build 
$ docker compose up -d

Dockerfileやdocker-compose.ymlファイルを修正し、改めてコンテナを立ち上げたい場合はイメージのビルドからしたいので--buildオプションが使われます:point_up_tone2:

(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についてはある程度抑えられたのではないかなと思います:writing_hand:
あとは実践あるのみですね:basketball_player_tone1:
私はこれまでに学んだ知識を活かして、RailsをDocker上で環境構築できるように頑張っていきたいと思います:laughing:

間違っている点などございましたら、遠慮なくご指摘いただければと思います:bow_tone2:

参考文献

101
86
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
101
86