More Related Content Similar to Docker with RHEL7 技術勉強会 (20) More from Etsuji Nakai (20) Docker with RHEL7 技術勉強会1. Docker with RHEL7 技術勉強会
レッドハット株式会社
中井悦司 / Etsuji Nakai
Senior Solution Architect
and Cloud Evangelist
v1.1 2016/02/10
2. 2
Docker with RHEL7 技術勉強会
自己紹介
中井悦司(なかいえつじ)
– Twitter @enakai00
日々の仕事
– Senior Solution Architect and
Cloud Evangelist at Red Hat K.K.
企業システムでオープンソースの活用を希望される
お客様を全力でご支援させていただきます。
昔とった杵柄
– 素粒子論の研究(超弦理論とか)
– 予備校講師(物理担当)
– インフラエンジニア(Unix/Linux専門)
好評発売中!
3. 3
Docker with RHEL7 技術勉強会
Contents
Dockerが生まれた背景
Dockerの使い方
Linuxコンテナの内部構造
Dockerイメージの内部構造
Dokcerイメージの外部保管形式
コンテナイメージの設計
参考:OpenShiftが実現するアプリケーション開発の世界
5. 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. 6
Docker with RHEL7 技術勉強会
Dockerに対するRed Hatの貢献
Red Hatの開発協力により、RHEL対応とさらなる機能拡張を継続
– RHEL7での正式サポート
– RHELのThin Provisioning機能対応(ディスク性能の向上)
– RHEL7のプロセス管理機能(systemd)との統合
– Docker専用Linuxディストリビューション(Atomic Host)の開発
7. 7
Docker with RHEL7 技術勉強会
Dockerが提供する基本機能
Dockerfile
① Dockerイメージを自動作成
OSイメージ
アプリケーション
ライブラリー
アプリケーション
フレームワーク
イメージの
作成手順を記載
Docker
イメージ
OS上にインストール可能な
ものはすべてイメージ化可能
② Dockerイメージを保存・公開
③ Dockerサーバーに
イメージを配布・実行
8. 8
Docker with RHEL7 技術勉強会
(参考)Linuxコンテナの仕組み
コンテナ
物理サーバー/仮想マシン
Linuxカーネル
アプリケーション
アプリケーション
・・・
物理サーバー/仮想マシン
Linuxカーネル
・・・
コンテナ
通常のLinux環境 コンテナで分割した環境
コンテナごとに
見える環境が異なる
すべてのアプリケーション
から同じ環境が見える
「Linuxコンテナ」は、プロセスグループごとに独立したOS環境を見せる技術
– ローカルディスクの内容(ディレクトリー内のファイル)
– ネットワーク環境(NIC、IPアドレス)
– CPU、メモリー割り当て
※ Dockerよりもずっと古くから存在する技術です。
アプリケーション
アプリケーション
9. 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. 10
Docker with RHEL7 技術勉強会
Dockerとコンテナの関係
コンテナ
アプリケーション
ディレクトリーツリー
Linux上にマウント
ルートディレクトリー
として割り当て
「Dockerイメージ」の実体は、コンテナに割
り当てるディスクイメージに、ネットワーク
設定などの環境情報を付与したものにすぎま
せん。
Dockerの真の価値は、次のような「イメージ
管理機能」にあります。
– Dockerfile:
Dockerイメージを自動作成する仕組み
– Docker Hub:
Dockerイメージを共有・配布する仕組み
Dockerイメージ
12. 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. 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 repolist
Loaded plugins: product-id, subscription-manager
rhel-6-server-rpms | 3.7 kB 00:00
rhel-6-server-rpms/primary_db | 36 MB 00:43
repo id repo name status
rhel-6-server-rpms Red Hat Enterprise Linux 6 Server (RPMs) 16510
repolist: 16510
FROM registry.access.redhat.com/rhel6:latest
MAINTAINER Etsuji Nakai
RUN 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. 14
Docker with RHEL7 技術勉強会
コンテナとイメージのライフサイクル
保存イメージ
スナップ
ショット
コンテナ起動時に
スナップショットを作成
×
run
commit
rm
プロセス
スナップ
ショット
stop
start
保存イメージ
コンテナを停止するとプロセスが停止
(ディスクイメージは残っている)
コンテナを削除すると
ディスクイメージを破棄
ディスクイメージを複製して
保存イメージとして登録
参考:Dockerにおけるコンテナのライフサイクル
http://d.hatena.ne.jp/enakai00/20140628/1403933390
15. 15
Docker with RHEL7 技術勉強会
Dockerの基本操作
RHEL6のイメージからコンテナ内でbashを起動する操作例です
– ローカルに保存されたイメージを確認します。
– イメージからコンテナを起動します。
– コンテナ内のbashに接続して、コンテナ内の様子を確認します。
– コンテナを停止・破棄します。
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
enakai00/httpd ver1.0 6df27b8c50bc 4 hours ago 452.4 MB
enakai00/rhel6 ver1.0 ff6f4181e480 6 hours ago 186.9 MB
registry.access.redhat.com/rhel6 latest fb7b495fd705 8 weeks ago 166.1 MB
# docker run -itd --name rhel enakai00/rhel6:ver1.0 /bin/bash
bcc09984018e91c85b68ae6928ff6244ce6d4c1dea06c2c547319d0d7ac8ef85
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bcc09984018e enakai00/rhel6:ver1.0 "/bin/bash" 3 seconds ago Up 3 seconds rhel
# docker attach rhel
[root@bcc09984018e /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 07:37 ? 00:00:00 /bin/bash
root 14 1 0 07:37 ? 00:00:00 ps -ef
[root@bcc09984018e /]#
# docker stop rhel
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bcc09984018e enakai00/rhel6:ver1.0 "/bin/bash" 36 seconds ago Exited (137) 4 seconds ago rhel
# docker rm rhel
Ctrl+[P][Q]でコンテナ内のbashを抜けます
16. 16
Docker with RHEL7 技術勉強会
Dockerの基本操作
Dockerfileを用いて、Apache(httpd)をインストールしたイメージを作成する例です。
– Dockerfileとアプリケーション起動スクリプトを用意します。
– イメージをビルドします。
(*) アプリケーション起動スクリプトのより適切な処理方法は、後ほど解説します。
FROM enakai00/rhel6:ver1.0
MAINTAINER Etsuji Nakai
RUN yum -y install httpd
RUN echo 'Hello, World!' >> /var/www/html/index.html
ADD init.sh /usr/local/bin/init.sh
RUN chmod u+x /usr/local/bin/init.sh
EXPOSE 80
CMD ["/usr/local/bin/init.sh"]
#!/bin/bash
/etc/init.d/httpd start
while [[ true ]]; do
/bin/bash
done
~/build_httpd/Dockerfile
~/build_httpd/init.sh
FROM: ベースイメージの指定
RUN: コンテナ内でコマンドを実行
ADD: コンテナ内にファイルをコピー
EXPOSE: コンテナ内でアクセスを受け付けるポート番号
CMD: コンテナ起動時に最初に実行するコマンド
このスクリプトが終了すると
コンテナ全体が停止するので
bashを起動しておく(*)
# docker build -t enakai00/httpd:ver1.0 ~/build_httpd/
17. 17
Docker with RHEL7 技術勉強会
Dockerの基本操作
作成したイメージからアプリケーション(httpd)を起動する例です。
– コンテナを起動して、アプリケーションにアクセスしてみます。
– コンテナを停止・破棄します。
# docker run -itd -p 8000:80 --name httpd enakai00/httpd:ver1.0
93cb65660357794474874ebf1a0ce096489cb3e03f0ef700893effcbb4e8dd2a
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
93cb65660357 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:8000
Hello, World!
# docker stop httpd
# docker rm httpd
19. 19
Docker with RHEL7 技術勉強会
各コンテナのプロセスは、同じLinuxカーネルで実行されますが、プロセステーブルはコンテ
ナごとに独立しているので、他のコンテナのプロセスは見えません。
– コンテナの外部にあたるホストLinux上では全てのプロセスが見えます。
コンテナによるリソース分割 〜 プロセステーブル
# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 02:50 ? 00:00:00 /bin/sh /usr/local/bin/init.sh
root 14 1 0 02:50 ? 00:00:00 /usr/sbin/httpd
apache 16 14 0 02:50 ? 00:00:00 /usr/sbin/httpd
apache 17 14 0 02:50 ? 00:00:00 /usr/sbin/httpd
...
root 24 1 0 02:50 ? 00:00:00 /bin/bash
# ps -ef
UID 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.sh
root 18783 18770 0 02:50 ? 00:00:00 /usr/sbin/httpd
48 18785 18783 0 02:50 ? 00:00:00 /usr/sbin/httpd
48 18786 18783 0 02:50 ? 00:00:00 /usr/sbin/httpd
root 18793 18770 0 02:50 pts/1 00:00:00 /bin/bash
コンテナ内から見えるプロセス
ホストLinuxから見えるプロセス
20. 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/bash
done
init.sh
21. 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. 22
Docker with RHEL7 技術勉強会
コンテナによるリソース分割 〜 ファイルシステム
Dockerでは、独自のディスクイメージ管理機能を利用して、指定のイメージをホストLinux
上にマウントしたものをコンテナのルートファイルシステムとして見せます。
ホストLinuxでのイメージ管理の仕組みは、別資料で解説します。
# df
Filesystem 1K-blocks Used Available Use% Mounted on
rootfs 103080888 502796 97318828 1% /
/dev/mapper/docker-253:1-25345014-d7cbab5140dbd4558757db87bc286546af68ac668f9e09940e4162d...
103080888 502796 97318828 1% /
tmpfs 942060 0 942060 0% /dev
shm 65536 0 65536 0% /dev/shm
tmpfs 942060 0 942060 0% /sys/fs/cgroup
tmpfs 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/hosts
tmpfs 942060 0 942060 0% /proc/kcore
tmpfs 942060 0 942060 0% /proc/timer_stats
コンテナ内から見える
ファイルシステム
ホストLinuxで用意した
ディスクイメージ
一部のファイルは個別に
bind mountされている
23. 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. 24
Docker with RHEL7 技術勉強会
コンテナによるリソース分割 〜 ネットワーク
コンテナと外部の通信は、vethを通じて行います。
– vethはLinuxカーネルが標準で提供する機能で、クロスケーブルで直結したかのような仮想NICのペア
を作成します。
vethのペアの片方をコンテナ用のNetwork namespaceに入れて、コンテナからのみ見えるよ
うにします。もう一方は、ホストLinuxの仮想ブリッジに接続します。
– IPアドレスの割り当てやルーティングテーブルなどもコンテナ内のNetwork namespaceで独立して設
定が可能です。
外部ネットワークとの通信は、ホストLinuxでNATが行われ
ます。
– コンテナから外部へは、デフォルトでIPマスカレードが行われ
ます。
– 外部からコンテナへは、コンテナ起動時のオプションでポート
フォワーディングを設定します。
コンテナ
ホストLinux
vethXX
eth0
docker0
eth0
外部ネットワーク
172.17.42.1
# docker run -it -p 8000:80 ...
ホストLinuxの
IPアドレスに接続
TCP 8000
TCP 80
ポート
フォワー
ディング
25. 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. 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 - - -
..(以下略)...
28. 28
Docker with RHEL7 技術勉強会
ローカルでのイメージ保存方式
RHEL7/CentOS7/Atomic Hostでは、ローカルでのイメージ保存に、「Device Mapper Thin-
Provisioning (dm-thin)」の機能を利用しています。
dm-thinでは、データ用デバイス(ブロックプール)の上に複数の「論理デバイス」を定義
して利用します。
– dm-thinで作成した論理デバイスをマウントすると、コンテナに見せるルートファイルシステムが
入っています。
– それぞれの論理デバイス対して、実際に書き込みがあった部分のみに一定サイズのブロックが割り当
てられていきます。
データ用デバイス(ブロックプール)
メタデータ用
デバイス
論理デバイスへの個々の
ブロックの割り当てを記録
Docker
イメージ
論理デバイス#1 ・・・
Docker
イメージ
論理デバイス#2
29. 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. 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/httpd
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
enakai/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. 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
# lsblk
NAME 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. 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. 33
Docker with RHEL7 技術勉強会
共通のベースイメージから複数イメージを作った場合
RHEL6のイメージから「httpdを追加したイメージ」と「mysqlを追加したイメージ」をそれ
ぞれ作成して保存すると、内部的には下記のような論理デバイスが構成されます。
RHEL6
論理デバイス#1
RHEL6
+ mysql
論理デバイス#3
RHEL6
+ httpd
論理デバイス#2
RHEL6の
コンテンツ
httpdの
追加ファイル
msyqlの
追加ファイル
34. 34
Docker with RHEL7 技術勉強会
Dockerfileによるイメージ作成時の動作
Dockerfileからイメージをビルドする際は、1つの命令ごとに中間コンテナを起動して、新
しい中間イメージを作成していきます。
– Dockerfileの一部を修正してイメージを再ビルドする際に、中間イメージがキャッシュとして利用さ
れます。
FROMで指定した
イメージイメージ
コンテナ起動
STEP1実行
コンテナ起動
STEP2実行
中間イメージ
を保存
××
・・・
中間コンテナは
その都度破棄する
中間コンテナ
完成イメージ
中間イメージ
を保存
コンテナ起動
STEP3実行
×
35. 35
Docker with RHEL7 技術勉強会
イメージの親子関係
ローカルに保存したイメージは、どのイメージのスナップショットから作成されたのかとい
う親子関係のツリー情報をメタデータとして保存しています。
– それぞれのイメージは、論理デバイスとしては独立しているので、サーバー上で使用する上では、親
子関係の情報は不要です。このようなツリー情報を保持している理由は、この後で・・・。
RHEL6
論理デバイス#1
RHEL6
+ mysql
論理デバイス#3
RHEL6
+ httpd
論理デバイス#2
親のイメージ 親のイメージ
37. 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. 38
Docker with RHEL7 技術勉強会
exportイメージは「単なるtarアーカイブ」
「docker export」でイメージを取り出すと、論理デバイスをローカルマウントして、その中
のルートファイルシステムをまるごとtarコマンドで固めたものが得られます。
– イメージの親子関係や各種メタデータはすべて失われます。
RHEL6
論理デバイス#1
RHEL6
+ mysql
論理デバイス#3
RHEL6
+ httpd
論理デバイス#2
export_image.tar
# docker export
ローカルマウント
tarコマンドでアーカイブ
39. 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. 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.tar
drwxr-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.tar
drwxr-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.tar
drwxr-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. 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. 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. 43
Docker with RHEL7 技術勉強会
exportイメージのインポート
exportイメージを「docker import」で読み込んだ場合は、新規の論理デバイスにルート
ファイルシステムの内容を展開するだけです。
– ベースイメージを共有することができないので、ディスク容量の節約はできなくなります。
一方、Dockerを使用しない普通の物理サーバーや仮想マシンのルートファイルシステムを
tarで固めて、無理やりインポートすることも可能です。
http://www.slideshare.net/Yuryu/ec2linux
45. 45
Docker with RHEL7 技術勉強会
コンテナイメージ設計のポイント
コンテナ内では、特定のアプリケーションのみを実行します。
– 余計なものを動かすと実行環境が限定されてポータビリティが損なわれます。
– アプリケーションの監視・管理処理は、コンテナの外部から実施します。
– コンテナ内で何らかのメンテナンスジョブを実行する際は、「docker exec」を利用します。
コンテナ内で最初に起動するプロセス(PID=1のプロセス)には、特別な役割があります。
– これが停止するとコンテナ全体が停止します。
– 「docker stop」でコンテナを停止する際は、このプロセスにTERMシグナルが送られます。これによ
り、アプリケーションの停止処理が実行されるように仕込んでおきます。
アプリケーション起動時は、環境変数で必要な情報を受け渡します。
– 「docker run」の-eオプションで環境変数がセットできます。
– OpenShift/Kubernetesなどのツールでも、環境変数をセットする仕組みが用意されています。
46. 46
Docker with RHEL7 技術勉強会
PostgreSQL用イメージのサンプル
FROM enakai00/rhel6:ver1.0
MAINTAINER Etsuji Nakai
RUN groupadd -g 10000 postgres;
useradd -u 10000 -g 10000 postgres
RUN yum -y install postgresql-server
ADD init.sh /usr/local/bin/init.sh
RUN chown postgres.postgres /usr/local/bin/init.sh;
chmod u+x /usr/local/bin/init.sh
USER postgres
EXPOSE 5432
CMD ["/usr/local/bin/init.sh"]
~/build_pgsql/Dockerfile
ユーザー「postgres」で
起動スクリプト init.sh を実行
uid/gidを明示して
ユーザー/グループを作成
47. 47
Docker with RHEL7 技術勉強会
PostgreSQL用イメージのサンプル
#!/bin/bash
export PGDATA=/var/lib/pgsql/data
if [ "${PG_USER-undef}" = "undef" ]; then
export PG_USER=pguser
fi
if [ "${PG_DATABASE-undef}" = "undef" ]; then
export PG_DATABASE=pgdb
fi
if [[ ! -f /var/lib/pgsql/data/PG_VERSION ]]; then
/usr/bin/initdb
cat <<'EOF' >> /var/lib/pgsql/data/postgresql.conf
listen_addresses = '*'
log_destination = 'stderr'
logging_collector = off
EOF
cat <<'EOF' > /var/lib/pgsql/data/pg_hba.conf
local all all trust
host all all 0.0.0.0/0 trust
host all all ::1/128 trust
EOF
/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 stop
fi
exec /usr/bin/postmaster
~/build_pgsql/init.sh
環境変数を用いて、作成する
ユーザーとDBを指定
execコマンドで自分自身(PID=1)を
アプリケーションプロセスに切り替える
あくまでサンプルなので
セキュリティ設定は適当です…
「docker logs」でログが見れるように
標準(エラー)出力にログを出力
48. 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 pgsql
The 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 EST
LOG: database system is ready to accept connections
LOG: 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. 49
Docker with RHEL7 技術勉強会
PostgreSQL用イメージのサンプル
コンテナを停止すると、DBの停止処理が適切に行われていることがわかります。
# docker stop pgsql
# docker logs pgsql
...
waiting for server to shut down....LOG: received smart shutdown request
LOG: autovacuum launcher shutting down
LOG: shutting down
LOG: database system is shut down
done
server stopped
LOG: database system was shut down at 2016-02-09 04:21:19 EST
LOG: database system is ready to accept connections
LOG: autovacuum launcher started
LOG: received smart shutdown request
LOG: autovacuum launcher shutting down
LOG: shutting down
LOG: database system is shut down
# docker rm pgsql
51. 51
Docker with RHEL7 技術勉強会
OpenShiftが提供する主な追加機能
Dockerイメージのバージョン管理
– イメージストリームとイメージビルドシステム
– 「開発環境」そのものを開発可能に
同一の開発環境のクラウド上への配布
– テンプレート機能
– それぞれの開発者に「自分専用」の開発/検証環境を提供
マルチテナントでの利用
– プロジェクト単位でのネームスペースの分割
– 開発機能(ブランチ)単位で独立した開発/検証環境を提供
サーバーの境界を意識しないコンテナのデプロイ
– Kubernetesによるコンテナのオーケストレーション
– マイクロサービス型アプリケーションのDevOps環境を実現
52. 52
Docker with RHEL7 技術勉強会
従来のPaaSの利用形態
アプリ開発者
開発環境
テンプレート
新しいコードをPushすると
開発・テスト環境に展開してビルド
開発したコードの
稼働確認
53. 53
Docker with RHEL7 技術勉強会
従来のPaaSの利用形態
アプリ開発者
開発環境
テンプレートテンプレートそのものの
メンテナンスはどうする?
開発中に開発環境の
アップデートは可能?
開発が終わったアプリは
どうやって本番展開する?
54. 54
Docker with RHEL7 技術勉強会
OpenShiftにおける役割分担
アプリ開発者
開発環境
構成テンプレート
テンプレート管理者
公式RHEL
イメージ
Dockerfile
テスト担当者
開発環境
イメージ
テスト環境
構成テンプレート
開発中
アプリイメージ
ソースコード
動作確認
コード開発
テスト用
デプロイ環境
動作確認
本番環境
構成テンプレート
開発用デプロイ環境
本番用
デプロイ環境
開発済み
アプリイメージ
テスト済み
アプリイメージ
リリース担当者
55. 55
Docker with RHEL7 技術勉強会
テンプレートとGUIの組み合わせによるPaaSの提供
テンプレート機能とGUIを組み合わせることで、アプリケーション開発者には、従来型の
「PaaS」環境として見せることができます。
アプリケーション開発者は
コードの開発のみに集中