Dockerfile、docker-compose.ymlについてまとめる

2024/01/22に公開

Dockerを学習していく中で、Dockerの中核となるDockerfileとdocker-compose.ymlについて学んだことをまとめておきます。
まずはこの2種のファイルの役割から説明していきたいと思います。

Dockerfileとは

Dockerfileとは、Dockerイメージを生成するためのテキストファイルです。
DockerはDockerfileを元にDockerイメージをビルドし、DockerイメージからDockerコンテナを生成します。
つまりは、Dockerコンテナの大元となるのがこのDockerfileになります。

docker-compose.ymlとは

docker-compose.ymlは、複数のDockerコンテナを束ねて一つのサービスとして利用するためのツールである「Docker Compose」の設定ファイルです。
docker-compose.ymlに複数のコンテナを設定することによって、まとめて起動や停止を行うことができます。
docker-compose.ymlには複数のDockerfileが所属しているみたいなイメージで良いでしょう。

次にこの2種のファイルの内部の記述について見ていきましょう。

Dockerfileの記述

Dockerfileにはいくつかの記述が存在しています。
基本的なものを紹介していきましょう。

  • FROM
    ベースとなるイメージを設定します。
    Dockerfileは基本的には元から存在するイメージをカスタマイズするために用いられるため、ここにベースとなるイメージを設定します。
    例えばruby:3.3.0と設定した場合、Ruby3.3.0がプリインストールされた環境を元にカスタマイズするということになります。
  • WORKDIR
    コンテナ内の作業ディレクトリを設定します。
    存在しない場合は新規で作成され、以下多くのコマンドのカレントディレクトリとなります。
  • RUN
    イメージのビルド時に実行するコマンドを記述します。
    例えば、Ruby3.3.0のコンテナにnode.jsをインストールしたい場合などにここにインストールのコマンドを記述することによってインストールすることができます。
  • ENV
    コンテナで利用する環境変数を定義します。
    ここで定義された環境変数はこのイメージから生成される全てのコンテナで利用可能となります。
  • COPY
    ローカルからコンテナイメージにファイルをコピーします。
    RubyのGemfileなどをコンテナ内に移動するためによく使います。
  • ADD
    COPY命令に幾つかの追加機能が追加されたものです。
    COPYの内容はすべて含まれます。
    追加機能として、リモートURLからのファイルダウンロード機能や、アーカイブの自動展開機能が存在します。
  • CMD
    コンテナ起動時に実行したいコマンドを指定します。
    例えばここにRailsサーバー起動のコマンドを設定すれば、コンテナ起動と同時にRailsサーバーが起動します。
    また、CMDに指定したコマンドはコンテナ実行時に引数としてコマンドを渡すことで上書きすることができます。
    そのため、デフォルトのコマンドを指定したいが、柔軟に実行時に変更もしたいという場合に使うと良いでしょう
  • ENTRYPOINT
    こちらもコンテナ起動時に実行するコマンドを指定します。
    CMDコマンドとの違いは、上書きすることができないという点です。
    ENTRYPOINTに設定されたコマンドは絶対に実行されるため、CMDと用途によって使い分けましょう。
    また、ENTRYPOINTとCMDを両方記述することもできます。
    この場合、ENTRYPOINTとCMDは組み合わされて一つのコマンドとして実行されます。
    よく使われるのが、ENTRYPOINTに命令文を書き、CMDに実行対象を記述するといった使い方です。
    これにより、命令は確実に実行され、実行対象は引数で動的に変更できるようになります。
  • EXPOSE
    コンテナが外部に公開するポートを指定する...と見せかけたただのメモ書きです。
    この命令自体にポート公開の機能はありません。
    実際にポートを開くにはコンテナ起動時に-pオプションを使用してポートを指定する必要があります。
    EXPOSE命令はシステムや技術者に、このコンテナはこのポートを開いているということを伝えるドキュメントに過ぎません。
  • VOLUME
    コンテナ内の特定のディレクトリ内のデータをボリュームとして永続化するための命令です。
    ここで指定されたディレクトリを匿名ボリュームとしてDockerホスト上に保存し、コンテナ終了後もデータを保持することができます。

docker-compose.ymlの記述

  • version
    docker-compose.ymlのファイル形式のバージョンを指定します。
  • services
    Docker Composeで管理したいサービスをこのセクションに記載していきます。
    • サービス名
      サービス名は自由に設定可能です。
      webサーバーはweb、dbサーバーはdbなどわかりやすい名前をつけると良いでしょう。
    • build
      指定した相対パスに存在するDockerfileを用いてコンテナを生成し、それをサービスとして使用します。
    • image
      buildが設定されているかどうかによって役割が変わります。
      buildが設定されている場合、ビルドされたコンテナに対して名前をつけるために用いられます。
      buildが設定されていない場合、ここに設定された名前を用いてDockerHubを検索し、発見したイメージを用いてコンテナを生成し、サービスとして使用します。
    • ports
      ホストのポートとコンテナのポートをマッピングします。
      これにより、外部からホストのポートにアクセスすることによってコンテナにアクセスすることが可能となります。
    • volumes
      データの永続化や共有のためにホストとコンテナ間でボリュームをマッピングします。
      これにより、片方で変更があった場合もう片方でも即座に変更が反映されます。
      また、名前付きボリュームを使用することで複数のサービス間でデータを共有することも可能です。
    • environment
      コンテナ内で参照できる環境変数を定義します。
    • depends_on
      設定したサービスが起動した後、サービスが起動するようになります。
      例えばdbに依存したサービスの場合、dbサーバーが起動していなければ上手く動きません。
      そのような事態を防ぐために、dbサーバーが起動した後にサービスが起動するようにすることが可能です。
    • networks
      サービスが利用するネットワークを指定します。
      詳細は後述。
  • networks
    ここに複数のネットワークを設定することで、各サービスを別々のネットワークにのせることが出来るようになります。
    各サービス内において、ここに設定したネットワークを記載してあげることで、ネットワークを分離することができます。
    ネットワークを分離せず、一つのネットワークに載せたい場合はこのセクションは不要です。
  • volumes
    各サービスで利用できる名前付きボリュームを定義します。
    この名前付きボリュームをサービスで参照することで、名前付きで情報を永続化することができます。
    また複数サービスで同一の名前付きボリュームを使用し、データを共有することも可能です。

最後に

Dockerfileとdocker-compose.ymlの基本的な設定は以上になります。
Dockerにおける中核を担うファイル群なので、設定をなるべく把握しておきましょう。

Discussion