docker-composeの便利さが体感できる(初級編)


 本記事では、簡単なサービスを構築する例を使用して、docker-composeの使い方をご紹介します。

 まず最初に、dockerコマンドのみでの構築方法について、その後、同じサービスをdocker-composeで構築する方法について書いております。

 

 docker-composeは、複数のコンテナを使うサービスを構築する際に力を発揮するDockerのツールです。

 なにか1つのサービスを構築する場合、WebサーバとDBサーバなど、複数のシステムを結合して構築することが良くあると思います。

 当然、使い慣れたdockerコマンドで立派なサービスが構築できるのですが、docker-composeコマンドを使いますと、もっと簡単にもっと確実に構築することが可能となります。

 以下に、ApacheサーバとMariaDBサーバを利用したサービスを、dockerコマンドだけで構築する方法とdocker-composeコマンドにて構築する方法の2つの方法をご紹介したいと思います。

 2つの方法がどのくらい違いがあるのかを体感していただければと思います。

 

構築するシステムについて

 構築するシステムを下図に示します。Docker環境はLinux(CentOS7)版を使用します。

docker-compose01

 システムは簡易的な3層アプリケーションサーバで、Webコンテナ(web01)とDBコンテナ(db01)の2コンテナ構成とします。

 Docker内に、サービス専用のdockerネットワーク(test-net01)を作成して利用します。DBコンテナのポートには外部からは直接アクセスできません。

 また、各々のコンテナにマウントするデータボリュームを作成します。

 このシステムは、Dockerホスト外からブラウザにて8080番ポートにアクセスすると、DBサーバ内の特定のデータを、PHPプログラムがSQLにて取得して、そのデータをブラウザに返すというサービスです。

■ 本記事の目次に戻る ■

docker-composeのインストール

 念のため、docker-composeのインストール方法について簡単に紹介させていただきます。

 方法は、基本的に、Docker公式サイト上に存在するdocker-composeのバイナリ(OS単位に別ファイル)をダウンロードして、パスの通った場所に、ファイル名を「docker-compose」として保存するだけです。

 本ページで使用するDockerはLinux(CentOS7)版ですので、docker-composeのLinux版についてご紹介させていただきます。

 rootにて以下のコマンドを実行します。赤字の部分は、docker-composeのバージョンになります。※現在(2016.09)の最新版は「1.8.0」

# curl -L https://github.com/docker/compose/releases/download/1.8.0/docker-compose-`uname -s`-`uname -m` > /usr/bin/docker-compose
# chmod 755 /usr/bin/docker-compose

以下のコマンドで、docker-composeのバージョンを確認してみましょう。

# docker-compose -v

以上でインストールは終わりです。

 

※Dockerのインストールについては省略させて頂きます。申し訳ございません。CentOS7へのインストールでしたら、本サイトでも紹介させていただいておりますので、もし宜しければ別記事「CentOS7へのDockerのインストール」をご覧ください。

■ 本記事の目次に戻る ■

 

dockerコマンドによるシステム構築

 最初は、dockerコマンドのみでの構築方法のご紹介です。

 作業に入る前に、作業用のディレクトリを作成します。今回は、作業ユーザのホームディレクトリ上にex1ディレクトリを作成し、使用することにします。

 

データボリュームの作成

 2つのコンテナにマウントするデータボリュームを作成します。作成したデータボリュームは、コンテナの起動時に「-v」オプションで指定することになります。

 最初はWebコンテナ用の2つのデータボリュームを作成します。

$ docker volume create --name web01_doc
web01_doc
$ docker volume create --name web01_log
web01_log

 作成されているか確認します。

$ docker volume ls | grep web01
local web01_doc
local web01_log

 次に、同じようにDBコンテナ用の2つのデータボリュームを作成します。

$ docker volume create --name db01_data
db01_data

 作成されたか確認します。

$ docker volume ls | grep db01
local db01_data

 

Dockerネットワークの作成

 サービス専用のDockerネットワークを作成します。作成したネットワークは、コンテナの起動時に「- -net」オプションで指定することになります。

$ docker network create -d bridge test-net01
69bfaf47b1e6640a872fd43c3851d117d8bb4b94fbe4b5839de39bf23a950111

 「-d」オプションに「bridge」と設定することで、Dockerホスト外と通信が可能になります。

 作成されているか確認します。

$ docker network ls | grep test-net01
69bfaf47b1e6 test-net01 bridge local

■ 本記事の目次に戻る ■

DBコンテナの起動

 基本的に、DBサーバは、Webサーバが起動する時点で、既に起動されていた方が良いと思います。よって、最初はDBサーバから起動します。

 ベースイメージはMariaDBの公式Dockerイメージ(現時点の最新版)を使用します。

$ docker run -d --net test-net01 -v db-1_data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=testtest --name db01 mariadb:latest

※青字部分は、最初にご覧いただきました今回構築するシステムの図内で定義した値になります。

※赤字部分の「testtest」はMariaDBのrootユーザの初期パスワードになります。ご自分のお好きな文字列を指定してください。

 「docker ps」コマンドで起動確認を行います。

$ docker ps
CONTAINER ID IMAGE          COMMAND                CREATED STATUS                       PORTS    NAMES
d96be66a4ad6 mariadb:latest "docker-entrypoint.sh" About a minute ago Up About a minute 3306/tcp elated_swirles

 起動が確認できました。

 

DBコンテナの初期設定

 本章の内容は、Docker固有の設定ではなく、MariaDB固有の設定、及び今回構築するシステムのテストデータの作成に関するものです。よって、dockerコマンドのみでの構築とdocker-composeでの構築の両方とも同じ内容を行います。

 では、作業に入ります。

 DBコンテナが起動しましたら、DBコンテナ内でbashを起動して、DBのセットアップを行います。

$ docker exec -it d96be66a4ad6 bash

赤字の部分は、DBコンテナのコンテナIDです。ご自分の環境に合わせて指定してください。

 DBコンテナ内で行うのは、データベースとテーブルの作成、及び初期データの投入です。

root@db01:/# mysql -u root -p
Enter password:xxxxxxxxxx

 赤字の部分は、DBコンテナ起動時に指定したMariaDBのrootユーザのパスワードになります。

 データベースへのログインが完了しますと、以下のようなプロンプトに変わると思います。

MariaDB [(none)]>

 ここからは、本記事の本筋ではありませんので、データベース作成とテーブルの作成、及び初期データの投入まで一気に行います。

MariaDB [(none)]> create database testdb;
MariaDB [(none)]> grant all privileges on testdb.* to testadmin identified by 'testtest';
MariaDB [(none)]> use testdb;
MariaDB [testdb]> create table testtable ( name varchar(100),data varchar(100) );
MariaDB [testdb]> insert into testtable ( name,data ) values ( 'hello','hello world!' );

 念のため簡単に説明いたします。

 MariaDB上に「testdb」というデータベースを作成し、そのデータベースの全権を持つ「testadmin」ユーザを作成し、認証パスワードに「testtest」を設定しました。

 また、「testdb」内に「testtable」を作成し、「name」が「hello」で「data」が「hello world!」のレコードを追加しました。

■ 本記事の目次に戻る ■

Webコンテナの起動

 次にwebコンテナを起動します。

 ベースイメージはPHPの公式Dockerイメージ(現時点の最新版)のapache同梱版を使用します。

$ docker run -d --net test-net01 -p 8080:80 -v web_doc:/var/www/html -v web_log:/var/log/apache2 --name web01 php:7-apache

※青字部分は、最初にご覧いただきました今回構築するシステムの図内で定義した値になります。

 「docker ps」コマンドで起動確認を行います。

$ docker ps
CONTAINER ID  IMAGE        COMMAND               CREATED STATUS            PORTS                NAMES
81a01a55b5bc  php:7-apache "apache2-foreground"  23 hours ago Up 3 seconds 0.0.0.0:8080->80/tcp web01

 起動が確認できました。

 

Webコンテナの初期設定

 本章の内容は、DBコンテナの初期設定ど同様に、Docker固有の設定ではなく、PHPの公式Dockerイメージ固有の設定、及び今回構築するシステムのテストアプリケーションの作成に関するものです。よって、dockerコマンドのみでの構築とdocker-composeでの構築の両方とも同じ内容を行います。

 では、作業を始めます。

 このシステムの動作確認のための、DBアクセス用のPHPソースファイルを以下の内容で作成します。ファイル名は「test.php」にしましょう。最初に作成したDockerホスト上の作業ディレクトリ内に作成してください。

<?php
$link = mysqli_connect('db01', 'testadmin', 'testtest', 'testdb');
if ($result = mysqli_query($link, "select * from testtable")) {
while ($row = mysqli_fetch_array($result, MYSQLI_NUM)) {
 echo $row[1] . "\n";
 }
 mysqli_free_result($result);
}
mysqli_close($link);
?>

 このPHPプログラムは、名前が「db01」のDBサーバに「testadmin」ユーザで接続して、SQLクエリ「select * from testtable」を実行し、結果の2カラム目を出力します。

 作成しましたら、Webコンテナ内のApacheのDocumentRootディレクトリにコピーします。

$ docker cp test.php 81a01a55b5bc:/var/www/html/

赤字の部分は、WebコンテナのコンテナIDです。ご自分の環境に合わせて指定してください。

 よって、Webサーバ上で正常に動いたとしたら、DBサーバに登録したデータを読み込んで表示するはずです。

 先ほど、「hello world!」の文字列をDBに登録してあります。

 

 次に、Webコンテナ内でbashを起動して、PHPの初期設定を行います。

$ docker exec -it 81a01a55b5bc bash

赤字の部分は、WebコンテナのコンテナIDです。ご自分の環境に合わせて指定してください。

Webコンテナ内で以下のコマンドを実行してください。

# docker-php-ext-install mysqli

※これは、PHPがmysqli使用できるようにするためのコマンドになります。詳細は本記事の趣旨と異なりますので省略させてください。

 処理が完了しましたらWebコンテナを再起動します。

$ docker restart 81a01a55b5bc

赤字の部分は、WebコンテナのコンテナIDです。ご自分の環境に合わせて指定してください。

 

動作確認

 Dockerホストの外からブラウザにて、Dockerホストの8080番ポートにアクセスします。

ブラウザ上に「hello world!」と表示されましたでしょうか。

■ 本記事の目次に戻る ■

docker-composeコマンドによるシステム構築

 次に、同じ内容をdocker-composeコマンドを使用して行います。

(注意)
8080番ポートが被るので、dockerコマンドのみの作業にて起動した2つのコンテナを「docker stop」コマンドで停止してください。

作業に入る前に、作業用のディレクトリを作成します。今回は、作業ユーザのホームディレクトリ上に「ex2」ディレクトリを作成し、使用することにします。

 

docker-compose.ymlファイルの作成

 作業ディレクトリ内に、以下の内容のdocker-compose.ymlを作成します。

version: "2"
services:
  web01:
  image: php:7-apache
  volumes:
  - web01_doc:/var/www/html
  - web01_log:/var/log/apache2
  ports:
  - "8080:80"
  depends_on:
  - db01

  db01:
  image: mariadb
  volumes:
  - db01_data:/var/lib/mysql
  environment:
  MYSQL_ROOT_PASSWORD: testtest

volumes:
  web01_doc:
  web01_log:
  db01_data:

※青字部分は、最初にご覧いただきました今回構築するシステムの図内で定義した値になります。

 dockerコマンドのみで行う際には、事前にコマンドでデータボリュームを作成したり、起動時に多くのオプションを指定したりしましたが、docker-composeコマンドを使用する場合は、それらをdocker-compose.ymlファイルに既定のフォーマットに従って記述するだけ大丈夫です。

 簡単に内容について説明させてください。

 「service:」と「volumes:」のキーワードが記述されてますが、「service:」はコンテナに関する定義情報、「volumes:」はデータボリュームの定義情報を記述します。

 Dockerネットワークについての記述が見当たりません。ネットワークの設定が無い場合は、デフォルトとして、1回のdocker-composeコマンドの実行で作成されるコンテナ群に、1つの専用のDockerネットワークが作成され、定義されたコンテナ群の全てが、そのネットワークに属します。

 「service:」内の「web01」の定義内に「depends_on」とありますが、これは、web01はdb01にdepends_on(頼る)する、つまり、web01はdb01が起動してから起動されます。コンテナ間の依存関係の定義が可能です。

 本記事では、docker-compose.ymlファイルの説明はこの程度にさせてください。詳細内容につきましては、別記事でご紹介させて頂く予定です。

■ 本記事の目次に戻る ■

サービスの起動

 作業ディレクトリ上で、以下のコマンドを実行してください。カレントディレクトリ内の「docker-compose.yml」が読み込まれて、記述内容通りにシステムが起動します。

$ docker-compose up -d
Creating network "ex2_default" with the default driver
Creating volume "ex2_web01_log" with default driver
Creating volume "ex2_db01_data" with default driver
Creating volume "ex2_web01_doc" with default driver
Creating ex2_db01_1
Creating ex2_web01_1

 実行後の出力内容より、このコマンド1つで、以下のものが作成されました。

  • Dockerネットワーク ex2_default(test-net01に該当)
  • データボリューム ex2_web01_log(web01_logに該当)、ex2_db01_data(db01_dataに該当)、ex2_db01_data(db01_dataに該当)
  • コンテナ ex2_db01_1(db01に該当)、ex2_web01_1(web01に該当)

 先ほどは、dockerコマンドで1つ1つ作ったものが、docker-composeコマンド1発で作成されました。

 念のため、以下のコマンドで起動確認を行って下さい。

$ docker-compose ps
 Name       Command                      State   Ports
------------------------------------------------------------------------
ex2_db01_1  docker-entrypoint.sh mysqld  Up      3306/tcp
ex2_web01_1 apache2-foreground           Up      0.0.0.0:8080->80/tcp

 コンテナが2つ起動されているのが確認できます。

 dockerコマンドで起動した場合と名前は異なりますが、WebコンテナとDBコンテナが起動されてます。

 次は、データボリュームの確認です。

$ docker volume ls | grep ex2
local ex2_db01_data
local ex2_web01_doc
local ex2_web01_log

 Dockerネットワークの確認です。

$ docker network ls | grep ex2
97778683a2f5       ex2_default            bridge           local

 必要なものは全て作成されていることが確認できました。

 

データベースの初期設定

 初期設定は、dockerコマンドのみの時に行ったものと同じ作業を行って下さい。

 

Webコンテナの初期設定

 初期設定は、dockerコマンドのみの時に行ったものと同じ作業を行って下さい。

 

動作確認

 Dockerホストの外からブラウザにて、Dockerホストの8080番ポートにアクセスします。前と同じように「hello world!」の文字が表示されたと思います。

 

(注意)
もし、dockerコマンドで起動したコンテナで再度試す場合は、以下のコマンドで、docker-composeで起動したコンテナを停止してから行って下さい。2つのコンテナは両方とも停止されます。

$ docker-compose stop

■ 本記事の目次に戻る ■

まとめ

 dockerコマンドのみの作業は、全ての部品を自作して、それらをつなぎ合わせるということを全て自分で行う必要があります。システムの規模が大きくなると、ミスも発生しやすくなると思います。

 docker-composeを利用すると、構築したいシステムを設計して、その最終イメージをdocker-compose.ymlに記述して、読み込ませるだけで、作業の大部分は終わってしまいます。

 それに、docker-compose.ymlは、YAML形式という汎用的なフォーマットを採用しており、とても見やすく、理解しやすいと思います。

 私は、まだdocker-composeを知らなくて、dockerコマンドだけでDockerと格闘していたころは、dockerコマンドを羅列したシェルスクリプトを作成し、そのスクリプトをメンテナンスしてました。

 今回は、docker-composeの便利さを少しでも体感していただきたくて、記事を書かせていただきました。

 本記事の内容は、docker-composeの基本中の基本程度の内容です。もっともっと素晴らしい機能が実装されておりますので、色々調べてご利用いただければと思います。

 なにか便利な使い方など見つけられましたら、コメントいただけるとうれしいです。もっと使いこなせるようになりたいので、参考にさせていただきます。

 尚、本記事は、dockerコマンドを否定するものでは決してありません。この記事を書いてますが、私はdockerコマンドを使う頻度のほうが圧倒的に高いです。

 要は、適材適所が重要だと思います。

 

 今回は長文を最後までお読みいただき本当にありがとうございました。

■ 本記事の目次に戻る ■


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です