第7回 Dockerに触れ、マルチOSを体験してみよう(後編)古賀政純の「攻めのITのためのDocker塾」(2/3 ページ)

» 2015年09月02日 08時00分 公開

コンテナにログインしなくても、ホストOSからDockerコンテナ上のコマンドを実行できる

 Dockerコンテナ環境では、ホストOSから直接Dockerコンテナ上のコマンドを確認できます。例えば、先ほどのWebサーバ入りのDockerコンテナ「c0001」のIPアドレスを知るには、Dockerコンテナのコマンドプロンプトでipコマンドを入力する以外にホストOSからも実行できます。

 これを実現するには「docker exec」に稼働中のコンテナ名を指定し、コンテナで実行したいコマンドを付与します。以下に稼働中のDockerコンテナ「c0001」で、ip aコマンドを実行した例を示します。

# docker exec -i -t c0001 ip a |grep inet
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
    inet 172.17.0.1/16 scope global eth0
    inet6 fe80::42:acff:fe11:1/64 scope link

Webサーバ入りDockerイメージは、みんなで再利用

 WebサーバとWebコンテンツ“test.html”入りのDockerコンテナ「c0001」は、Dockerイメージとして保存できます。Dockerイメージとして保管しておけば、他の開発者や運用担当者がDockerイメージを再利用し、カスタマイズすることができます。

photo Webサーバ入りのDockerイメージの保管

 Dockerコンテナ「c0001」を使って、新しいDockerイメージ(今回は「c66apache0001」という名前のDockerイメージにします)を作ってみます。既存のDockerコンテナからDockerイメージを作成するには、ホストOS上で「docker commit」コマンドにイメージ化したいコンテナ名(c0001)とDockerイメージ名を指定します。

# docker commit c0001 c66apache0001

 これで、Dockerイメージ「c66apache0001」が作成されました。Dockerイメージを確認してみます。

# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
c66apache0001       latest              594aac610bd8        2 minutes ago       443.3 MB

 では、このDockerイメージ「c66apache0001」から、Dockerコンテナ「c0003」を起動してみましょう。c66apache0001は、Apache WebサーバもWebコンテンツ“test.html”も入っているイメージです。Dockerコンテナ「c0003」でも、すぐにWebサーバとして稼働し、クライアントにWebコンテンツを提供できるはずです。

# docker run -i -t --name c0003 --hostname c0003 c66apache0001 /bin/bash
[root@c0003 /]# ip a |grep inet
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
    inet 172.17.0.7/16 scope global eth0
    inet6 fe80::42:acff:fe11:5/64 scope link
[root@c0003 /]# service httpd restart

 起動したDockerコンテナ「c0003」のIPアドレスは、172.17.0.7です。では、クライアントとなるホストOSから、Dockerコンテナc0003が提供するWebコンテンツ“test.html”が見えるかを確認してみます。

# curl http://172.17.0.7/test.html
Hello Docker.


 ここで、少し疑問に感じた方はいるかもしれません。

 コンテナ「c0003」を起動後、コンテナ上でserviceコマンドを実行することでWebサービス(httpdデーモン)を再起動しています。では、Dockerコンテナ「c0003」を起動後、Webサービスのhttpdデーモンも自動的に起動できないのでしょうか。

 コンテナでない環境の普通のOS環境では、通常、CentOS 6.xならば「chkconfig」コマンドを使って、OS起動時にデーモンなどのサービスを自動的に起動させる設定が行えます。CentOS 7.xならば、「systemctl」コマンドでサービスの自動起動が可能です。しかし、Dockerコンテナ環境でchkconfigやsystemctlコマンドを使用してサービス(デーモン)を自動的に起動するには、少し工夫が必要になります。

 CentOS 6.xにおけるchkconfigは、OS起動時のinitスクリプトと呼ばれるスクリプト群の実行が深く関係しています。しかしDocker環境では、「docker run」実行時に/bin/bashを指定して実行した場合、DockerコンテナのOS起動時のinitスクリプトの実行をスキップします。このため、Dockerコンテナ内であらかじめchkconfigコマンドによるサービスの自動起動を設定し、Dockerイメージを作成しても、次回のコンテナ起動時に/sbin/initを指定しなければサービスの自動起動が行われません。

 CentOS 6.xにおけるchkconfigや、CentOS 7.xにおけるsystemctlを使ってOS起動時のサービスの自動起動をDockerコンテナ上で実現するためには、Dockerコンテナの起動の際に、以下のように/sbin/initを指定する必要があります。

# docker run -i -t -d --name c0003 --hostname host0003 c66apache0001 /sbin/init

 このほかに、Docker起動時に/sbin/initを指定せず、サービスを自動的に起動するスクリプトを組み込む場合もあります。Dockerの初心者にとって、このサービスの起動方法は少し複雑に思えるかもしれませんが、Dockerコンテナにおけるサービスの自動起動は通常のOSにおける起動プロセスとは異なる場合があることを正しく理解しておく必要があります。ここでは、厳密な仕組みは省きますが、まずは最低限、以下のポイントを理解してください。

Dockerコンテナ起動時に自動的にサービスを起動させるため際のポイント

  • Dockerコンテナ起動時に、/sbin/initを指定しない場合、OSが持つinitスクリプトなどによるサービスの自動起動の処理は行われない
  • Dockerコンテナ上でchkconfigやsystemctlを使ったサービスの自動起動を行うには、コンテナ起動時に/sbin/initを指定する
  • /sbin/initを使用せずに、コンテナ起動時にサービスを自動起動させるには、サービスを起動させるスクリプトなどを組み込む工夫が必要である

 ちなみに、起動させたいDockerコンテナがCentOS 7.xのようなsystemdが採用されているLinux OSで、systemdによるサービスの起動をDockerコンテナで実現するには、docker runによるコンテナ起動時に、/sbin/initの指定のほかに管理者権限モードのオプション(--privileged、または、--cap-add=SYS_ADMIN)が必要になります。しかし、管理者権限モードで実行されたDockerコンテナは、ホストOSのハードウェア資源(デバイスなど)へのアクセスが無制限に許可されるため、セキュリティ面において注意すべきです。Dockerの本番環境では、Dockerコンテナに対して、必要最低限の権限のみを付与するような運用をできるだけ心掛けて下さい。

Copyright © ITmedia, Inc. All Rights Reserved.

注目のテーマ