56
Docker with RHEL7 技術勉強会 レッドハット株式会社 中井悦司 / Etsuji Nakai Senior Solution Architect and Cloud Evangelist v1.1 2016/02/10

Docker with RHEL7 技術勉強会

Embed Size (px)

Citation preview

Page 1: Docker with RHEL7 技術勉強会

Docker with RHEL7 技術勉強会

レッドハット株式会社

中井悦司 / Etsuji NakaiSenior Solution Architect

and Cloud Evangelist

v1.1 2016/02/10

Page 2: Docker with RHEL7 技術勉強会

2

Docker with RHEL7 技術勉強会

自己紹介

中井悦司(なかいえつじ)– Twitter @enakai00

日々の仕事– Senior Solution Architect and

Cloud Evangelist at Red Hat K.K.企業システムでオープンソースの活用を希望されるお客様を全力でご支援させていただきます。

昔とった杵柄– 素粒子論の研究(超弦理論とか)– 予備校講師(物理担当)– インフラエンジニア(Unix/Linux専門)

好評発売中!

Page 3: Docker with RHEL7 技術勉強会

3

Docker with RHEL7 技術勉強会

Contents

Dockerが生まれた背景 Dockerの使い方 Linuxコンテナの内部構造 Dockerイメージの内部構造 Dokcerイメージの外部保管形式 コンテナイメージの設計 参考:OpenShiftが実現するアプリケーション開発の世界

Page 4: Docker with RHEL7 技術勉強会

Dockerが生まれた背景

Page 5: Docker with RHEL7 技術勉強会

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

Page 6: Docker with RHEL7 技術勉強会

6

Docker with RHEL7 技術勉強会

Dockerに対するRed Hatの貢献

Red Hatの開発協力により、RHEL対応とさらなる機能拡張を継続– RHEL7での正式サポート– RHELのThin Provisioning機能対応(ディスク性能の向上)– RHEL7のプロセス管理機能(systemd)との統合– Docker専用Linuxディストリビューション(Atomic Host)の開発

Page 7: Docker with RHEL7 技術勉強会

7

Docker with RHEL7 技術勉強会

Dockerが提供する基本機能

Dockerfile

① Dockerイメージを自動作成

OSイメージ

アプリケーションライブラリー

アプリケーションフレームワーク

イメージの作成手順を記載

Dockerイメージ

OS上にインストール可能なものはすべてイメージ化可能

② Dockerイメージを保存・公開

③ Dockerサーバーに イメージを配布・実行

Page 8: Docker with RHEL7 技術勉強会

8

Docker with RHEL7 技術勉強会

(参考)Linuxコンテナの仕組み

コンテナ

物理サーバー/仮想マシン

Linuxカーネル

アプ

リケ

ーシ

ョン

アプ

リケ

ーシ

ョン

・・・

物理サーバー/仮想マシン

Linuxカーネル

・・・

コンテナ

通常のLinux環境 コンテナで分割した環境

コンテナごとに見える環境が異なる

すべてのアプリケーションから同じ環境が見える

「Linuxコンテナ」は、プロセスグループごとに独立したOS環境を見せる技術– ローカルディスクの内容(ディレクトリー内のファイル)– ネットワーク環境(NIC、IPアドレス)– CPU、メモリー割り当て

※ Dockerよりもずっと古くから存在する技術です。

アプ

リケ

ーシ

ョン

アプ

リケ

ーシ

ョン

Page 9: Docker with RHEL7 技術勉強会

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コンテナの実体

Page 10: Docker with RHEL7 技術勉強会

10

Docker with RHEL7 技術勉強会

Dockerとコンテナの関係コンテナ

アプ

リケ

ーシ

ョン

ディレクトリーツリー

Linux上にマウント

ルートディレクトリーとして割り当て

「Dockerイメージ」の実体は、コンテナに割り当てるディスクイメージに、ネットワーク設定などの環境情報を付与したものにすぎません。

Dockerの真の価値は、次のような「イメージ管理機能」にあります。

– Dockerfile:Dockerイメージを自動作成する仕組み

– Docker Hub:Dockerイメージを共有・配布する仕組み

Dockerイメージ

Page 11: Docker with RHEL7 技術勉強会

Dockerの使い方

Page 12: Docker with RHEL7 技術勉強会

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

Page 13: Docker with RHEL7 技術勉強会

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

Page 14: Docker with RHEL7 技術勉強会

14

Docker with RHEL7 技術勉強会

コンテナとイメージのライフサイクル

保存イメージ スナップショット

コンテナ起動時にスナップショットを作成

×run

commit

rm

プロセス

スナップショット

stop

start

保存イメージ

コンテナを停止するとプロセスが停止(ディスクイメージは残っている)

コンテナを削除するとディスクイメージを破棄

ディスクイメージを複製して保存イメージとして登録

参考:Dockerにおけるコンテナのライフサイクルhttp://d.hatena.ne.jp/enakai00/20140628/1403933390

Page 15: Docker with RHEL7 技術勉強会

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を抜けます

Page 16: Docker with RHEL7 技術勉強会

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/

Page 17: Docker with RHEL7 技術勉強会

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

Page 18: Docker with RHEL7 技術勉強会

Linuxコンテナの内部構造

Page 19: Docker with RHEL7 技術勉強会

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から見えるプロセス

Page 20: Docker with RHEL7 技術勉強会

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

Page 21: Docker with RHEL7 技術勉強会

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

Page 22: Docker with RHEL7 技術勉強会

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されている

Page 23: Docker with RHEL7 技術勉強会

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

Page 24: Docker with RHEL7 技術勉強会

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

ポートフォワーディング

Page 25: Docker with RHEL7 技術勉強会

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のグループ名

Page 26: Docker with RHEL7 技術勉強会

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 - - -..(以下略)...

Page 27: Docker with RHEL7 技術勉強会

Dockerイメージの内部構造

Page 28: Docker with RHEL7 技術勉強会

28

Docker with RHEL7 技術勉強会

ローカルでのイメージ保存方式

RHEL7/CentOS7/Atomic Hostでは、ローカルでのイメージ保存に、「Device Mapper Thin-Provisioning (dm-thin)」の機能を利用しています。

dm-thinでは、データ用デバイス(ブロックプール)の上に複数の「論理デバイス」を定義して利用します。

– dm-thinで作成した論理デバイスをマウントすると、コンテナに見せるルートファイルシステムが入っています。

– それぞれの論理デバイス対して、実際に書き込みがあった部分のみに一定サイズのブロックが割り当てられていきます。

データ用デバイス(ブロックプール)メタデータ用

デバイス

論理デバイスへの個々のブロックの割り当てを記録

Dockerイメージ

論理デバイス#1 ・・・

Dockerイメージ

論理デバイス#2

Page 29: Docker with RHEL7 技術勉強会

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

遅延挿入

Page 30: Docker with RHEL7 技術勉強会

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}

Page 31: Docker with RHEL7 技術勉強会

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

データ用デバイス

メタデータ用デバイス

Page 32: Docker with RHEL7 技術勉強会

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

書き込み発生

・・・

ブロックプール 書き込んだ部分は新しいブロックを割り当てる

Page 33: Docker with RHEL7 技術勉強会

33

Docker with RHEL7 技術勉強会

共通のベースイメージから複数イメージを作った場合

RHEL6のイメージから「httpdを追加したイメージ」と「mysqlを追加したイメージ」をそれぞれ作成して保存すると、内部的には下記のような論理デバイスが構成されます。

RHEL6

論理デバイス#1

RHEL6+ mysql

論理デバイス#3

RHEL6+ httpd

論理デバイス#2

RHEL6のコンテンツ

httpdの追加ファイル

msyqlの追加ファイル

Page 34: Docker with RHEL7 技術勉強会

34

Docker with RHEL7 技術勉強会

Dockerfileによるイメージ作成時の動作

Dockerfileからイメージをビルドする際は、1つの命令ごとに中間コンテナを起動して、新しい中間イメージを作成していきます。

– Dockerfileの一部を修正してイメージを再ビルドする際に、中間イメージがキャッシュとして利用されます。

FROMで指定したイメージイメージ

コンテナ起動STEP1実行

コンテナ起動STEP2実行

中間イメージを保存

××

・・・

中間コンテナはその都度破棄する

中間コンテナ

完成イメージ

中間イメージを保存

コンテナ起動STEP3実行

×

Page 35: Docker with RHEL7 技術勉強会

35

Docker with RHEL7 技術勉強会

イメージの親子関係

ローカルに保存したイメージは、どのイメージのスナップショットから作成されたのかという親子関係のツリー情報をメタデータとして保存しています。

– それぞれのイメージは、論理デバイスとしては独立しているので、サーバー上で使用する上では、親子関係の情報は不要です。このようなツリー情報を保持している理由は、この後で・・・。

RHEL6

論理デバイス#1

RHEL6+ mysql

論理デバイス#3

RHEL6+ httpd

論理デバイス#2

親のイメージ 親のイメージ

Page 36: Docker with RHEL7 技術勉強会

Dockerイメージの外部保管形式

Page 37: Docker with RHEL7 技術勉強会

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

これらにはどんな違いがあるのでしょうか?

Page 38: Docker with RHEL7 技術勉強会

38

Docker with RHEL7 技術勉強会

exportイメージは「単なるtarアーカイブ」

「docker export」でイメージを取り出すと、論理デバイスをローカルマウントして、その中のルートファイルシステムをまるごとtarコマンドで固めたものが得られます。

– イメージの親子関係や各種メタデータはすべて失われます。

RHEL6

論理デバイス#1

RHEL6+ mysql

論理デバイス#3

RHEL6+ httpd

論理デバイス#2

export_image.tar

# docker export

ローカルマウント

tarコマンドでアーカイブ

Page 39: Docker with RHEL7 技術勉強会

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アーカイブ

Page 40: Docker with RHEL7 技術勉強会

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

ベースイメージなのでサイズが大きい

差分イメージなのでサイズが小さい

Page 41: Docker with RHEL7 技術勉強会

41

Docker with RHEL7 技術勉強会

RHEL6+ httpd

saveイメージからの論理デバイスの復元

saveイメージを「docker load」で読み込むと、次のような流れで、最初と同じ論理デバイスの状態が再現されます。

– 空の論理デバイス「RHEL6」を作成して、ベースイメージのアーカイブを書き出します。– 「RHEL6」のスナップショットコピー「RHEL6+httpd」を作成して、差分ファイルのアーカイブを

上書きで書き出します。

それぞれのイメージには、固有のUUIDが割り当てられているので、共通のベースイメージを持つ複数のsaveイメージを復元した場合、同じベースイメージが重複して再現されることはありません。

RHEL6

httpd.tarbase_image.tar

save_image.tar

① 復元② スナップショット作成

③ 差分を上書き

Page 42: Docker with RHEL7 技術勉強会

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

Page 43: Docker with RHEL7 技術勉強会

43

Docker with RHEL7 技術勉強会

exportイメージのインポート

exportイメージを「docker import」で読み込んだ場合は、新規の論理デバイスにルートファイルシステムの内容を展開するだけです。

– ベースイメージを共有することができないので、ディスク容量の節約はできなくなります。

一方、Dockerを使用しない普通の物理サーバーや仮想マシンのルートファイルシステムをtarで固めて、無理やりインポートすることも可能です。

http://www.slideshare.net/Yuryu/ec2linux

Page 44: Docker with RHEL7 技術勉強会

コンテナイメージの設計

Page 45: Docker with RHEL7 技術勉強会

45

Docker with RHEL7 技術勉強会

コンテナイメージ設計のポイント

コンテナ内では、特定のアプリケーションのみを実行します。– 余計なものを動かすと実行環境が限定されてポータビリティが損なわれます。– アプリケーションの監視・管理処理は、コンテナの外部から実施します。– コンテナ内で何らかのメンテナンスジョブを実行する際は、「docker exec」を利用します。

コンテナ内で最初に起動するプロセス(PID=1のプロセス)には、特別な役割があります。– これが停止するとコンテナ全体が停止します。– 「docker stop」でコンテナを停止する際は、このプロセスにTERMシグナルが送られます。これによ

り、アプリケーションの停止処理が実行されるように仕込んでおきます。

アプリケーション起動時は、環境変数で必要な情報を受け渡します。– 「docker run」の-eオプションで環境変数がセットできます。– OpenShift/Kubernetesなどのツールでも、環境変数をセットする仕組みが用意されています。

Page 46: Docker with RHEL7 技術勉強会

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を明示してユーザー/グループを作成

Page 47: Docker with RHEL7 技術勉強会

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」でログが見れるように標準(エラー)出力にログを出力

Page 48: Docker with RHEL7 技術勉強会

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上に用意

Page 49: Docker with RHEL7 技術勉強会

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

Page 50: Docker with RHEL7 技術勉強会

参考:OpenShiftが実現するアプリケーション開発の世界

Page 51: Docker with RHEL7 技術勉強会

51

Docker with RHEL7 技術勉強会

OpenShiftが提供する主な追加機能

Dockerイメージのバージョン管理– イメージストリームとイメージビルドシステム– 「開発環境」そのものを開発可能に

同一の開発環境のクラウド上への配布– テンプレート機能–それぞれの開発者に「自分専用」の開発/検証環境を提供

マルチテナントでの利用– プロジェクト単位でのネームスペースの分割– 開発機能(ブランチ)単位で独立した開発/検証環境を提供

サーバーの境界を意識しないコンテナのデプロイ– Kubernetesによるコンテナのオーケストレーション–マイクロサービス型アプリケーションのDevOps環境を実現

Page 52: Docker with RHEL7 技術勉強会

52

Docker with RHEL7 技術勉強会

従来のPaaSの利用形態

アプリ開発者

開発環境テンプレート

新しいコードをPushすると開発・テスト環境に展開してビルド

開発したコードの稼働確認

Page 53: Docker with RHEL7 技術勉強会

53

Docker with RHEL7 技術勉強会

従来のPaaSの利用形態

アプリ開発者

開発環境テンプレートテンプレートそのものの

メンテナンスはどうする?開発中に開発環境の

アップデートは可能?

開発が終わったアプリはどうやって本番展開する?

Page 54: Docker with RHEL7 技術勉強会

54

Docker with RHEL7 技術勉強会

OpenShiftにおける役割分担

アプリ開発者

開発環境構成テンプレート

テンプレート管理者公式RHELイメージ

Dockerfile

テスト担当者

開発環境イメージ

テスト環境構成テンプレート

開発中アプリイメージ

ソースコード

動作確認

コード開発

テスト用デプロイ環境

動作確認

本番環境構成テンプレート

開発用デプロイ環境本番用デプロイ環境

開発済みアプリイメージ

テスト済みアプリイメージ

リリース担当者

Page 55: Docker with RHEL7 技術勉強会

55

Docker with RHEL7 技術勉強会

テンプレートとGUIの組み合わせによるPaaSの提供

テンプレート機能とGUIを組み合わせることで、アプリケーション開発者には、従来型の「PaaS」環境として見せることができます。

アプリケーション開発者はコードの開発のみに集中

Page 56: Docker with RHEL7 技術勉強会

EMPOWER PEOPLE,

EMPOWER ENTERPRISE,

OPEN INNOVATION.