第7章 Docker フォーマットのコンテナーイメージの使用方法
7.1. 概要
昨今 Docker はアプリケーションのコンテナー化における重要なプロジェクトの 1 つとなっています。本書では、Red Hat Enterprise Linux 7 および RHEL Atomic で Docker を使用するための実践的なアプローチを紹介します。ここでは、Docker レジストリーのセットアップ、Docker イメージの取得と使用、および Docker コンテナーの使用について説明します。
7.2. 背景
Docker プロジェクトは、軽量コンテナーでアプリケーションをパッケージ化する方法を提供します。アプリケーションを Docker コンテナーで実行すると、以下のような利点があります。
- 仮想マシンよりもサイズが小さい: Docker イメージにはアプリケーションの実行に必要なコンテナーのみが含まれるため、(オペレーティングシステム全体を含む) 仮想マシンの場合よりも Docker を使用して保存および共有を実行する方がはるかに効率的です。
- パフォーマンスの向上: 同様にコンテナーの場合は全く別個のオペレーティングシステムを実行する必要がないため、通常は新規の仮想マシン全体のオーバーヘッドを伴うアプリケーションよりも高速に実行されます。
- 安全性: Docker コンテナーには通常、独自のネットワークインターフェース、ファイルシステムおよびメモリーがあるため、そのコンテナーで実行されるアプリケーションはホストコンピューターの他のアクティビティーから分離し、セキュリティーを保護することができます。
- 柔軟性: コンテナー内のアプリケーションに組み込まれているアプリケーションのランタイム要件により、Docker コンテナーは複数の環境で実行できます。
現時点で、Docker コンテナーは Red Hat Enterprise Linux 7 (RHEL 7) および Red Hat Enterprise Linux Atomic (RHEL 7 ベース) システムで実行できます。RHEL Atomic に馴染みがない場合は、『Red Hat Enterprise Linux Atomic Host スタートガイド』またはアップストリームの Project Atomic サイトを参照してください。Project Atomic では、とくに OpenStack、VirtualBox、Linux KVM その他のいくつかの異なる環境で Docker コンテナーを実行することを目的として作成された RPM ベースの Linux ディストリビューション (RHEL、Fedora および CentOS) の小型版を生成しています。
本書は、RHEL 7 および RHEL Atomic の初期リリースの Docker の使用を開始するのに役立ちます。Docker を試用する実践的な方法のほかに、以下を実行する方法について説明します。
- Red Hat カスタマーポータルから RHEL ベースの Docker イメージへのアクセス
- RHEL で有効なソフトウェアのコンテナーへの組み込み
本書の今後のリリースは、以下に役立つ情報が提供されます。
- RHEL のセキュリティー機能によるコンテナーの安全なデプロイメント
- Docker イメージの構築方法を標準化するツールの検索
- セキュリティープロトコルに準拠する方法でコンテナーを構築するためのヒント
Docker の仕組みの詳細をお知りになりたい場合は、以下を参照してください。
- リリースノート: RHEL 7 の Docker 機能の概要については、RHEL 7 リリースノートの Docker フォーマットの Linux コンテナー のセクションを参照してください。
- Docker プロジェクトサイト: Docker サイト の What is Docker? ページおよび Getting Started ページから Docker の詳細を学ぶことができます。さらに、Docker ドキュメンテーション ページを参照することもできます。
- Docker README: docker パッケージのインストール後は、/usr/share/doc/docker-1* ディレクトリーの README.md ファイルを参照してください。
- Docker の man ページ: Docker をインストールした状態で
man docker
と入力すると、docker コマンドについて確認できます。次に各 Docker オプションについてそれぞれの man ページを参照します (たとえばman docker-image
と入力し、docker image
オプションについて確認します)。
注意: 現時点で、docker コマンドを RHEL 7 および RHEL Atomic で実行するには root 権限が必要です。この手順ではコマンドプロンプトにハッシュ記号 (#) がある場合は root 権限が必要です。root ユーザーアカウントに直接ログインすることを選択しない場合は、sudo を設定することができます。
7.3. RHEL 7 における Docker の取得
Docker を開発できる環境を取得するには、コンテナーホストだけではなく開発システムとして機能するように Red Hat Enterprise Linux 7 システムをインストールすることができます。Docker パッケージ自体は RHEL Extras リポジトリーに保存されます (Red Hat Enterprise Linux Extras チャンネルのサポートポリシーおよびライフサイクル情報については Red Hat Enterprise Linux Extras Life Cycle の記事を参照してください)。
RHEL 7 サブスクリプションモデルを使用して Docker イメージまたはコンテナーを作成する必要がある場合は、それらを構築するために使用するホストコンピューターを適切に登録し、これにエンタイトルメントを付与する必要があります。コンテナー内で yum install を使用してパッケージを追加する場合、コンテナーは RHEL 7 ホストから利用できるエンタイトルメントに自動的にアクセスできるため、ホストで有効にされたすべてのリポジトリーから RPM パッケージを取得できます。
- RHEL Server エディションのインストール: 開始する準備ができたら、Red Hat Enterprise Linux 7 インストールガイド で説明されているように Red Hat Enterprise Linux システム (Server エディション) をインストールして開始することができます。
RHEL の登録: RHEL 7 がインストールされたら、サブスクリプション管理ツールを使用してシステムを登録し、Docker パッケージをインストールします。さらに、必要なソフトウェアリポジトリーを有効にします(pool_id を RHEL 7 サブスクリプションのプール ID に置き換えます)。以下のようになります。
注意: 本書では、docker および docker-registry サービスが同じホストシステムで実行されていることを示しています。実際の環境ではよくあることですが、Docker レジストリーが複数のクライアントで使用されている場合は、docker-registry をインストールするシステムとこれを実行するシステムを別にすることができます。この場合、docker-registry パッケージを docker を実行するシステムにインストールする必要はありません。
# subscription-manager register --username=rhnuser --password=rhnpasswd # subscription-manager list --available Find pool ID for RHEL subscription # subscription-manager attach --pool=pool_id # subscription-manager repos --enable=rhel-7-server-extras-rpms # subscription-manager repos --enable=rhel-7-server-optional-rpms
注意: Red Hat Satellite 5 の docker パッケージを取得するのに必要なチャンネル名については、Satellite 5 repo to install Docker on Red Hat Enterprise Linux 7 を参照してください。
docker および docker-registry のインストール: docker パッケージをインストールし、オプションで docker-registry をインストールします。(device-mapper-libs および device-mapper-をインストールしていない場合はここでインストールします。)
# yum install docker docker-registry # yum install device-mapper-libs device-mapper-event-libs
docker の起動:
# systemctl start docker.service
docker の有効化:
# systemctl enable docker.service
docker ステータスの確認:
# systemctl status docker.service docker.service - Docker Application Container Engine Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled) Active: active (running) since Thu 2014-10-23 11:32:11 EDT; 14s ago Docs: http://docs.docker.io Main PID: 2068 (docker) CGroup: /system.slice/docker.service └─2068 /usr/bin/docker -d --selinux-enabled -H fd:// ...
docker サービスを実行すると、一部の Docker イメージを取得し、docker コマンドを使用して RHEL 7 で Docker イメージを使用できるようになります。
7.4. RHEL Atomic における Docker の取得
RHEL Atomic は、コンテナーを実行するために特別に設計された軽量の Linux オペレーティングシステムのディストリビューションです。これには、Docker サービスと Kubernetes および Etcd サービスを含む、Docker コンテナーのオーケストレーションと管理を行うために使用できるいくつかのサービスが含まれます。
RHEL Atomic はフル機能の Linux システムではなくアプライアンスであるため、(システムに追加するコンテナー以外の) RPM パッケージまたはその他のソフトウェアをインストールするために作成されている訳ではありません。
RHEL Atomic には既存のパッケージをアップデートするメカニズムがありますが、これはユーザーが新規パッケージを追加するためのものではありません。したがって、(開発およびデバッグツールを追加するには) 標準の RHEL 7 サーバーシステムを使用してアプリケーションを開発することを検討してください。標準の RHEL 7 サーバーシステムを使用すれば、RHEL Atomic を使用してコンテナーをさまざまな仮想化環境とクラウド環境にデプロイできます。
つまり RHEL Atomic システムをインストールすれば、コンテナーを実行し、構築し、停止し、開始し、本書で紹介している例に従ってコンテナーを使用したりすることができます。そのためには、以下の手順を使用して RHEL Atomic を取得し、インストールします。
RHEL Atomic の取得: RHEL Atomic は Red Hat カスタマーポータルから使用できます。RHEL Atomic をライブイメージ (.qcow2 形式) として実行するか、またはインストールメディア (.iso 形式) から RHEL Atomic をインストールするオプションがあります。以下のサイトからこれらの形式 (およびその他の形式) で RHEL Atomic を取得できます。
次に『Red Hat Enterprise Linux Atomic Host スタートガイド』に従って Atomic をセットアップし、いくつかの異なる仮想環境で実行します。
RHEL Atomic の登録: RHEL 7 Atomic がインストールされたら、サブスクリプション管理ツールを使用してシステムを登録します (これにより、atomic upgrade を実行して Atomic ソフトウェアをアップグレードできますが、yum コマンドを使用して追加パッケージをインストールすることはできません)。以下は例になります。
# subscription-manager register --username=rhnuser --password=rhnpasswd --auto-attach
重要: 本書で説明しているように、docker コマンドでコンテナーを実行するのに、RHEL Atomic システムを登録したり、サブスクリプションを割り当てたりする必要はありません。ただし、コンテナーで yum install コマンドを実行する必要がある場合は、コンテナーは RHEL Atomic ホストから有効なサブスクリプション情報を取得する必要があります。この情報がないと失敗します。ホストが使用している RHEL バージョンでデフォルトで有効にされないリポジトリーを有効にする必要がある場合は、/etc/yum.repos.d/redhat.repo ファイルを編集する必要があります。これはコンテナー内で手動で実行でき、使用するレポジトリーに enabled=1 を設定します。さらに、yum repo ファイルを管理するためにコマンドラインツールの yum-config-manager を使用することもできます。以下のコマンドを使用してリポジトリーを有効にできます。
# yum-config-manager --enable REPOSITORY You can also use **yum-config-manager** to display Yum global options, add repositories and others. **yum-config-manager** is documented in detail in the Red Hat Enterprise Linux 7 System Administrator's Guide. Since **redhat.repo** is a big file and editing it manually can be error prone, it is recommended to use **yum-config-manager**.
Docker の使用の開始: RHEL Atomic には docker パッケージがすでにインストールされ、有効にされています。そのため、ログインして Atomic システムのサブスクライブを行っている場合は、docker と関連ソフトウェアのステータスは以下のようになります。
- docker コマンドを実行して、Docker イメージとコンテナーをすぐに使用できます。
- docker-registry パッケージはインストールされていません。Atomic システムとプライベートのレジストリー間でイメージを移動できるようにするには、docker-registry パッケージを RHEL 7 システムにインストールし (以下で説明)、独自のコンテナーイメージを保存するためにレジストリーにアクセスします。
- Docker コンテナーのオーケストレーションに使用される kubernetes パッケージは RHEL Atomic にインストールされますが、デフォルトでは有効にされません。RHEL Atomic のコンテナーを Kubernetes でオーケストレーションできるようにするには、いくつかの Kubernetes 関連のサービスを有効にし、起動する必要があります。
7.5. Docker レジストリーの使用
Docker レジストリーは、他のユーザーと共有できるイメージとして保存される docker コンテナーを保存し、共有するための場所を提供します。docker パッケージを RHEL および RHEL Atomic で利用可能な状態にすると、イメージを Red Hat カスタマーポータルから取得し、各自のプライベートレジストリーからイメージの移動を実行できます。Red Hat Container イメージの検索ページ を検索して、Red Hat カスタマーポータルから取得できるイメージを確認できます (docker pull を使用)。
このセクションでは、ローカルレジストリーの起動方法、Docker イメージをローカルレジストリーにロードする方法、およびそれらのイメージを使用して docker コンテナーを起動する方法について説明します。
7.5.1. Docker のプライベートレジストリーの作成
Docker のプライベートレジストリーを作成する 1 つの方法は、docker-registry サービスを使用する方法です。本書の始めの部分で説明されているように docker-registry パッケージを RHEL 7 (Atomic では利用不可) にインストールしている場合、以下のようにサービスを有効にし、起動することができます。
docker-registry サービスの有効化および起動: 以下を入力すると、docker-registry サービスを有効にし、起動し、ステータスを確認することができます。
# systemctl enable docker-registry # systemctl start docker-registry # systemctl status docker-registry docker-registry.service - Registry server for Docker Loaded: loaded (/usr/lib/systemd/system/docker-registry.service; enabled) Active: active (running) since Thu 2014-10-23 13:40:26 EDT; 4s ago Main PID: 21031 (gunicorn) CGroup: /system.slice/docker-registry.service ├─21031 /usr/bin/python /usr/bin/gunicorn --access-logfile - --debug ... ...
レジストリー、ファイアウォールの問題: docker-registry サービスは TCP ポート 5000 で listen するため、そのポートへのアクセスは、ローカルシステム外のクライアントがレジストリーを使用できるように開いた状態にしておく必要があります。これは、docker-registry や docker を同じシステムで実行しているかどうかとは関係がありません。以下を実行して TCP ポート 5000 を開くことができます。
# firewall-cmd --zone=public --add-port=5000/tcp # firewall-cmd --zone=public --add-port=5000/tcp --permanent # firewall-cmd --zone=public --list-ports 5000/tcp
または、iptables ファイアウォールルールを直接使用しているファイアウォールを有効にしている場合は、システムを起動するたびに以下のコマンドを実行する方法があります。
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 5000 -j ACCEPT
7.5.2. リモート Docker レジストリーからのイメージの取得
リモートレジストリー (Red Hat 独自の Docker レジストリー) から Docker イメージを取得し、それらをローカルシステムに追加するには、docker pull コマンドを使用します。
# docker pull <registry>[:<port>]/[<namespace>/]<name>:<tag>
<registry> は、TCP <port> に docker-registry サービスを提供するホストです (デフォルト: 5000)。さらに、<namespace> および <name> は、そのレジストリーで <namespace> によって制御される特定のイメージを特定します。また、一部のレジストリーも生の <name> をサポートします。これらの場合、<namespace> はオプションです。ただし、名前空間が組み込まれていると、<namespace> が提供する階層の追加のレベルは、同じ <name> の複数のイメージを区別するのに役立ちます。以下は例になります。
名前空間 | 例 (<namespace>/<name>) |
---|---|
組織 |
|
ログイン (ユーザー名) |
|
ロール |
|
2014 年 11 月の時点で、Red Hat がサポートする唯一の Docker レジストリーは registry.access.redhat.com にあります。tarball として保存されている Docker イメージにアクセスできる場合、そのイメージをローカルファイルシステムから Docker レジストリーにロードできます。
docker pull: pull オプションを使用すると、リモートレジストリーからイメージを取得できます。rhel ベースイメージを Red Hat レジストリーから取得するには、docker pull registry.access.redhat.com/rhel と入力します。イメージが Red Hat レジストリーのものであることを確認するには、レジストリーのホスト名、スラッシュおよびイメージ名を入力します。以下のコマンドは、rhel イメージを Red Hat レジストリーから取得する例を示しています。
# docker pull registry.access.redhat.com/rhel
イメージはリポジトリー名とタグで特定されます。リポジトリー名 rhel は、レジストリー名を付けずに docker pull コマンドに渡されると、不明確となり、信用できないリポジトリーのイメージの取得を招く可能性があります。したがって、latest などのタグを追加して、名前を rhel:latest にします。
上記の docker pull コマンドで作成されたイメージを表示するには、docker images と入力します。
# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE registry.access.redhat.com/rhel 0-21 e1f5733f050b 4 months ago 140.2 MB registry.access.redhat.com/rhel 0 bef54b8f8a2f 4 months ago 139.6 MB registry.access.redhat.com/rhel 0-23 bef54b8f8a2f 4 months ago 139.6 MB registry.access.redhat.com/rhel latest bef54b8f8a2f 4 months ago 139.6 MB
docker load: コンテナーイメージをローカルシステムに tarball として保存する場合、そのイメージの tarball をロードして、ローカルシステムで docker コマンドで実行できます。以下の手順に従ってください。
現在のディレクトリーにある Docker イメージの tarball を使用して、以下のように tarball をローカルシステムにロードします。
# docker load -i rhel-server-docker-7.0-23.x86_64.tar.gz
ローカルホストで実行されているレジストリーに同じイメージを送る場合は、docker-registry サービスのホスト名 (または "localhost") とポート番号 (TCP ポート 5000) のタグをイメージに付けます。docker push はこのタグ情報を使用して、イメージを適切なレジストリーに送ります。
# docker tag bef54b8f8a2f localhost:5000/myrhel7 docker push localhost:5000/myrhel7 The push refers to a repository [localhost:5000/myrhel7] (len: 1) Sending image list Pushing repository localhost:5000/myrhel7 (1 tags) bef54b8f8a2f: Image successfully pushed Pushing tag for rev [bef54b8f8a2f] on {http://localhost:5000/v1/repositories/myrhel7/tags/latest} ...
7.5.3. Docker イメージの調査
イメージをローカルレジストリーに追加し、ロードしている場合、docker コマンドの docker images を使用してそれらのイメージを表示できます。以下は、ローカルシステムにあるイメージを一覧表示する方法を示しています。
# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE redhat/rhel latest e1f5733f050b 4 weeks ago 140.2 MB rhel latest e1f5733f050b 4 weeks ago 140.2 MB redhat/rhel7 0 e1f5733f050b 4 weeks ago 140.2 MB redhat/rhel7 0-21 e1f5733f050b 4 weeks ago 140.2 MB redhat/rhel7 latest e1f5733f050b 4 weeks ago 140.2 MB rhel7 0 e1f5733f050b 4 weeks ago 140.2 MB rhel7 0-21 e1f5733f050b 4 weeks ago 140.2 MB rhel7 latest e1f5733f050b 4 weeks ago 140.2 MB
注意: イメージまたはリポジトリーをアップストリームの Docker.io レジストリー (docker push) に追加するデフォルトのオプションは、docker コマンドの Red Hat バージョンでは無効になっています。イメージを特定のレジストリーに追加するには、レジストリー、そのポート番号およびタグを指定して、追加するイメージを指定します。
7.5.4. Docker 環境の調査
ここまでで docker および docker-registry サービスを実行でき、いくつかのコンテナーが利用できる状態になったので、Docker 環境とコンテナーの構成内容を確認することができます。docker を version および info オプションと共に実行すると、Docker 環境の状態を確認できます。
docker version: version オプションを使用すると、インストールされている Docker コンポーネントのバージョンを表示できます。なお、 docker パッケージは新しいバージョンを利用できます (RHEL 7 では yum update docker でアップデートできます)。
# docker version Shows components/versions in use. Note that docker needs updating here. Client version: 1.2.0 Client API version: 1.14 Go version (client): go1.3.1 Git commit (client): 2a2f26c/1.2.0 OS/Arch (client): linux/amd64 Server version: 1.2.0 Server API version: 1.14 Go version (server): go1.3.1 Git commit (server): 2a2f26c/1.2.0 Last stable version: 1.3.0, please update docker
docker info: info オプションを使用すると、ローカルコンテナーやイメージの数などのコンポーネントの場所や、Docker ストレージ領域のサイズや場所の情報を確認できます。
# docker info Containers: 3 Images: 5 Storage Driver: devicemapper Pool Name: docker-253:1-16826017-pool Pool Blocksize: 64 Kb Data file: /var/lib/docker/devicemapper/devicemapper/data Metadata file: /var/lib/docker/devicemapper/devicemapper/metadata Data Space Used: 1042.4 Mb Data Space Total: 102400.0 Mb Metadata Space Used: 1.3 Mb Metadata Space Total: 2048.0 Mb Execution Driver: native-0.2 Kernel Version: 3.10.0-123.8.1.el7.x86_64 Operating System: Red Hat Atomic Host 7.0
7.5.5. Docker コンテナーの使用
(実行しているかどうかに関わらず) システムに作成された Docker イメージは、複数の方法で管理できます。docker run コマンドを実行すると、コンテナーで実行するコマンドを指定できます。コンテナーを起動したら、停止、開始、再起動を行うことができます。不要なコンテナーは削除できます。
Docker コンテナーの実行
docker run コマンドを実行すると、基本的に Docker イメージからコンテナーを新たに作成できます。コンテナーはイメージのコンテンツと、docker run コマンドラインで渡す追加のオプションに基づく複数の機能で構成されます。
docker run コマンドラインで渡すコマンドは、コンテナーの内部をその実行環境として表示します。そのため、デフォルトではホストシステムについてはほとんど確認できません。たとえば、デフォルトでは実行中のアプリケーションで以下を確認できます。
- Docker イメージで提供されるファイルシステム。
- コンテナー内の新規のプロセステーブル (ホストのプロセスは表示されない)。
- 新規のネットワークインターフェース (デフォルトでは、別の docker ネットワークインターフェースが DHCP 経由で各コンテナーにプライベートの IP アドレスを提供する)。
コンテナーで利用できるホストからディレクトリーを作成し、コンテナーからホストにネットワークポートをマップし、コンテナーが使用できるメモリーのサイズを制限し、コンテナーで利用できる CPU 共有を拡大する必要などがある場合、これらを docker run コマンドラインで実行することができます。以下は、異なる機能を有効にする docker コマンドラインのいくつかの例になります。
例 #1 (quick コマンドの実行): この docker コマンドは ip addr show eth0 コマンドを実行して、RHEL イメージから生成されるコンテナー内の eth0 ネットワークのアドレス情報を表示します。これは必要最低限のコンテナーであるため、このデモの RHEL 7 ホストシステムから /usr/sbin ディレクトリーをマウントします (マウントは -v オプションで実行します)。これには実行に必要な ip コマンドが含まれるためです。コンテナーがコマンドを実行した後に、IP アドレス (172.17.0.2/16) および eth0 についての他の情報が表示され、コンテナーは停止し、削除されます (--rm)。
# docker run -v /usr/sbin:/usr/sbin \ --rm rhel /usr/sbin/ip addr show eth0 20: eth0: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 4e:90:00:27:a2:5d brd ff:ff:ff:ff:ff:ff inet 172.17.0.10/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::4c90:ff:fe27:a25d/64 scope link tentative valid_lft forever preferred_lft forever
このコンテナーを保存して再度使用する場合は、これに名前を割り当て、その名前を使って後で起動することができます。たとえば、このコンテナーに myipaddr という名前を付けます。
# docker run -v /usr/sbin:/usr/sbin \ --name=myipaddr rhel /usr/sbin/ip addr show eth0 20: eth0: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 4e:90:00:27:a2:5d brd ff:ff:ff:ff:ff:ff inet 172.17.0.10/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::4c90:ff:fe27:a25d/64 scope link tentative valid_lft forever preferred_lft forever # docker start -i myipaddr 22: eth0: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 4e:90:00:27:a2:5d brd ff:ff:ff:ff:ff:ff inet 172.17.0.10/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::4c90:ff:fe27:a25d/64 scope link tentative valid_lft forever preferred_lft forever
例 #2 (コンテナー内でシェルを実行): コンテナーを使用して bash シェルを起動すると、コンテナー内を確認でき、コンテンツを変更することができます。ここでは、コンテナーの名前を mybash に設定しています。-i でインタラクティブなセッションを作成し、-t でターミナルセッションを開きます。-i を使用しないと、シェルは開いた後に終了します。-t を使用しないと、シェルは開いたままになりますが、シェルには何も入力できなくなります。
コマンドを実行すると、シェルプロンプトが表示され、コンテナー内からコマンドを実行できるようになります。
# docker run --name=mybash -it rhel /bin/bash [root@49830c4f9cc4/]#
ベースの RHEL イメージ内で利用できるアプリケーションはほとんどありませんが、yum コマンドを使用してソフトウェアを追加できます。コンテナー内のシェルを開いたら、以下のコマンドを実行します。
[root@49830c4f9cc4/]# cat /etc/redhat-release Red Hat Enterprise Linux Server release 7.1 (Maipo) [root@49830c4f9cc4/]# ps bash: ps: command not found [root@49830c4f9cc4/]# yum install -y procps [root@49830c4f9cc4/]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 15:36 ? 00:00:00 /bin/bash root 46 1 0 15:43 ? 00:00:00 ps -ef [root@49830c4f9cc4/]# exit
コンテナーが RHEL 7.1 コンテナーになっていることに注意してください。ps コマンドは RHEL のベースイメージには含まれていません。ただし、上記のように yum を使用してインストールできます。コンテナーを終了するには、exit と入力します。
コンテナーを終了すると実行しなくなりますが、コンテナーは新規のソフトウェアパッケージがインストールされた状態で存在したままになります。docker ps -a を使用してコンテナーを一覧表示します。
# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 49830c4f9cc4 rhel:latest "/bin/bash" 2 minutes ago Exited (0) 25 minutes ago mybash ...
docker start を -ai オプションと共に使用してコンテナーを再起動できます。以下は例になります。
# docker start -ai mybash [root@a0aee493a605/]#
例 #3 (ログファイルのバインドマウント): コンテナー内のログメッセージをホストシステムで利用できるようにする 1 つの方法は、コンテナー内でホストの /dev/log デバイスをバインドマウントする方法です。この例では、ログメッセージを生成する log_test という名前の RHEL コンテナーでアプリケーションを実行 (この場合は logger コマンドを使用) し、ホストからコンテナーにマウントした /dev/log デバイスにメッセージを移動する方法について示しています。--rm オプションを使用すると、コンテナーが実行後に削除されます。
# docker run --name="log_test" -v /dev/log:/dev/log --rm rhel logger "Testing logging to the host" # journalctl -b | grep Testing Apr 22 16:00:37 node1.example.com logger[102729]: Testing logging to the host
Docker コンテナー外からの調査
1 つ以上の Docker コンテナーがホストで実行されているとします。ホストシステムからコンテナーを使用するには、シェルを開いて以下のコマンドをいくつかを実行できます。
docker ps: ps オプションは、現在実行中のすべてのコンテナーを表示します。
# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0d8b2ded3af0 rhel:latest "/bin/bash" 10 minutes ago Up 3 minutes mybash
実行されていないものの、(--rm オプションを使用して) 削除されていないコンテナーがある場合 、コンテナーは保存されているために再起動できます。docker ps -a コマンドは、実行中または停止しているすべてのコンテナーを表示します。
# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 92b7ed0c039b rhel:latest /bin/bash 2 days ago Exited (0) 2 days ago agitated_hopper eaa96236afa6 rhel:latest /bin/bash 2 days ago Exited (0) 2 days ago prickly_newton
システムに存在するコンテナーの起動、停止、および削除についての詳細は、「Docker コンテナーの使用」セクションを参照してください。
docker inspect: 既存のコンテナーのメタデータを調べるには、docker inspect コマンドを使用します。コンテナーのすべてのメタデータを表示することも、選択した項目のみを表示することもできます。たとえば、選択したコンテナーのすべてのメタデータを表示するには、以下を入力します。
# docker inspect mybash [{ "Args": [], ... "Hostname": "a0aee493a605", "Image": "rhel", "Labels": { "Architecture": "x86_64", "Build_Host": "rcm-img04.build.eng.bos.redhat.com", "Name": "rhel-server-docker", "Release": "4", "Vendor": "Red Hat, Inc.", "Version": "7.1" ...
docker inspect --format: このコマンドを使用すると、コンテナーから情報の特定の部分を取得することができます。情報は階層的に保存されます。コンテナーの IP アドレス (NetworkSettings 下の IPAddress) を表示するには、--format オプションとコンテナーの ID を使用します。以下が例になります。
# docker inspect --format='{{.NetworkSettings.IPAddress}}' mybash 172.17.0.2
その他にも、.Path (コンテナーで実行するコマンドを表示する)、.Args (コマンドへの引数)、.Config.ExposedPorts (コンテナーから表示される TCP または UDP ポート)、.State.Pid (コンテナーのプロセス ID を表示する)、.HostConfig.PortBindings (コンテナーからホストへのポートマッピング) などを調べることができます。以下は、.State.Pid および .HostConfig.PortBindings の例になります。
# docker inspect --format='{{.State.Pid}}' mybash 5007 # docker inspect --format='{{.HostConfig.PortBindings}}' mybash map[8000/tcp:[map[HostIp: HostPort:8000]]]
実行中の Docker コンテナー内の調査
実行中の Docker コンテナー内で調査を行うには、docker exec コマンドを使用することができます。docker exec を使用すると、コマンド (/bin/bash など) を実行して、実行中の Docker コンテナープロセスに入ってコンテナーを調べることができます。
コンテナーが目的のアプリケーションを実行している間にコンテナーを調べることができるため、コンテナーを bash シェルで起動するのではなく、docker exec を使用します。目的のタスクを実行中のコンテナーに割り当てると、コンテナーのアクティビティーを中断せずに、コンテナーの実際の機能をより詳細に確認できます。
以下の例では、docker exec を使用して、myrhel_httpd という名前の実行中のコンテナーを調べ、そのコンテナーの内部を調べます。
コンテナーの起動: 「Dockerfile からのイメージの構築」に記載されている myrhel_httpd コンテナーや、調査したいその他の Docker コンテナーを起動します。docker ps と入力し、コンテナーが実行されていることを確認します。
# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1cd6aabf33d9 rhel_httpd:latest "/usr/sbin/httpd -DF 6 minutes ago Up 6 minutes 0.0.0.0:80->80/tcp myrhel_httpd
docker exec でコンテナーに入る: コンテナー ID または名前を使用して bash シェルを開き、実行中のコンテナーにアクセスします。次に、以下のようにコンテナーの属性を調べることができます。
# docker exec -it myrhel_httpd /bin/bash [root@1cd6aabf33d9 /]# cat /etc/redhat-release Red Hat Enterprise Linux Server release 7.1 (Maipo) [root@1cd6aabf33d9 /]# ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 08:41 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND apache 7 1 0 08:41 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND ... root 12 0 0 08:54 ? 00:00:00 /bin/bash root 35 12 0 08:57 ? 00:00:00 ps -ef [root@1cd6aabf33d9 /]# df -h Filesystem Size Used Avail Use% Mounted on /dev/mapper/docker-253:0-540464... 9.8G 414M 8.8G 5% / tmpfs 7.9G 0 7.9G 0% /dev shm 64M 0 64M 0% /dev/shm /dev/mapper/rhel_unused-root 137G 45G 92G 33% /etc/hosts tmpfs 7.9G 8.0K 7.9G 1% /run tmpfs 7.9G 184K 7.9G 1% /run/secrets tmpfs 7.9G 0 7.9G 0% /proc/kcore [root@1cd6aabf33d9 /]# uname -r 3.10.0-229.1.2.el7.x86_64 [root@1cd6aabf33d9 /]# rpm -qa | less redhat-release-server-7.1-1.el7.x86_64 basesystem-10.0-7.el7.noarch nss-softokn-freebl-3.16.2.3-9.el7.x86_64 ... bash-4.2# free -m total used free shared buff/cache available Mem: 16046 6759 641 20 8645 8948 Swap: 8071 2 8069 [root@1cd6aabf33d9 /]# ip addr show eth0 44: eth0: mtu 1500 qdisc pfifo_fast state UP link/ether 92:b1:31:b2:79:69 brd ff:ff:ff:ff:ff:ff inet 172.17.0.14/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::90b1:31ff:feb2:7969/64 scope link valid_lft forever preferred_lft forever [root@1cd6aabf33d9 /]# exit
(コンテナー内で実行中の) bash シェルからこのコマンドを実行すると、以下のことを確認できます。コンテナーは、RHEL Server リリース 7.1 システムを保持しています。プロセステーブル (ps -ef) は、httpd コマンドが (他の 5 つの httpd プロセスの後に続く) プロセス ID 1、/bin/bash が PID 12、および ps -ef が PID 35 であることを示しています。ホストのプロセステーブルで実行しているプロセスはコンテナー内では確認できません。コンテナーのファイルシステムは、9.8G の領域が利用できる root ファイルシステムで、414M を使用しています。
コンテナーでは他のカーネルは実行していません (uname -r はホストシステムのカーネル 3.10.0-229.1.2.el7.x86_64 を示します)。rpm -qa コマンドを使うと、コンテナーに含まれる RPM パッケージが表示されます。つまり、コンテナーには RPM データベースがあります。メモリーを表示 (free -m) すると、ホストで利用できるメモリーが表示されます (ただし、cgroups を使用してコンテナーが実際に使用できるものを制限できます)。コンテナーの IP アドレス (172.17.0.14/16) は、DHCP 経由でホストシステムからコンテナーに割り当てられます。この場合、ホストシステムには、IP アドレスが 172.17.42.1/16 の docker0 という名前のインターフェースがあります。
コンテナーの起動および停止
実行したコンテナーを実行しても、それを削除しない場合 (--rm)、そのコンテナーはローカルシステムに保存され、再度実行できます。実行した後に削除しなかったコンテナーを起動するには、start オプションを使用します。実行中のコンテナーを停止するには、stop オプションを使用します。
コンテナーの起動: docker コンテナーをインタラクティブに実行する必要がない場合は、start オプションとコンテナー ID (または名前) が必要になります。
# docker start myrhel_httpd myrhel_httpd
コンテナーをローカルシェルから起動して使用するには、-a (attach) および -i (interactive) オプションを使用します。bash シェルが起動したら、コンテナー内で必要なコマンドを実行します。exit を実行すると、シェルを kill してコンテナーを停止できます。
# docker start -a -i agitated_hopper bash-4.2# exit
コンテナーの停止: 端末のセッションに割り当てられていない実行中のコンテナーを停止するには、stop オプションとコンテナー ID または番号を使用します。以下が例になります。
# docker stop myrhel_httpd myrhel_httpd
stop オプションは SIGTERM 信号を送り、実行中のコンテナーを停止します。しばらくの間 (デフォルトでは 10 秒) コンテナーが停止しないと、docker は SIGKILL 信号を送ります。さらに、docker kill コマンドを使用してコンテナーを kill (SIGKILL) するか、または別の信号をコンテナーに送信することもできます。以下は、SIGHUP 信号をコンテナーに送る例です (アプリケーションがサポートしている場合、SIGHUP によりアプリケーションが設定ファイルを再読み込みを行います)。
# docker kill --signal="SIGHUP" myrhel_httpd
コンテナーの削除
システムに保存されているコンテナーの一覧を表示するには、docker ps -a コマンドを実行します。不要なコンテナーを削除するには、オプションのコンテナー ID または名前と共に docker rm コマンドを使用します。以下は例になります。
# docker rm goofy_wozniak
同じコマンドラインで複数のコンテナーを削除できます。
# docker rm clever_yonath furious_shockley drunk_newton
すべてのコンテナーを削除する場合は、以下のようなコマンドを使用してローカルシステムからすべてのコンテナー (イメージではない) を削除できます。このコマンドを実行すると、すべてのコンテナーが削除されることに注意してください。
# docker rm $(docker ps -a -q)
7.5.6. Docker イメージの作成
ここまでの手順で、既存の docker コンテナーイメージを取得し、各種の方法でそれらを使用できるようになりました。必要なコンテナーをより少ない手順で実行するプロセスを用意するには、Docker イメージを始めから作成するか、既存のイメージを別のコンテンツまたは設定と組み合わせて実行したコンテナーから作成できます。
コンテナーからのイメージの作成
以下の手順では、既存のイメージ (rhel:latest) と選択しているパッケージセット(例: Apache Web サーバーの httpd) から新規イメージを作成する方法について説明します。
注意: 現在の Red Hat Docker リリースの場合、Red Hat から取得したデフォルトの RHEL 7 Docker イメージは、ホストシステムから利用できる RHEL 7 エンタイトルメントで利用できます。そのため、Docker ホストが適切にサブスクライブされていて、コンテナーで必要なソフトウェアを取得するためのリポジトリーが有効にされている限り (さらに Docker ホストからインターネットにアクセスできる場合)、RHEL 7 ソフトウェアリポジトリーからパッケージをインストールできます。
新規コンテナーへの httpd のインストール: Red Hat カスタマーポータルからローカルシステムに rhel イメージをロードし、Red Hat のサブスクリプション管理を使用してホストを適切にサブスクライブした場合は、次のコマンドを使用して以下を実行できます。
- イメージをベースイメージとして使用する。
- 現在インストールしているパッケージの最新バージョンを取得する (アップデート)。
- httpd パッケージ (およびすべての依存パッケージ) をインストールする。
yum の一時キャッシュファイルをすべて削除する。
# docker run -i rhel:latest /bin/bash -c "yum clean all; \ yum update -y; yum install -y httpd; yum clean all"
新規イメージのコミット: 新規コンテナーの ID または名前 (docker ps -l) を取得して、そのコンテナーをローカルリポジトリーにコミットします。コンテナーを新規イメージにコミットすると、コメント (-m) および作者名 (-a) を追加できます。さらに、イメージ名 (rhel_httpd) を新たに設定できます。次に docker images と入力して、新規イメージをイメージの一覧で確認します。
# docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f6832df8da0a redhat/rhel7:0 /bin/bash -c 'yum cl About a minute ago Exited (0) 13 seconds ago backstabbing_ptolemy4 # docker commit -m "RHEL with httpd" -a "Chris Negus" f6832df8da0a rhel_httpd 630bd3ff318b8a5a63f1830e9902fec9a4ab9eade7238835fa6b7338edc988ac # docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE rhel_httpd latest 630bd3ff318b 27 seconds ago 170.8 MB redhat/rhel latest e1f5733f050b 4 weeks ago 140.2 MB
新規イメージからのコンテナーの実行: 作成したばかりのイメージを使用して、以下の docker run コマンドを実行し、インストールした Web サーバー (httpd) を起動します。以下は例になります。
# docker run -d -p 8080:80 rhel_httpd:latest \ /usr/sbin/httpd -DFOREGROUND
この例では、Apache Web サーバー (httpd) はコンテナーのポート 80 で listen していて、このコンテナーはホストのポート 8080 にマップされています。
コンテナーが実行中であることの確認: 起動した httpd サーバーが利用可能であることを確認するには、そのサーバーからファイルを取得してみます。ホストからアドレスが http://localhost:8080 の Web ブラウザーを開くか、または curl などのコマンドラインユーティリティーを使用して httpd サーバーにアクセスします。
# curl http://localhost:8080
Dockerfile からのイメージの構築
これまでの手順でイメージやコンテナーをコマンドラインから作成する方法について説明したので、このセクションではより永続的な方法でコンテナーを構築します。Docker フォーマットのコンテナーを作成するには、Dockerfile ファイルからコンテナーイメージを構築する方法が、実行中のコンテナーを修正し、それらのコンテナーをイメージにコミットすることよりもはるかに推奨される方法になります。
以下の手順では、前述の数多くの機能を含む Dockerfile ファイルを作成します。
- ベースイメージの選択
- Apache Web サーバー (httpd) に必要なパッケージのインストール
- サーバーのポート (TCP ポート 80) のホストの別のポート (TCP ポート 8080) へのマッピング
- Web サーバーの起動
RHEL 7 で Docker 開発環境を設定する機能は多数ありますが、ここでは、独自の docker コンテナーを構築する際に注意する必要がある点についていくつか紹介します。
エンタイトルメント: コンテナーに関連する Red Hat エンタイトルメント関連の問題についていくつか紹介します。
- Red Hat Subscription Manager を使用して Docker ホストシステムのサブスクライブを行う場合、そのホストに Docker イメージを構築する際に、ビルド環境はホストで有効にしたのと同じ Red Hat ソフトウェアリポジトリーに自動的にアクセスできます。
- コンテナーを構築する際にさらに多くのリポジトリーを利用できるようにするには、ホスト上またはコンテナー内でそれらのリポジトリーを有効にします。
- subscription-manager コマンドはコンテナーでサポートされていないため、/etc/yum.repos.d/redhat.repo ファイル内で repo を有効にすると、リポジトリーを有効または無効にできます。また、yum-utils パッケージをコンテナーにインストールして yum-config-manager コマンドを実行できます。
- RHEL 6 コンテナーを RHEL 7 ホストに構築する場合は、ホストで有効にされている RHEL 6 バージョンのリポジトリーを自動的に選択します。
- コンテナー内の Red Hat エンタイトルメントの詳細は、Docker Entitlements ソリューションを参照してください。
- アップデート: Red Hat Enterprise Linux の Docker コンテナーには、アップデートしたソフトウェアパッケージが自動的に含まれません。Docker イメージを再構築して、パッケージを最新にしたり、重要なアップデートが必要な場合にすぐに再構築したりする必要がある場合があります。たとえば、以下の Dockerfile の例で示される "RUN yum update -y" 行を使用して、Docker イメージが再構築されるたびにパッケージをアップデートできます。
イメージ: デフォルトで、docker ビルドはローカルキャッシュから特定するベースイメージの最新バージョンを使用します。新規イメージを構築する前に、リモート Docker レジストリーからイメージの最新バージョンを取得 (docker pull コマンドを使用) する必要がある場合があります。イメージの特定のインスタンスが必要な場合はタグを指定します。たとえば、イメージ "centos" を指定すると、centos:latest イメージが取得されます。CentOS 6 のイメージが必要な場合は、centos:centos6 イメージを取得する必要があります。
プロジェクトディレクトリーの作成: docker および docker-registry サービスを実行中のホストシステムで、プロジェクトのディレクトリーを作成します。
# mkdir -p httpd-project # cd httpd-project
Dockerfile ファイルの作成: テキストエディターを使用して Dockerfile という名前のファイルを開きます (vim Dockerfile など)。ホストの RHEL 7 システムを登録し、サブスクライブを行なった場合は、以下が httpd サーバーの Docker コンテナーを構築する際の Dockerfile ファイルの例になります。
# My cool Docker image # Version 1 # If you loaded redhat-rhel-server-7.0-x86_64 to your local registry, uncomment this FROM line instead: # FROM registry.access.redhat.com/rhel # Pull the rhel image from the local registry FROM registry.access.redhat.com/rhel MAINTAINER Chris Negus # Update image RUN yum update -y # Add httpd package. procps and iproute are only added to investigate the image later. RUN yum install httpd procps iproute -y RUN echo container.example.com > /etc/hostname # Create an index.html file RUN bash -c 'echo "Your Web server test is successful." >> /var/www/html/index.html'
- Dockerfile 構文の作成 (オプション): Red Hat は Red Hat カスタマーポータルで Docker file ファイルを確認するツールを提供しています。Dockerfile ファイルを構築する前に Linter for Dockerfile ページに移動してそのファイルを確認することができます。
イメージの構築: Dockerfile ファイルからイメージを構築するには、build オプションを使用して Dockerfile ファイルの場所を指定する必要があります (ここでは現行ディレクトリーを示す "." を使用)。
注意: docker build で --no-cache オプションを使用することを検討してください。--no-cache を使用すると、各ビルド層のキャッシュを取得しないで、過剰なディスク領域の使用を防ぐことができます。
# docker build -t rhel_httpd . Uploading context 2.56 kB Uploading context Step 0 : FROM registry.access.redhat.com/rhel ---> f5f7ddddef7d Step 1 : MAINTAINER Chris Negus ---> Running in 3c605e879c72 ---> 77828ebe8f6f Removing intermediate container 3c605e879c72 Step 2 : RUN yum update -y ---> Running in 9f45bb262dc6 ... ---> Running in f44ea9eb6155 ---> 6a532e340ccf Removing intermediate container f44ea9eb6155 Successfully built 6a532e340ccf
イメージ内での httpd サーバーの実行: 以下のコマンドを実行すると、構築したイメージ (この例では rhel_httpd) から httpd サーバーを実行できます。
# docker run -d -t --name=myrhel_httpd \ -p 80:80 -i rhel_httpd:latest \ /usr/sbin/httpd -DFOREGROUND
サーバーが実行中であることの確認: ホストの別の端末で以下を入力し、httpd サーバーにアクセスできることを確認します。
# netstat -tupln | grep 80 tcp6 0 0 :::80 :::* LISTEN 26137/docker-proxy # curl localhost:80 Your Web server test is successful.
イメージのタグ付け
何が含まれているかを判別しやすくするために、名前をイメージに追加できます。docker tag コマンドを使用すると、基本的に複数の部分で構成されるイメージにエイリアスが追加されます。これには以下が含まれます。
registryhost/username/NAME:tag
NAME だけを追加することもできます。以下は例になります。
# docker tag 474ff279782b myrhel7
ここで、rhel7 イメージのイメージ ID は 474ff279782b です。docker tag を使用すると、名前 myrhel7 をイメージ ID に割り当てることもできます。そのため、このコンテナーを名前 (rhel7 または myrhel7) またはイメージ ID で実行できます。:tag を名前に追加しないと、:latest がタグとして割り当てられます。以下のようにタグを 7.1 に設定できます。
# docker tag 474ff279782b myrhel7:7.1
オプションで、ユーザー名やレジストリー名を名前の前に追加できます。ユーザー名は、実際はリポジトリーを所有するユーザーアカウントに関連する Docker.io のリポジトリーです。イメージにレジストリー名を使ってタグ付けする方法は「Docker レジストリーの外からイメージを取得する」を参照してください。以下は、ユーザー名を追加する例です。
# docker tag 474ff279782b cnegus/myrhel7 # docker images | grep 474ff279782b rhel7 latest 474ff279782b 7 months ago 139.6 MB myrhel7 latest 474ff279782b 7 months ago 139.6 MB myrhel7 7.1 474ff279782b 7 months ago 139.6 MB cnegus/myrhel7 latest 474ff279782b 7 months ago 139.6 MB
ここでは、1 つのイメージ ID に割り当てられたイメージ名がすべて表示されます。
イメージの保存およびインポート
作成した Docker イメージを保存する場合は、docker save を実行すると tarball にイメージを保存できます。tarball の作成後にはイメージを再ロードし、再利用することができるため、それを保存したり、他のユーザーに送信したりすることができます。以下は、イメージを tarball として保存する例です。
# docker save -o myrhel7.tar myrhel7:latest
myrhel7.tar ファイルは現在のディレクトリーに保存されます。後に tarball をコンテナーイメージとして再利用する場合は、以下のようにこれを別の docker 環境にインポートできます。
# cat myrhel7.tar | docker import - cnegus/myrhel7
イメージの削除
システムにあるイメージの一覧を確認するには、docker images コマンドを実行します。不要になったイメージを削除するには、docker rmi コマンドにオプションとしてイメージ ID または名前を追加して実行します (イメージを削除する前に、そのイメージを使用しているコンテナーを停止する必要があります)。以下は例になります。
# docker rmi rhel
同じコマンドラインで複数のイメージを削除することができます。
# docker rmi rhel fedora
すべてのイメージを削除する必要がある場合、以下のようなコマンドを使用してローカルレジストリーからすべてのイメージを削除できます (このコマンドを実行すると、すべてのイメージが削除されます)。
# docker rmi $(docker images -a -q)
7.6. まとめ
現在、docker と docker-registry サービスが動作している Red Hat Docker をインストールことができます。コンテナーの実行方法や独自のイメージを構築する方法を確認できるように、1 つ以上の Docker メージを使用することができます。
Comments