前回の記事では、単一のイメージまたはコンテナを取り扱う方法について取り上げてきました。
しかし、実際の開発では、データベースや Webサーバなどの複数プロセスを組み合わせてシステムを構成するのが一般的です。Docker を使ったシステムでは、1つずつコンテナを割り当てることが公式ドキュメントでも推奨されており、必然的に複数のコンテナを扱うことが多くなります。
ただ、扱うコンテナ数が増えたり、さまざまなオプションを使って起動するものが増えたりすると、その管理が大変になってきます。
そこで本記事では、その管理を簡単にする「Docker-Compose」というツールを紹介します。
Docker-Composeとは?
Docker-compose を理解するには、Docker の流れを抑えておく必要があります。
Docker はアプリケーションが動作するのに必要な設定をコンテナにまとめて実行する環境のことです。
コンテナの起動には次のような流れがあります。
- DockerHub(Docker イメージのレジストリの一つ)などのレジストリからイメージ(コンテナの設計図)をPullする。
- pull したイメージをもとにDockerfile(イメージの定義書)でコンテナの設計図を作成する
- Docker Compose で Dockerfile をビルドすることで Docker イメージ(コンテナの設計図)が作られ、そのイメージを起動することでコンテナが起動する。
この流れだけ見ると Dockerfile ごとにコンテナを起動しなければいけないのかと面倒に思う人もいるでしょう。
しかし、ここで活躍するのが「Docker Compose」です。
Docker Compose とは、複数のコンテナをまとめて管理するツールで、複数のコンテナ(データベース、キャッシュ、Web API など)で構成されたアプリケーションをどう展開するか定義できます。
Docker コマンドのみで複数のコンテナで構成されたアプリケーションを起動する場合、コンテナごとに設定をパラメータで指定しながら、コンテナの依存関係に従って起動していかなくてはなりません。
しかし、コマンドや手順が複雑になると、他の環境で使う場合に、ミスが発生しやすくなります。
こういった場合に、Docker Compose を使えば、複数コンテナの設定やオプションを「docker-compose.yml」という設定ファイルに記述することで、一つのコマンドで複数コンテナを一度に起動できます。
Docker-Composeのメリット
実行コマンドが簡潔になる
起動するコンテナやオプション情報など全て一つのファイル「docker-compose.yml」に記述できるため、イメージを作成する「docker build」やコンテナを起動する「docker run」などのコマンドを、コンテナの数だけ実行する必要がなくなり、コマンドを打つ手間が省けたり、打ち間違えによるミスをなくせたりと、実行自体が簡潔になります。
Docker-Composeの利用例
開発環境を標準化する
開発に携わるメンバー間で開発環境を手作業で整備する場合、時間や手間がかかるうえに、間違えてしまうこともあるかもしれません。ですが、Docker Compose を使えば、設定ファイルさえ手元にあれば開発環境の細部までを気にすることなく、一つのコマンドで環境を整備でき、効率化を図れます。
テスト環境を自動化する
全てのコンポーネントを結合して行うテストの自動化には、それぞれ独立したテスト環境を用意する必要がありますが、Docker Compose で環境定義をしておけば、一つのコマンドでテスト環境を起動でき、テスト終了後は、簡単に破棄できます。
単一ホストへデプロイする
本番環境が単一サーバの場合、本番環境を意識した機能が充実している Docker Compose を使えばリモートにある Docker Engine に対してデプロイすることもできます。
「docker-compose.yml」ファイルがあれば、同じ環境を作成できる
「docker-compose.yml」ファイルが一つの環境の設計書のような役割になるため、違う環境でも、このファイルさえあれば、同様の環境が作成可能になります。
この記事の対象者
- 初めてDockerでの環境構築を検討している
- 複数のローカル環境を1台の開発マシンで構築していて、管理を煩雑に感じている
- Dockerをしっかり勉強する時間は無いが、とりあえず概要を知って使えるようになりたい
前提条件
本記事では Mac での開発環境を前提に書かれています。
Windows でも動くとは思いますが、若干の専用対応が必要になるかもしれません。
必須知識
Laravel や cakePHP、Rails といった開発環境の構築経験。
※本記事は Docker Project の作成方法を解説する記事となるため、各種 Framework を用いた Project の生成手順には言及しておりません。
所用時間
15 分 ~ 30 分
そもそもDockerって何がすごいの?
従来の手順では開発 Project ごとに環境を用意するのは非常に大変でした。
1つのマシンの中で複数の環境を作ろうとしたら他の開発環境で行っていた設定が邪魔をしたり、かといって仮想マシンで作成しても動作が重くて開発が難しかったり…。
その点、Dockerは煩わしい操作の殆どをカット可能なことに加え、環境構築もコマンドをたった1行実行するだけで完了し、何より動作が非常に軽いことが特徴です。
簡単にまとめると以下のような利点がありますね。
- 土台 の用意さえしてしまえば誰でも扱えるため、チーム開発にも向いている
- 既存環境を流用しやすく、新しいプロジェクトがスタートした時にもローカル環境を用意しやすい
- 本番環境やテスト環境でも同じ手順で環境を起動できる
- 仮想マシンより処理速度が圧倒的に早い
本記事は上記における「土台」の部分を作ってみようといった内容となります。
Docker を用いた環境構築ステップ
Docker での環境構築には以下のステップがあります。
- 作りたいサービスの内容を考える。
- サービスの単位を細分化して考える( 例えば gw / db / app の構成等 )
- docker-compose.yml ファイルを作成し、container 作成プロセスの定義
※ container とは仮想化技術における VM( Virtial Machine ) のようなものだと思ってください。 - 微調整を入れつつ構築
さて、それでは早速構築に参りましょう。
今回作成するのは以下の環境です。
- gw ( nginx )
- app ( php / laravel )
- db ( MySQL 8.0 )
とりあえず動かしてみる
M1 チップの Mac を使っている場合、事前に以下のコマンドを実行しておいてください。
# 8.0 の部分は使用したい MySQL の version に変更
docker pull --platform linux/amd64 mysql:8.0
Docker Project のダウンロード
最終形があると分かりやすいと思うので、こちらの github repository を git clone してください。
Laravel Project も含まれるため、新規に Laravel を立ち上げる必要はありません。
sample_docker_web
Docker Project の起動
まず terminal を起動しましょう。
clone した repository のフォルダ直下へカレントディレクトリを移動し、以下のコマンドを実行してください。
docker-compose build
エラーが発生しないかをしっかり確認しましょう。
既知の問題として「buildkit」の使用を true としている場合に MySQL の image が見つからない時があります。
「ERROR [internal] load metadata for docker.io/library/mysql:8.0」といったエラーが発生した場合、Docker の Preferences を開き、Docker Engine の設定から buildkit を false に設定してください。
build でエラーが無くなったら以下のコマンドを実行してください。
このコマンドで docker project が生成され、バックグラウンドで起動します。
# -d オプションをつけることでバックグラウンドで container が稼働するようになります。
# -d をつけないとメインスレッド処理となってしまうため注意しますしょう。
docker-compose up -d
Laravel Project の composer install 実行
起動した container へ接続し、Laravel の composer install を行います。
まず以下のコマンドを実行し、container への接続に必要となる container id を取得します。
docker ps | grep sample_docker_web_app
実行すると以下のような結果が表示されるかと思います。
一番左のデータが container id です。
以下のコマンドを実行し、container へ接続します。
# <container_id> の部分を先の手順で取得した値に置き換えてください。
docker exec -it <container_id> bash
接続に成功すると「/var/www/sample_web」がカレントディレクトリの状態で、ssh 接続した時のような表示になったかと思います。
composer install を実行します。
composer install
ブラウザで表示検証
「http://localhost:10080」にアクセスし、Laravel!! と表示されれば成功です。
具体的な解説
さて、ここからは具体的な設定ファイルの解説に移ります。
docker は難しく見えがちですが、意識すべきファイルは少なかったりします。
意識すべき 3 つの要素
Docker Project の構築において重要な要素は以下の3つです。
- Docker-Compose.yml
- DockerFile
- Docker Image
1つずつ詳しく見ていきましょう。
その1「 Docker-Compose.yml 」について
Docker-Compose.yml は言うなれば「この Docker Project で作成する container と Host OS の関連付け」や「container の初期設定」を定義するファイルです。
まずは実際の記述を見てみましょう。
version: '3.3' # Docker-Compose.yml を実行するにあたっての docker build の version 指定
services: # コンテナを定義する親要素
app:
container_name: sample_web_app # コンテナ名の設定
build: ./docker/app # DockerFile の参照先
volumes: # HostOS のディレクトリやファイルとコンテナ内でシンボリックリンクを繋げる
- ./www:/var/www
networks: # ローカルネットワークにおける IP アドレスの指定
web_segment:
ipv4_address: 172.240.0.2
gw:
image: nginx # DockerFile を使用しない場合は Docker-Compose.yml で直接 image を指定できる。
container_name: sample_web_gw
ports: # ポートフォワーディング この例なら HostOS への 10080 ポートアクセスをこのコンテナの 80 番ポートにフォワードする。
- 10080:80
volumes:
- ./www:/var/www
- ./docker/gw/default.conf:/etc/nginx/conf.d/default.conf # conf ファイルの紐付け
depends_on: # 依存関係の定義 この例なら app container が作成されてから構築の意味
- app
networks:
web_segment:
ipv4_address: 172.240.0.3
db:
build:
context: .
dockerfile: docker/mysql/Dockerfile
volumes:
- ./docker/mysql/db:/docker-entrypoint-initdb.d
- db-store:/var/lib/mysql # DB データの永続化。本ファイルの例の場合、末尾の「volumes: db-store:」を使用している。詳しい解説はそこで。
- ./logs:/var/log/mysql
- ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
ports:
- "33306:3306"
environment: # MySQL の場合初期 DB の作成と root password 及び mysql user account の登録が可能
MYSQL_ROOT_PASSWORD: password
MYSQL_USER: administrator
MYSQL_PASSWORD: password
MYSQL_DATABASE: default_database
TZ: "Asia/Tokyo"
networks:
web_segment:
ipv4_address: 172.240.0.4
networks: # docker 仮想ネットワークの作成
web_segment:
driver: bridge # driver の選択
ipam:
config:
- subnet: 172.240.0.0/24 # subnet mask の指定。
この例なら、この Docker Project に所属する container は 172.240.0.0~254 の範囲を
同一ネットワークとして判定可能となる。
volumes: # Docker MySQL のデータは再起動で消えてしまいます。
そのため他の container と同じく volume 定義を皆試すと思いますが、
Docker の仕様上エラーになります。
Docker の「名前付きボリューム」と呼ばれる領域を構築し、データの永続化を行います。
db-store:
重要なところパラメータにコメントを設定しているため、それらを読めば内容がざっくり理解できるかと思います。
基本的には上記のようなベースとなる Docker-Compose.yml を作成し、カスタマイズして使うのが基本となります。
続いて DockerFile の説明です。
その2「 DockerFile 」について
app container に設定している「./docker/app」の DockerFile を例に見てみましょう。
# 使用する Docker Image の指定と container の生成
FROM php:8.0-fpm
#------------------------------------------------------------------------#
# 以降は生成された container に対しての初期設定用コマンド群
#------------------------------------------------------------------------#
# php.ini ファイルの設置
COPY php.ini /usr/local/etc/php/
# Laravel を動かす上で必要となる
RUN apt-get update
RUN apt-get install -y zlib1g-dev mariadb-client
RUN apt-get install -y \
nano \
libicu-dev \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libzip-dev \
npm \
&& rm -rf /var/lib/apt/lists/*
# npm の更新及び webpack build に必要な package をインストール
RUN npm install npm@latest -g
RUN npm install -g n
RUN n 14.15.2
RUN update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10
RUN docker-php-ext-install zip pdo_mysql
RUN npm install -D ts-loader typescript vue-property-decorator
RUN npm install -g yarn
RUN npm install --save-dev tsc-watch
RUN npm install --save-dev watch
# php の package 管理システム、composer の設置
COPY --from=composer /usr/bin/composer /usr/bin/composer
# 環境変数の定義
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
ENV PATH $PATH:/composer/vendor/bin
# composer で laravel 実行ファイルを事前に定義
WORKDIR /var/www/sample_web
RUN composer global require "laravel/installer"
この例で言えば Laravel を実行できる環境を作る上で、WebPack の実行環境構築に伴い TypeScript の実行環境も用意している形になりますね。
例を見て「Linux で環境を構築する時と同じ」と感じた方もいるのではないでしょうか。
その認識は正しくて、Docker における container の基本構造は「作成する container と Host OS の繋ぎ込みは Docker独自の設定だが、内部の実装は通常のサーバ構築とほぼ同じである」となります。
上記の理由から Docker container は簡単に立ち上げと停止のルール付けができる軽いVMであると言って差し支えありません。
Docker 化したいサービスに応じ、初期設定を適切に記述しましょう。
使用しているコマンドの概要を以下に記載させていただきます。
- FROM ・・・ container のベースとなる image の指定
- RUN ・・・ container に実行させたいコマンドの指定
- COPY ・・・ container にファイルをコピーしたい場合に使用
- WORKDIR ・・・ RUN で記述するコマンドを実行するカレントディレクトリの変更
その3「 Docker Image 」について
さて、ここまで色々と説明したのですが全ての基本となるDocker Imageの説明を最後にさせていただきます。
一言で表すなら Docker container の構築を想定し最適化されたcontainerのtemplateファイルとなります。
Docker HubでImageを探したり、以下のコマンドでダウンロード可能なImageを探すことができます。
用途に応じ必要な Image を探し、使用しましょう。
# 例: docker search php
docker search <keyword>
Image の自作も可能なため、慣れてきたら自分で作ってみるのもいいでしょう。
まとめ
今回の解説は以上となりますが、いかがでしたでしょうか?
要約すると、実際の Docker Project の構築手順は以下の形となります。
- DockerFile 作成で必要となる実行コマンドを調査する
※ 本記事の例であれば npm や composer の設定コマンド等ですね。 - Docker Project の中心となる Docker-Compose.yml ファイルを作成する
- DockerFile を作成する
- Docker-Project を立ち上げる
ローカル環境を複数立ち上げる際の vendor ファイルの配置や衝突を意識する必要もなく、Docker Project を配布するだけで全員が同じ環境を共有できる Docker は非常に便利です。
是非使ってみてください。
以下の記事では筆者がよく使うコマンドをまとめました。
Docker入門(第1回)|初心者向けに概要や基本コマンドを解説