最近Dockerが力を入れている機能の1つが、Dockerクラスタ環境を構築・運用するための機能であるswarmモードだ。本記事ではDocker 1.13以降で追加されたswarmモード関連の機能を紹介する。

記事前編では、Dockerの開発体制の変化や最近追加された新機能について紹介した。続いて今回は、最近機能強化が続いているDockerの「swarmモード」関連の新機能について紹介していこう。

Dockerの普及により、複数のマシンを組み合わせたクラスタ環境でDockerを利用してサービスを提供する構成が検討されるようになった。Dockerクラスタ構築を支援するKubernetesやCoreOSといったソフトウェアも登場している。Docker自体も、クラスタ構築ツールである「Docker Swarm」を提供していたが、Docker 1.12ではこの機能の一部がDocker本体に「swarmモード」として組み込まれた。これにより、追加のソフトウェアをインストール/設定することなしに、Docker本体だけでDockerクラスタを構築し、複数台のマシン上のDockerデーモンを連携させて容易にコンテナを分散稼動させたり、冗長性のある構成でのサービス運用が行えるようになっている(図1)。

図1 Dockerだけでクラスタを構成できるswarmモード
図1 Dockerだけでクラスタを構成できるswarmモード

swarmモードの概要

Dockerのswarmモードは、「manager」ノードと「worker」ノードから構成される。managerノードはクラスタを管理するノードで、workerノードはコンテナを稼働させるノードだ。managerノードはworkerノードを兼ねることもできるので、1つのマシンだけでswarmモードを利用することも可能だ。

swarmモードを使ってクラスタを構成するには、まずmanagerノードで「docker swarm init」コマンドを実行してマネージャーを稼働させる。このとき、マシンに複数IPアドレスが割り当てられている場合は「–advertise-addr <IPアドレス>」オプションでほかのノードと通信するために使用するIPアドレスを指定する必要がある。

たとえば「192.168.1.10」というIPアドレスを使用する場合、次のようになる。

# docker swarm init --advertise-addr 192.168.1.10
Swarm initialized: current node (7aquw76ng1tbpll9yrya8d3ge) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-40oas1mo53i4o172j3mokf3b67d2al9cqcnh5lyhw12togq7if-923xulrntakv3k3et4kkwrzrg 192.168.1.10:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

docker swarm initコマンドを実行すると、クラスタに加入するためのコマンドおよびその引数がが表示されるので、これをworkerノード上でそのまま実行するだけでクラスタ内にノードを追加できる。たとえば上記の例の場合、次のようなコマンドをworkerノード上で実行する。

# docker swarm join --token SWMTKN-1-40oas1mo53i4o172j3mokf3b67d2al9cqcnh5lyhw12togq7if-923xulrntakv3k3et4kkwrzrg 192.168.1.10:2377
This node joined a swarm as a worker.

なお、swarmモードでは下記のポートを利用するので、ノード同士がこれらのポートにアクセスできるようファイアウォールの設定を行っておく必要がある。

2377/tcp
7946/tcp
7946/udp
4789/tcp
4789/udp

たとえばfirewalldを利用している場合、次のように実行することで一時的にこれらのポートを開放できる。

# for p in 2377/tcp 7946/tcp 7946/udp 4789/tcp 4789/udp; do firewall-cmd --zone=public --add-port $p;done

クラスタで稼働しているノードは、docker node lsコマンドで確認できる。次の例では、managerノードに加えて2つのworkerノードが稼働していることを確認できる。

# docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
68p32lyf31fz46kku2r91noq4     centos02            Ready               Active              
7aquw76ng1tbpll9yrya8d3ge *   fedora25            Ready               Active              Leader
k9sxalugwyl9dvpj15yyym1cv     centos01            Ready               Active      

swarmモードでは、「サービス(service)」という単位でコンテナの管理を行う。たとえばクラスタ上でコンテナを稼働させるには、docker service createコマンドを使用する。次の例は、「httpd」コンテナをクラスタ上で稼働させる例だ。ここで、「–replicas」はクラスタ内で稼働させるコンテナ数を指定するオプション、「–name」オプションはそのサービスを参照するための名前を指定するオプションだ。

# docker service create --replicas 1 --name httpd-test httpd

作成したサービスはdocker service lsコマンドで確認できる。

# docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE               PORTS
ad3mz54z3v4i        httpd-test          replicated          1/1                 httpd:latest   

稼働しているサービスは、docker service rmコマンドで削除できる。

# docker service rm httpd-test

このほかswarmモードではレプリカ数の動的変更やコンテナのローリングアップデートといった機能も用意されている。詳しくは、公式ドキュメントのSwarm mode overviewを参照して欲しい。

デプロイ機能の強化

さて、Dockerではサービス提供に必要なコンテナの情報をファイルに記述し、その設定ファイルを元にコンテナを起動・設定する「Docker Compose」というツールが用意されている。Docker Composeについては、以前の記事(複数のDockerコンテナを自動で立ち上げる構成管理ツール「Docker Compose」)で紹介しているので、詳しくはそちらを参照して欲しいのだが、Docker 1.13ではDocker Composerの設定ファイル(composeファイル)を利用して、swarmモードを使って立ち上げたDockerクラウド上にコンテナをデプロイすることが可能になった。この機能は、「docker stack」コマンドから利用できる。

また、この機能の導入とともに、composeファイルの書式も拡張され、新たに「deploy」という設定セクションが追加された。必要に応じて設定を追加・修正した上で、swarmクラスタを構築した環境で次のように「docker stack deploy」コマンドを実行することで、クラスタ内でサービスを起動できる。

$ docker stack deploy <スタック名> --compose-file <composeファイル>

「docker stack」コマンドでは、「スタック」という単位でサービスを管理する。スタック名はそれらを識別するための名称で、任意のものが利用可能だ。

たとえば、次のcomposeファイル(今回は「wp-blog.yml」というファイル名とした)は、MySQLが稼働するmysqlコンテナと、WordPressが稼働するwordpressコンテナについて定義したものだ。

version: '3'
services:
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: some_password
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress_password

  wordpress:
    image: wordpress:4.5-apache
    environment:
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress_password
      WORDPRESS_DB_NAME: wordpress
    ports:
      - 80:80

swarmモードで利用するcomposeファイルはバージョン3以降である必要があるため、「version」の部分を「3」に設定し、それ以外にも一部の値を変更しているが、このファイルは基本的には以前の記事で紹介したものと同一だ(バージョン番号については後述する)。

このファイルからクラスタにコンテナをデプロイする場合、次のように実行する。

# docker stack deploy wp-blog --compose-file wp-blog.yml
Creating network wp-blog_default
Creating service wp-blog_mysql
Creating service wp-blog_wordpress

作成されているスタックは「docker stack ls」コマンドで確認できる。

# docker stack ls
NAME                SERVICES
wp-blog             2

また、各スタックで稼動中のサービスやコンテナは「docker stack services <スタック名>」や「docker stack ps <スタック名>」で確認できる。

# docker stack services wp-blog
ID                  NAME                MODE                REPLICAS            IMAGE                  PORTS
2upz2n0b7l76        wp-blog_mysql       replicated          1/1                 mysql:5.7              
w58rurzrccs6        wp-blog_wordpress   replicated          1/1                 wordpress:4.5-apache   *:80->80/tcp

さらに、「docker stack ps <スタック名>」でどのコンテナがどのノード上で動いているかも確認できる。

# docker stack ps wp-blog
ID                  NAME                  IMAGE                  NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
mtqtlmj77rl6        wp-blog_wordpress.1   wordpress:4.5-apache   centos01            Running             Running 2 minutes ago                       
ddhn4n1vjzij        wp-blog_mysql.1       mysql:5.7              fedora25            Running             Running 2 minutes ago

なお、今回はホストの80番ポート経由でwordpressコンテナの80番ポートにアクセスできるよう設定している。swarmモードでは公開設定されたポートへのアクセスを自動的に適切なノードに転送する機能が提供されているので、たとえば今回の例では、「http://192.168.1.10/」「http://192.168.1.100/」「http://192.168.1.101/」のいずれでもwordpressコンテナにアクセスが可能だ。

スタックの削除は「docker stack rm」コマンドで行える(ドキュメント)。

# docker stack rm wp-blog
Removing service wp-blog_mysql
Removing service wp-blog_wordpress
Removing network wp-blog_default

そのほかのswarmモード関連新機能

swarmモード関連の改善としてはそのほか、Docker 17.05でサービスのアップデートやロールバックを行う際に稼動中のコンテナを停止させてから新しいコンテナを立ち上げるか、それとも新しいコンテナを立ち上げてから稼動中のコンテナを停止させるのかを指定する「–update-order」や「–rollback-order」オプションが「docker service create」や「docker service update」コマンドに追加された。

さらに、Dockerfile中で指定された「ENTRYPOINT」を上書きして別のものを使用できるようにする「–entrypoint」オプションの導入や、「docer service update」コマンドにネットワークの追加/削除を行う「–network-add」および「–network-rm」オプションが追加されるといった機能追加も行われている。

Docker Composeファイルのアップデート

docker stackコマンドでDocker Composeの設定ファイルが利用できるようになったことに伴い、この設定ファイルのフォーマットもアップデートされている。

Composeファイルでは、ファイル内にバージョンを記述することで互換性を保つような仕組みになっている。現在の最新バージョンは3.3で、これはDocker 17.06以降で利用が可能だ。ちなみに3.0はDocker 1.13以降、2.0はDocker 1.10以降で利用できる。バージョン間の違いについてはドキュメントにもまとめられているが、バージョン1は「volumes」や「networks」、ビルド引数の設定機能がない。また、Docker Composer 1.6までのサポートとなっており、これ以降のバージョンではサポートされない可能性があるという。バージョン2ではバージョン1から大きく構造が変わっているため、現在バージョン1の設定ファイルを利用している場合、バージョン2の設定ファイルに早めに移行するほうが良いかもしれない。

バージョン2では「services」というキーが導入され、コンテナ関連の設定はこのキー以下に記述するようになった。また、ボリュームやネットワーク関連の設定を記述する「volumes」や「networks」などのキーも導入されている。

バージョン3ではswarmモードでのサポートを加えた一方、いくつかのオプションが削除され、またswarmモードでのデプロイ設定を記述する「deploy」キーが導入されている。

機密情報をコンテナに安全に受け渡す「docker secret」

Docker 1.13では、swarmモードでのみ利用できる機能として「Docker Secrets Management」という機能が導入された。

Dockerを使ってサービスを立ち上げる場合、パスワードや秘密鍵、証明書といったセキュリティに関わる情報はコンテナ内には格納せず、コンテナの起動時に外部から投入することが推奨される。単独のマシン上でコンテナを実行するのであれば、たとえばローカルのファイルをコンテナ内にマウントしたり、コンテナ起動時のオプション経由で機密情報を受け渡すことは容易だが、複数のマシンを使ったクラスタ環境ではこういった処理を行うために多少の工夫が必要となっていた。

Docker Secrets Managementでは、「docker secret」コマンドで機密情報の登録や管理などを行う仕組みになっている(ドキュメント)。たとえば「docker secret create <名称> <ファイル>」コマンドでは、指定したファイルの内容を指定した名称でシステムに登録できる。

登録された機密情報は、「docker service create」コマンドによるswarmモードでのサービスの起動時に明示的に使用する機密情報を「–secret=<名称>」オプションで指定することで、そのコンテナの「run/secrets/」ディレクトリ内にマウントされ利用可能になる。

設定ファイルなどを共有するための「docker config」

Docker 17.06では、設定ファイルをコンテナ内プロセスに渡すための機能も導入された。これらはDocker Secrets Managementと同様swarmモードでのみ利用可能で、あらかじめ登録しておいたファイルをコンテナ内の任意の場所にマウントできるというものになっている(ドキュメント)。

この機能は、「docker config」コマンド経由で操作が可能だ(ドキュメント)。まず「docker config create <名称> <ファイル>」コマンドで利用したいファイルを登録し、「docker service create」コマンドによるコンテナ起動時に「–config src=<名称>,target=<マウントパス>」オプションを追加することで、コンテナ内で指定した設定ファイルが指定したパスにマウントされる。

Dockerの実験的な機能

最後に、「実験的」(experimental)機能についても紹介しておこう。

Dockerでは、まずは実験的機能として新規機能を実装するケースがある。以前は実験的機能を利用するためにはDockerのビルド時に設定を行う必要があったが、Docker 1.13以降ではDockerが配布するバイナリにも実験的機能が組み込まれるようになり、Dockerデーモンの起動時に「–experimental」オプションを追加することでバイナリを独自ビルドすることなしに実験的な機能を利用できるようになった。

実験的機能が有効になっているかどうかは、「docker version」コマンドを実行で確認できる。「Experimental」が「true」となっていれば実験的機能が有効になっている。

# docker version
Client:
 Version:      17.06.2-ce
 API version:  1.30
 Go version:   go1.8.3
 Git commit:   cec0b72
 Built:        Tue Sep  5 19:59:06 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.06.2-ce
 API version:  1.30 (minimum version 1.12)
 Go version:   go1.8.3
 Git commit:   cec0b72
 Built:        Tue Sep  5 20:00:25 2017
 OS/Arch:      linux/amd64
 Experimental: true

systemdでDockerデーモンを起動している場合、実験的機能を有効にするには次のような手順を踏めばよい。まず次のようにsystemdの設定ファイル「/lib/systemd/system/docker.service」を/etc/systemd/systemディレクトリ以下にコピーする。

# cp -i /lib/systemd/system/docker.service /etc/systemd/system

続いて、コピーした設定ファイル中の「ExecStart」行に「–experimental」オプションを追加する。

  
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd --experimental
ExecReload=/bin/kill -s HUP $MAINPID
  

最後に「systemctl daemon-reload」コマンドを実行してsystemd設定ファイルの再読込を行い、続いてdockerデーモンをリスタートすればDockerで実験的機能が利用可能になる。

# systemctl daemon-reload
$ systemstl restart docker

チェックポイント機能の導入

現在Dockerではいくつか実験的機能が導入されているが、最近導入された大きな実験的機能として「チェックポイント」機能がある。これは、稼動中コンテナの状態を一時的に記録する「チェックポイント」を作成・管理する機能だ。VirtualBoxやVMwareなどの仮想化ソフトウェアは、稼動中の仮想マシンの状態をストレージに保存して仮想マシンを一時停止させたり、任意のタイミングで再開する機能があるが、Dockerのチェックポイントもこれと同様の機能となる。

チェックポイントの作成は、「docker checkpoint create」コマンドで行える(ドキュメント)。作成されたチェックポイントの一覧は「docker checkpoint ls」コマンド、チェックポイントの削除は「docker checkpoint rm」コマンドで行える。

また、チェックポイントからのコンテナの復元は「docker start」コマンドを「–checkpoint」オプション付きで実行することで行える。

この機能はDocker 1.13で実験的機能(experimental)という位置付けで導入されており、Docker 17.06でもまだ実験的機能のままだ。そのため、デフォルトの設定では利用できないので注意したい。

「Moby」ベースや「Docker CE」になっても方向性に大きな変更はなし

さて、本記事では最近のDockerの状況や新機能について紹介してきた。商用版である「Docker EE」の登場や、コア部分の「Moby」プロジェクトへの移行という大きなトピックはあったものの、Docker自体の機能強化については順調に進んでおり、無償でのDockerの利用についても現時点では特に制限されることはない状況となっている。ひとまず、しばらくは安心してDockerを利用できる状況と言えるだろう。