Upload
etsuji-nakai
View
3.117
Download
1
Embed Size (px)
Citation preview
Docker with RHEL7 技術勉強会
レッドハット株式会社
中井悦司 / Etsuji NakaiSenior Solution Architect
and Cloud Evangelist
v1.1 2016/02/10
2
Docker with RHEL7 技術勉強会
自己紹介
中井悦司(なかいえつじ)– Twitter @enakai00
日々の仕事– Senior Solution Architect and
Cloud Evangelist at Red Hat K.K.企業システムでオープンソースの活用を希望されるお客様を全力でご支援させていただきます。
昔とった杵柄– 素粒子論の研究(超弦理論とか)– 予備校講師(物理担当)– インフラエンジニア(Unix/Linux専門)
好評発売中!
3
Docker with RHEL7 技術勉強会
Contents
Dockerが生まれた背景 Dockerの使い方 Linuxコンテナの内部構造 Dockerイメージの内部構造 Dokcerイメージの外部保管形式 コンテナイメージの設計 参考:OpenShiftが実現するアプリケーション開発の世界
Dockerが生まれた背景
5
Docker with RHEL7 技術勉強会
History
2011年 米dotCloud社がパブリックのPaaSサービスを提供開始 2013年 dotCloudのコア技術を「Docker」として公開 2014年 dotCloud社は、Docker, Inc.に社名を変更して、Dockerを
活用したサービス、製品にビジネスを切り替えることを表明 (*)
(*) dotCloudのPaaSサービスは、米cloudControl社が事業を引き継いでサービスを提供中 https://www.dotcloud.com/about.html
6
Docker with RHEL7 技術勉強会
Dockerに対するRed Hatの貢献
Red Hatの開発協力により、RHEL対応とさらなる機能拡張を継続– RHEL7での正式サポート– RHELのThin Provisioning機能対応(ディスク性能の向上)– RHEL7のプロセス管理機能(systemd)との統合– Docker専用Linuxディストリビューション(Atomic Host)の開発
7
Docker with RHEL7 技術勉強会
Dockerが提供する基本機能
Dockerfile
① Dockerイメージを自動作成
OSイメージ
アプリケーションライブラリー
アプリケーションフレームワーク
イメージの作成手順を記載
Dockerイメージ
OS上にインストール可能なものはすべてイメージ化可能
② Dockerイメージを保存・公開
③ Dockerサーバーに イメージを配布・実行
8
Docker with RHEL7 技術勉強会
(参考)Linuxコンテナの仕組み
コンテナ
物理サーバー/仮想マシン
Linuxカーネル
アプ
リケ
ーシ
ョン
アプ
リケ
ーシ
ョン
・・・
物理サーバー/仮想マシン
Linuxカーネル
・・・
コンテナ
通常のLinux環境 コンテナで分割した環境
コンテナごとに見える環境が異なる
すべてのアプリケーションから同じ環境が見える
「Linuxコンテナ」は、プロセスグループごとに独立したOS環境を見せる技術– ローカルディスクの内容(ディレクトリー内のファイル)– ネットワーク環境(NIC、IPアドレス)– CPU、メモリー割り当て
※ Dockerよりもずっと古くから存在する技術です。
アプ
リケ
ーシ
ョン
アプ
リケ
ーシ
ョン
9
Docker with RHEL7 技術勉強会
コンテナによって分離されるリソースにはいくつかの種類がありますが、内部的には、それぞれ異なる技術によって実現されています。
– ファイルシステムの分離 → Mount namespace (kernel 2.4.19) – ホストネームの分離 → UTS namespace (kernel 2.6.19)– IPCの分離 → IPC namespece (kernel 2.6.19)– ユーザ(UID/GID)の分離 → User namespace (kernel 2.6.23〜kernel 3.8)– プロセステーブルの分離 → PID namespace (kernel 2.6.24) – ネットワーク設定の分離 → Network Namepsace (kernel 2.6.24)– リソース配分の制御 → Control groups
※参考資料「Namespaces in operation, part 1: namespaces overview」• http://lwn.net/Articles/531114/
Linuxコンテナはこれらの機能を組み合わせて実現されるものであり、「コンテナ」という単一の技術があるわけではありません。これら機能を統合してコンテナを作り上げる管理ツール/ライブラリには、いくつかの種類があります。(ツール/ライブラリによって利用するネームスペースの種類が異なる場合もあります。)
– lxctools : コンテナを作成・管理するコマンドを集めたもの。– libvirt : KVM/Xenなどの仮想化環境の操作を共通化するAPIライブラリ。コンテナも管理可能。– Docker : 本資料のメインテーマとなるツール。ディスクイメージの管理機能が特徴的。
Linuxコンテナの実体
10
Docker with RHEL7 技術勉強会
Dockerとコンテナの関係コンテナ
アプ
リケ
ーシ
ョン
ディレクトリーツリー
Linux上にマウント
ルートディレクトリーとして割り当て
「Dockerイメージ」の実体は、コンテナに割り当てるディスクイメージに、ネットワーク設定などの環境情報を付与したものにすぎません。
Dockerの真の価値は、次のような「イメージ管理機能」にあります。
– Dockerfile:Dockerイメージを自動作成する仕組み
– Docker Hub:Dockerイメージを共有・配布する仕組み
Dockerイメージ
Dockerの使い方
12
Docker with RHEL7 技術勉強会
RHEL7でDockerを利用する準備 Dockerのインストール
– RHEL7を最小構成でインストールした後、サブスクリプションを登録します。
– パッケージをアップデートとして、firewalldサービスを停止します。(firewalldサービスの停止はこの後の手順を簡単にするためです。本番環境では適切に設定してください。)
– Dockerをインストールして起動します。
# subscription-manager register --username=<username> --password=<password># subscription-manager list --available # subscription-manager attach --pool=<pool_id>
# yum -y update# systemctl mask firewalld.service# reboot
# subscription-manager repos --enable=rhel-7-server-extras-rpms # subscription-manager repos --enable=rhel-7-server-optional-rpms# yum -y install docker# systemctl enable docker.service # systemctl start docker.service # systemctl status docker.service
13
Docker with RHEL7 技術勉強会
RHEL7でDockerを利用する準備 RHEL6イメージの準備
– RHEL6イメージを用意するためのDockerファイルを作成します。
– RHEL6イメージをビルドして、結果を確認します。(「enakai00」は任意のユーザー名に変更)
# docker build -t enakai00/rhel6:ver1.0 ~/build_rhel6/# docker run -it --rm enakai00/rhel6:ver1.0 yum repolistLoaded plugins: product-id, subscription-managerrhel-6-server-rpms | 3.7 kB 00:00 rhel-6-server-rpms/primary_db | 36 MB 00:43 repo id repo name statusrhel-6-server-rpms Red Hat Enterprise Linux 6 Server (RPMs) 16510repolist: 16510
FROM registry.access.redhat.com/rhel6:latestMAINTAINER Etsuji NakaiRUN yum -y install yum-utils ;\ yum clean all ;\ sed -i 's/enabled = 1/enabled = 0/' /etc/yum.repos.d/redhat.repo ;\ yum-config-manager --enable rhel-6-server-rpms;\ yum -y update ;\ yum clean all
~/build_rhel6/Dockerfile
14
Docker with RHEL7 技術勉強会
コンテナとイメージのライフサイクル
保存イメージ スナップショット
コンテナ起動時にスナップショットを作成
×run
commit
rm
プロセス
スナップショット
stop
start
保存イメージ
コンテナを停止するとプロセスが停止(ディスクイメージは残っている)
コンテナを削除するとディスクイメージを破棄
ディスクイメージを複製して保存イメージとして登録
参考:Dockerにおけるコンテナのライフサイクルhttp://d.hatena.ne.jp/enakai00/20140628/1403933390
15
Docker with RHEL7 技術勉強会
Dockerの基本操作 RHEL6のイメージからコンテナ内でbashを起動する操作例です
– ローカルに保存されたイメージを確認します。
– イメージからコンテナを起動します。
– コンテナ内のbashに接続して、コンテナ内の様子を確認します。
– コンテナを停止・破棄します。
# docker imagesREPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZEenakai00/httpd ver1.0 6df27b8c50bc 4 hours ago 452.4 MBenakai00/rhel6 ver1.0 ff6f4181e480 6 hours ago 186.9 MBregistry.access.redhat.com/rhel6 latest fb7b495fd705 8 weeks ago 166.1 MB
# docker run -itd --name rhel enakai00/rhel6:ver1.0 /bin/bashbcc09984018e91c85b68ae6928ff6244ce6d4c1dea06c2c547319d0d7ac8ef85# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESbcc09984018e enakai00/rhel6:ver1.0 "/bin/bash" 3 seconds ago Up 3 seconds rhel
# docker attach rhel[root@bcc09984018e /]# ps -efUID PID PPID C STIME TTY TIME CMDroot 1 0 0 07:37 ? 00:00:00 /bin/bashroot 14 1 0 07:37 ? 00:00:00 ps -ef[root@bcc09984018e /]#
# docker stop rhel# docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESbcc09984018e enakai00/rhel6:ver1.0 "/bin/bash" 36 seconds ago Exited (137) 4 seconds ago rhel# docker rm rhel
Ctrl+[P][Q]でコンテナ内のbashを抜けます
16
Docker with RHEL7 技術勉強会
Dockerの基本操作 Dockerfileを用いて、Apache(httpd)をインストールしたイメージを作成する例です。
– Dockerfileとアプリケーション起動スクリプトを用意します。
– イメージをビルドします。
(*) アプリケーション起動スクリプトのより適切な処理方法は、後ほど解説します。
FROM enakai00/rhel6:ver1.0MAINTAINER Etsuji Nakai
RUN yum -y install httpdRUN echo 'Hello, World!' >> /var/www/html/index.htmlADD init.sh /usr/local/bin/init.shRUN chmod u+x /usr/local/bin/init.shEXPOSE 80CMD ["/usr/local/bin/init.sh"]
#!/bin/bash
/etc/init.d/httpd start
while [[ true ]]; do /bin/bashdone
~/build_httpd/Dockerfile
~/build_httpd/init.sh
FROM: ベースイメージの指定
RUN: コンテナ内でコマンドを実行
ADD: コンテナ内にファイルをコピー
EXPOSE: コンテナ内でアクセスを受け付けるポート番号CMD: コンテナ起動時に最初に実行するコマンド
このスクリプトが終了するとコンテナ全体が停止するので
bashを起動しておく(*)
# docker build -t enakai00/httpd:ver1.0 ~/build_httpd/
17
Docker with RHEL7 技術勉強会
Dockerの基本操作 作成したイメージからアプリケーション(httpd)を起動する例です。
– コンテナを起動して、アプリケーションにアクセスしてみます。
– コンテナを停止・破棄します。
# docker run -itd -p 8000:80 --name httpd enakai00/httpd:ver1.0 93cb65660357794474874ebf1a0ce096489cb3e03f0ef700893effcbb4e8dd2a# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES93cb65660357 enakai00/httpd:ver1.0 "/usr/local/bin/init." 2 seconds ago Up 2 seconds 0.0.0.0:8000->80/tcp httpd# curl http://localhost:8000Hello, World!
# docker stop httpd# docker rm httpd
Linuxコンテナの内部構造
19
Docker with RHEL7 技術勉強会
各コンテナのプロセスは、同じLinuxカーネルで実行されますが、プロセステーブルはコンテナごとに独立しているので、他のコンテナのプロセスは見えません。
– コンテナの外部にあたるホストLinux上では全てのプロセスが見えます。
コンテナによるリソース分割 〜 プロセステーブル
# ps -efUID PID PPID C STIME TTY TIME CMDroot 1 0 0 02:50 ? 00:00:00 /bin/sh /usr/local/bin/init.shroot 14 1 0 02:50 ? 00:00:00 /usr/sbin/httpdapache 16 14 0 02:50 ? 00:00:00 /usr/sbin/httpdapache 17 14 0 02:50 ? 00:00:00 /usr/sbin/httpd...root 24 1 0 02:50 ? 00:00:00 /bin/bash
# ps -efUID PID PPID C STIME TTY TIME CMD...root 9420 1 0 00:25 ? 00:00:18 /usr/bin/docker daemon --selinux-enabled...root 18770 9420 0 02:50 pts/1 00:00:00 /bin/sh /usr/local/bin/init.shroot 18783 18770 0 02:50 ? 00:00:00 /usr/sbin/httpd48 18785 18783 0 02:50 ? 00:00:00 /usr/sbin/httpd48 18786 18783 0 02:50 ? 00:00:00 /usr/sbin/httpdroot 18793 18770 0 02:50 pts/1 00:00:00 /bin/bash
コンテナ内から見えるプロセス
ホストLinuxから見えるプロセス
20
Docker with RHEL7 技術勉強会
コンテナによるリソース分割 〜 プロセステーブル
dockerデーモン
fork&exec
PID namespace
全ページの例では、dockerデーモンが最初のプロセスである「init.sh」を起動するタイミングで、新たな「PID namespace」に入れます。その後、init.shからフォークしていくプロセスは、すべて同じPID namespaceで起動していきます。
– コンテナ内部では、PIDは、ホストLinuxとは独立した値が「1」から振られていきます。– Docker0.9ではUID namespaceは使用しておらず、UID/GIDの値はコンテナ内外で同じです。
/etc/passwdなどのファイルが異なるため、表示される名前は異なっています。• 参考:"Docker 1.0 and user namespaces"
https://groups.google.com/forum/#!topic/docker-dev/MoIDYDF3suY
PID=1
bash
/bin/sh /usr/local/bin/init.sh
httpd
httpd
・・・
#!/bin/bash
/etc/init.d/httpd start
while [[ true ]]; do /bin/bashdone
init.sh
21
Docker with RHEL7 技術勉強会
コンテナによるリソース分割 〜 ファイルシステム
一般には、コンテナ内に独立したディレクトリツリーを用意して、ホストLinuxのディレクトリをコンテナ内のツリーにbind mountすることで、コンテナからアクセス可能にします。
lxctoolsやlibvirtでは、コンテナごとのルートファイルシステムを事前にホストLinux上に用意して利用します。
– 特定のアプリケーションの実行に必要な最小限のファイルのみを配置しても構いません。– 特定のLinuxディストリビューションのルートファイルシステムと同じものをごっそり用意して、まとめて見せることも可能です。
– /devや/procはコンテナ起動時に個別に(必要に応じて)構成します。
Mount namespace
/ |--etc |--bin |--sbin...
/export/container01/rootfs/ |--etc |--bin |--sbin ...
bind mount
22
Docker with RHEL7 技術勉強会
コンテナによるリソース分割 〜 ファイルシステム
Dockerでは、独自のディスクイメージ管理機能を利用して、指定のイメージをホストLinux上にマウントしたものをコンテナのルートファイルシステムとして見せます。
ホストLinuxでのイメージ管理の仕組みは、別資料で解説します。
# dfFilesystem 1K-blocks Used Available Use% Mounted onrootfs 103080888 502796 97318828 1% //dev/mapper/docker-253:1-25345014-d7cbab5140dbd4558757db87bc286546af68ac668f9e09940e4162d... 103080888 502796 97318828 1% /tmpfs 942060 0 942060 0% /devshm 65536 0 65536 0% /dev/shmtmpfs 942060 0 942060 0% /sys/fs/cgrouptmpfs 942060 260 941800 1% /run/secrets/dev/vda1 20959892 3708452 17251440 18% /etc/resolv.conf/dev/vda1 20959892 3708452 17251440 18% /etc/hostname/dev/vda1 20959892 3708452 17251440 18% /etc/hoststmpfs 942060 0 942060 0% /proc/kcoretmpfs 942060 0 942060 0% /proc/timer_stats
コンテナ内から見えるファイルシステム
ホストLinuxで用意したディスクイメージ
一部のファイルは個別にbind mountされている
23
Docker with RHEL7 技術勉強会
ホストLinuxのディレクトリー割り当て
ホストLinuxのディレクトリーをコンテナー内に割り当てることも可能です。– たとえば、アプリケーションログをホストLinux上に出力して、ホストLinuxから監視す
ることができます。–ホストLinuxからコンテナー内にファイルを受け渡すためにも使えます。※ コンテナーに見せるディレクトリーは、SELinuxのセキュリティラベルを設定しておく必要があります。
コンテナ
ホストLinux
/tmp/work
/root/work
コンテナイメージ
ホストLinuxのディレクトリーを割り当て
-v /root/work:/tmp/work
その他のディレクトリーはコンテナイメージを使用
# chcon -Rt svirt_sandbox_file_t /root/work
24
Docker with RHEL7 技術勉強会
コンテナによるリソース分割 〜 ネットワーク
コンテナと外部の通信は、vethを通じて行います。– vethはLinuxカーネルが標準で提供する機能で、クロスケーブルで直結したかのような仮想NICのペア
を作成します。
vethのペアの片方をコンテナ用のNetwork namespaceに入れて、コンテナからのみ見えるようにします。もう一方は、ホストLinuxの仮想ブリッジに接続します。
– IPアドレスの割り当てやルーティングテーブルなどもコンテナ内のNetwork namespaceで独立して設定が可能です。
外部ネットワークとの通信は、ホストLinuxでNATが行われます。
– コンテナから外部へは、デフォルトでIPマスカレードが行われます。
– 外部からコンテナへは、コンテナ起動時のオプションでポートフォワーディングを設定します。
コンテナ
ホストLinuxvethXX
eth0
docker0
eth0
外部ネットワーク
172.17.42.1# docker run -it -p 8000:80 ...
ホストLinuxのIPアドレスに接続
TCP 8000
TCP 80
ポートフォワーディング
25
Docker with RHEL7 技術勉強会
コンテナによるリソース分割 〜 CPUとメモリ
CPUとメモリについては、コンテナ内部から物理ホスト全体のリソースが認識されます。ただし、cgroupsを利用して、コンテナ内のプロセスについて、CPUの割り当て時間や利用可能なメモリの上限を設定することが可能です。
– 原理的には、cgroupsの機能の範囲で、I/Oの帯域制御なども含めて、自由にリソースの割り当て制限が可能です。
Dockerでは、systemdと連携することで、コンテナ内のプロセスに対してcgroupsのグループを割り当てます。
– コンテナを起動する際に、Unitを動的に生成して、最初のプロセスをUnitから起動します。 systemdは、それぞれのUnitごとに自動的にcgroupsのグループを割り当てて管理するので、結果的にコンテナ内のプロセスがまとめて特定のグループに入ります。
# systemd-cgls...└─system.slice ├─docker-cc08291a81556ba55f049e50fd2c04287b04c6cf657a8a9971ef42468a2befa7.scope │ ├─7444 nginx: master process ngin │ ├─7458 nginx: worker proces │ ├─7459 nginx: worker proces │ ├─7460 nginx: worker proces │ └─7461 nginx: worker proces...
「docker-<コンテナID>.scope」がcgroupsのグループ名
26
Docker with RHEL7 技術勉強会
コンテナによるリソース分割 〜 CPUとメモリ
コンテナに割り当てるCPU/メモリを制限したい場合は、次のオプションを用います。– -c、--cpu-shares コンテナに対するCPU時間の割り当て比率– --cpuset-cpus コンテナが使用するCPUコアを指定– -m、--memory コンテナが使用するメモリの上限– --memory-swap スワップ領域を含めたメモリの上限
各コンテナのCPU/メモリ使用量は、systemd-cgtopコマンドで確認します。
# systemd-cgtop -bn1 Path Tasks %CPU Memory Input/s Output/s/ 92 21.3 217.1M - -/system.slice 13 19.7 87.5M - -/system.slice/docker-6049fc656220ed99fe69ea26e431adeb2092841a289ba3aa0cf2bf726a826092.scope 2 19.7 44.4M - -/user.slice 6 0.8 - - -/system.slice/docker.service 2 0.0 - - -/system.slice/tuned.service 1 0.0 - - -..(以下略)...
Dockerイメージの内部構造
28
Docker with RHEL7 技術勉強会
ローカルでのイメージ保存方式
RHEL7/CentOS7/Atomic Hostでは、ローカルでのイメージ保存に、「Device Mapper Thin-Provisioning (dm-thin)」の機能を利用しています。
dm-thinでは、データ用デバイス(ブロックプール)の上に複数の「論理デバイス」を定義して利用します。
– dm-thinで作成した論理デバイスをマウントすると、コンテナに見せるルートファイルシステムが入っています。
– それぞれの論理デバイス対して、実際に書き込みがあった部分のみに一定サイズのブロックが割り当てられていきます。
データ用デバイス(ブロックプール)メタデータ用
デバイス
論理デバイスへの個々のブロックの割り当てを記録
Dockerイメージ
論理デバイス#1 ・・・
Dockerイメージ
論理デバイス#2
29
Docker with RHEL7 技術勉強会
Device Mapperはブロックデバイス(/dev/sdXなど)の上にソフトウェアのWrapperを被せて、さまざまな機能拡張を行ったブロックデバイスを作成する仕組みです。次のような機能拡張を行うモジュールがあります。
– ソフトウェアRAID(dm-raid)– マルチパスアクセス(dm-multipath)– 暗号化(dm-crypt)– アクセス遅延挿入(dm-delay)– etc...
(参考)Device Mapperとは?
/dev/sda /dev/sdb
/dev/dm1
ミラーリング
dm-raid
/dev/sda
/dev/dm1
dm-crypt
暗号化/復号化
/dev/sda
/dev/dm1
dm-delay
遅延挿入
30
Docker with RHEL7 技術勉強会
論理デバイスの管理情報は、下記のJSONファイルに記録されています。– /var/lib/docker/devicemapper/metadata/<Image ID>
– 特に、デバイスID「0」の論理デバイスは、最初にDockerサービスを起動した際に10GBで作成され、ファイルシステムとしてフォーマットされます。Docker Hubからイメージをダウンロードすると、この論理デバイスのスナップショットを作成して、空のファイルシステムを用意して、その中にダウンロードファイルを展開します。(そのため、すべての論理デバイスのサイズは10GBになります。)
DockerにおけるThin Povisioningの利用方式
# docker images enakai/httpdREPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZEenakai/httpd ver1.0 d3d92adfcafb 36 hours ago 206.6 MB
# cat /var/lib/docker/devicemapper/metadata/d3d92adfcafb* | python -mjson.tool{ "device_id": 72, "initialized": false, "size": 10737418240, "transaction_id": 99}
# cat /var/lib/docker/devicemapper/metadata/base | python -mjson.tool{ "device_id": 0, "initialized": true, "size": 10737418240, "transaction_id": 1}
31
Docker with RHEL7 技術勉強会
データ用デバイスの構成について
RHEL7に普通にDockerをインストールした場合は、「100GBのスパース形式のディスクイメージファイル」をループバックマウントしたものが「データ用デバイス」として使用されます。
– ちょっといけてません。。。。
追加設定を行うことで、論理ボリューム(LV)をデータ用デバイスにすることも可能です。
# ls -lh /var/lib/docker/devicemapper/devicemapper/合計 1.2G-rw-------. 1 root root 100G 5月 11 21:37 data-rw-------. 1 root root 2.0G 5月 11 22:05 metadata
# losetup NAME SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE/dev/loop0 0 0 1 0 /var/lib/docker/devicemapper/devicemapper/data/dev/loop1 0 0 1 0 /var/lib/docker/devicemapper/devicemapper/metadata
# lsblkNAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT...loop0 7:0 0 100G 0 loop └─docker-252:3-130516-pool 253:0 0 100G 0 dm loop1 7:1 0 2G 0 loop └─docker-252:3-130516-pool 253:0 0 100G 0 dm
データ用デバイス
メタデータ用デバイス
32
Docker with RHEL7 技術勉強会
dm-thinのスナップショット機能について
Dockerは、Dockerイメージのスナップショットコピーを多用します(次ページ参照)が、 RHEL7/CentOS7/Atomic HostのDockerでは、dm-thinのスナップショット機能を用いて、コピーを作成します。
– 差分領域のみに新しいブロックが割り当てるため高速にコピーを取得すると共に、ディスク使用量を節約する効果があります。
A B C
スナップショット作成直後
A B C A B C
ブロックプール
・・・ A B C D
A B C A B D
書き込み発生
・・・
ブロックプール 書き込んだ部分は新しいブロックを割り当てる
33
Docker with RHEL7 技術勉強会
共通のベースイメージから複数イメージを作った場合
RHEL6のイメージから「httpdを追加したイメージ」と「mysqlを追加したイメージ」をそれぞれ作成して保存すると、内部的には下記のような論理デバイスが構成されます。
RHEL6
論理デバイス#1
RHEL6+ mysql
論理デバイス#3
RHEL6+ httpd
論理デバイス#2
RHEL6のコンテンツ
httpdの追加ファイル
msyqlの追加ファイル
34
Docker with RHEL7 技術勉強会
Dockerfileによるイメージ作成時の動作
Dockerfileからイメージをビルドする際は、1つの命令ごとに中間コンテナを起動して、新しい中間イメージを作成していきます。
– Dockerfileの一部を修正してイメージを再ビルドする際に、中間イメージがキャッシュとして利用されます。
FROMで指定したイメージイメージ
コンテナ起動STEP1実行
コンテナ起動STEP2実行
中間イメージを保存
××
・・・
中間コンテナはその都度破棄する
中間コンテナ
完成イメージ
中間イメージを保存
コンテナ起動STEP3実行
×
35
Docker with RHEL7 技術勉強会
イメージの親子関係
ローカルに保存したイメージは、どのイメージのスナップショットから作成されたのかという親子関係のツリー情報をメタデータとして保存しています。
– それぞれのイメージは、論理デバイスとしては独立しているので、サーバー上で使用する上では、親子関係の情報は不要です。このようなツリー情報を保持している理由は、この後で・・・。
RHEL6
論理デバイス#1
RHEL6+ mysql
論理デバイス#3
RHEL6+ httpd
論理デバイス#2
親のイメージ 親のイメージ
Dockerイメージの外部保管形式
37
Docker with RHEL7 技術勉強会
Dockerイメージのexport/importとsave/loadの違い
Dockerイメージをアーカイブファイルとして取り出して、他のDockerサーバーに持ち運ぶ方法には、「export/import」と「save/load」の2種類の方法があります。
RHEL6
論理デバイス#1
RHEL6+ mysql
論理デバイス#3
RHEL6+ httpd
論理デバイス#2
save_image.tar export_image.tar
# docker save # docker export
これらにはどんな違いがあるのでしょうか?
38
Docker with RHEL7 技術勉強会
exportイメージは「単なるtarアーカイブ」
「docker export」でイメージを取り出すと、論理デバイスをローカルマウントして、その中のルートファイルシステムをまるごとtarコマンドで固めたものが得られます。
– イメージの親子関係や各種メタデータはすべて失われます。
RHEL6
論理デバイス#1
RHEL6+ mysql
論理デバイス#3
RHEL6+ httpd
論理デバイス#2
export_image.tar
# docker export
ローカルマウント
tarコマンドでアーカイブ
39
Docker with RHEL7 技術勉強会
saveイメージは「親子関係を再現可能な分割tarファイル」
「docker save」でイメージを取り出すと、親子関係を再現できるように複数のtarアーカイブが作成されます。下図の例では、次のような順序になります。
– ベースイメージ(RHEL6)をローカルマウントして、ルートファイルシステムをtarアーカイブにします。
– 派生したイメージ(RHEL6+httpd)をローカルマウントして、「ベースイメージから追加・変更されたファイルのみを抽出したtarアーカイブ」を作成します。
– それぞれのイメージの親子関係やメタデータを記載したファイルを作成します。– 以上のすべてを1つのtarアーカイブにまとまて出力します。
RHEL6 RHEL6+ httpd
httpd.tar
# docker save
ローカルマウント
base_image.tar
ローカルマウント
ルートファイルシステムをまとめてアーカイブ
ベースイメージとの差分ファイルのみをアーカイブ
save_image.tar すべてを1つにまとめたtarアーカイブ
40
Docker with RHEL7 技術勉強会
saveイメージは「親子関係を再現可能な分割tarファイル」
saveイメージの内容を実際に確認した例です。– layer.tarは、そのレイヤーのコンテンツを含むアーカイブファイルです。– jsonは、そのレイヤーの親子関係やメタデータを記載したファイルです。
# docker save hoge > hoge.tar# tar -tvf hoge.tar drwx------ 0/0 0 2014-08-02 14:49 ./drwxr-xr-x 0/0 0 2014-08-02 14:49 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a/-rw-r--r-- 0/0 3 2014-08-02 14:49 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a/VERSION-rw-r--r-- 0/0 1565 2014-08-02 14:49 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a/json-rw-r--r-- 0/0 1024 2014-08-02 14:49 34e94e67e63a0f079d9336b3c2a52e814d138e5b3f1f614a0cfe273814ed7c0a/layer.tardrwxr-xr-x 0/0 0 2014-08-02 14:49 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/-rw-r--r-- 0/0 3 2014-08-02 14:49 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/VERSION-rw-r--r-- 0/0 585 2014-08-02 14:49 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/json-rw-r--r-- 0/0 1536 2014-08-02 14:49 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158/layer.tardrwxr-xr-x 0/0 0 2014-08-02 14:49 aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/-rw-r--r-- 0/0 3 2014-08-02 14:49 aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/VERSION-rw-r--r-- 0/0 1285 2014-08-02 14:49 aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/json-rw-r--r-- 0/0 3584 2014-08-02 14:49 aff9664bf7d8eed96731fffc05a2002306e09ca5e22290354eeca6fa577fe8b2/layer.tardrwxr-xr-x 0/0 0 2014-08-02 14:49 b1bd49907d559b703c2b7c1b0d6f120b5182440f7ac5f08636625d328e96f1ef/-rw-r--r-- 0/0 3 2014-08-02 14:49 b1bd49907d559b703c2b7c1b0d6f120b5182440f7ac5f08636625d328e96f1ef/VERSION-rw-r--r-- 0/0 1574 2014-08-02 14:49 b1bd49907d559b703c2b7c1b0d6f120b5182440f7ac5f08636625d328e96f1ef/json-rw-r--r-- 0/0 222638592 2014-08-02 14:49 b1bd49907d559b703c2b7c1b0d6f120b5182440f7ac5f08636625d328e96f1ef/layer.tar-rw-r--r-- 0/0 86 2014-08-02 14:49 repositories
ベースイメージなのでサイズが大きい
差分イメージなのでサイズが小さい
41
Docker with RHEL7 技術勉強会
RHEL6+ httpd
saveイメージからの論理デバイスの復元
saveイメージを「docker load」で読み込むと、次のような流れで、最初と同じ論理デバイスの状態が再現されます。
– 空の論理デバイス「RHEL6」を作成して、ベースイメージのアーカイブを書き出します。– 「RHEL6」のスナップショットコピー「RHEL6+httpd」を作成して、差分ファイルのアーカイブを
上書きで書き出します。
それぞれのイメージには、固有のUUIDが割り当てられているので、共通のベースイメージを持つ複数のsaveイメージを復元した場合、同じベースイメージが重複して再現されることはありません。
RHEL6
httpd.tarbase_image.tar
save_image.tar
① 復元② スナップショット作成
③ 差分を上書き
42
Docker with RHEL7 技術勉強会
Docker Hubのイメージ保存形式
Docker Hubにイメージをアップロードすると、次のような処理が行われます。– saveイメージの作成と同じ流れで、それぞれのレイヤーの「差分tarファイル」を作成します。– それぞれの「差分tarファイル」を固有のUUIDと共にDocker Hubにアップロードして登録します。– Docker Hubにすでに存在するファイル(UUIDで識別)は、アップロードをスキップします。
つまり、Docker Hubは「差分tarファイル」の巨大な保管庫として機能しています。– 複数のユーザーが、Docker Hubから取得した「RHEL6」のベースイメージをもとにさまざまな派生イ
メージを作って、Docker Hubにアップロードした場合、「RHEL6」のベースイメージは、あくまで1つだけ存在することになります。
RHEL6(ベースイメージ)
httpd(差分tarファイル)
mysql(差分tarファイル)
# docker pull
RHEL6
RHEL6+httpd
# docker push
# docker pull
RHEL6
RHEL6+mysql
# docker push
Docker HubユーザーA ユーザーB
43
Docker with RHEL7 技術勉強会
exportイメージのインポート
exportイメージを「docker import」で読み込んだ場合は、新規の論理デバイスにルートファイルシステムの内容を展開するだけです。
– ベースイメージを共有することができないので、ディスク容量の節約はできなくなります。
一方、Dockerを使用しない普通の物理サーバーや仮想マシンのルートファイルシステムをtarで固めて、無理やりインポートすることも可能です。
http://www.slideshare.net/Yuryu/ec2linux
コンテナイメージの設計
45
Docker with RHEL7 技術勉強会
コンテナイメージ設計のポイント
コンテナ内では、特定のアプリケーションのみを実行します。– 余計なものを動かすと実行環境が限定されてポータビリティが損なわれます。– アプリケーションの監視・管理処理は、コンテナの外部から実施します。– コンテナ内で何らかのメンテナンスジョブを実行する際は、「docker exec」を利用します。
コンテナ内で最初に起動するプロセス(PID=1のプロセス)には、特別な役割があります。– これが停止するとコンテナ全体が停止します。– 「docker stop」でコンテナを停止する際は、このプロセスにTERMシグナルが送られます。これによ
り、アプリケーションの停止処理が実行されるように仕込んでおきます。
アプリケーション起動時は、環境変数で必要な情報を受け渡します。– 「docker run」の-eオプションで環境変数がセットできます。– OpenShift/Kubernetesなどのツールでも、環境変数をセットする仕組みが用意されています。
46
Docker with RHEL7 技術勉強会
PostgreSQL用イメージのサンプル
FROM enakai00/rhel6:ver1.0MAINTAINER Etsuji Nakai
RUN groupadd -g 10000 postgres; \ useradd -u 10000 -g 10000 postgresRUN yum -y install postgresql-server
ADD init.sh /usr/local/bin/init.shRUN chown postgres.postgres /usr/local/bin/init.sh; \ chmod u+x /usr/local/bin/init.sh
USER postgresEXPOSE 5432CMD ["/usr/local/bin/init.sh"]
~/build_pgsql/Dockerfile
ユーザー「postgres」で起動スクリプト init.sh を実行
uid/gidを明示してユーザー/グループを作成
47
Docker with RHEL7 技術勉強会
PostgreSQL用イメージのサンプル
#!/bin/bash
export PGDATA=/var/lib/pgsql/dataif [ "${PG_USER-undef}" = "undef" ]; then export PG_USER=pguserfiif [ "${PG_DATABASE-undef}" = "undef" ]; then export PG_DATABASE=pgdbfi
if [[ ! -f /var/lib/pgsql/data/PG_VERSION ]]; then /usr/bin/initdb cat <<'EOF' >> /var/lib/pgsql/data/postgresql.conflisten_addresses = '*'log_destination = 'stderr'logging_collector = offEOF cat <<'EOF' > /var/lib/pgsql/data/pg_hba.conflocal all all trusthost all all 0.0.0.0/0 trusthost all all ::1/128 trustEOF /usr/bin/pg_ctl start sleep 5 /usr/bin/createuser -D -E -R -S -U postgres $PG_USER /usr/bin/createdb -O $PG_USER $PG_DATABASE /usr/bin/pg_ctl stopfiexec /usr/bin/postmaster
~/build_pgsql/init.sh
環境変数を用いて、作成するユーザーとDBを指定
execコマンドで自分自身(PID=1)をアプリケーションプロセスに切り替える
あくまでサンプルなのでセキュリティ設定は適当です…
「docker logs」でログが見れるように標準(エラー)出力にログを出力
48
Docker with RHEL7 技術勉強会
PostgreSQL用イメージのサンプル
ビルド/実行例は次のようになります。
# docker build -t enakai00/pgsql:ver1.0 ~/build_pgsql/# mkdir /data# chcon -Rt svirt_sandbox_file_t /data# chown 10000.10000 /data# docker run -itd -p 5432:5432 -v /data:/var/lib/pgsql/data --name pgsql \ -e PG_USER=etsuji -e PG_DATABASE=mydb enakai00/pgsql:ver1.0
# docker logs pgsqlThe files belonging to this database system will be owned by user "postgres".This user must also own the server process....LOG: database system was shut down at 2016-02-09 04:10:27 ESTLOG: database system is ready to accept connectionsLOG: autovacuum launcher started
# psql -h localhost -U etsuji -l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+-----------+---------+-------+----------------------- mydb | etsuji | SQL_ASCII | C | C | postgres | postgres | SQL_ASCII | C | C | template0 | postgres | SQL_ASCII | C | C | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | SQL_ASCII | C | C | =c/postgres + | | | | | postgres=CTc/postgres(4 rows)
データ保存ディレクトリーはホストLinux上に用意
49
Docker with RHEL7 技術勉強会
PostgreSQL用イメージのサンプル
コンテナを停止すると、DBの停止処理が適切に行われていることがわかります。
# docker stop pgsql# docker logs pgsql...waiting for server to shut down....LOG: received smart shutdown requestLOG: autovacuum launcher shutting downLOG: shutting downLOG: database system is shut down doneserver stoppedLOG: database system was shut down at 2016-02-09 04:21:19 ESTLOG: database system is ready to accept connectionsLOG: autovacuum launcher startedLOG: received smart shutdown requestLOG: autovacuum launcher shutting downLOG: shutting downLOG: database system is shut down
# docker rm pgsql
参考:OpenShiftが実現するアプリケーション開発の世界
51
Docker with RHEL7 技術勉強会
OpenShiftが提供する主な追加機能
Dockerイメージのバージョン管理– イメージストリームとイメージビルドシステム– 「開発環境」そのものを開発可能に
同一の開発環境のクラウド上への配布– テンプレート機能–それぞれの開発者に「自分専用」の開発/検証環境を提供
マルチテナントでの利用– プロジェクト単位でのネームスペースの分割– 開発機能(ブランチ)単位で独立した開発/検証環境を提供
サーバーの境界を意識しないコンテナのデプロイ– Kubernetesによるコンテナのオーケストレーション–マイクロサービス型アプリケーションのDevOps環境を実現
52
Docker with RHEL7 技術勉強会
従来のPaaSの利用形態
アプリ開発者
開発環境テンプレート
新しいコードをPushすると開発・テスト環境に展開してビルド
開発したコードの稼働確認
53
Docker with RHEL7 技術勉強会
従来のPaaSの利用形態
アプリ開発者
開発環境テンプレートテンプレートそのものの
メンテナンスはどうする?開発中に開発環境の
アップデートは可能?
開発が終わったアプリはどうやって本番展開する?
54
Docker with RHEL7 技術勉強会
OpenShiftにおける役割分担
アプリ開発者
開発環境構成テンプレート
テンプレート管理者公式RHELイメージ
Dockerfile
テスト担当者
開発環境イメージ
テスト環境構成テンプレート
開発中アプリイメージ
ソースコード
動作確認
コード開発
テスト用デプロイ環境
動作確認
本番環境構成テンプレート
開発用デプロイ環境本番用デプロイ環境
開発済みアプリイメージ
テスト済みアプリイメージ
リリース担当者
55
Docker with RHEL7 技術勉強会
テンプレートとGUIの組み合わせによるPaaSの提供
テンプレート機能とGUIを組み合わせることで、アプリケーション開発者には、従来型の「PaaS」環境として見せることができます。
アプリケーション開発者はコードの開発のみに集中
EMPOWER PEOPLE,
EMPOWER ENTERPRISE,
OPEN INNOVATION.