Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Docker with RHEL7 技術勉強会

4,469 views

Published on

「Docker with RHEL7 技術勉強会」の資料です。

2016/02/10 ver1.0 公開
2016/02/10 ver1.1 Dockerfileによるビルドの流れを追加

Published in: Technology
  • Be the first to comment

Docker with RHEL7 技術勉強会

  1. 1. Docker with RHEL7 技術勉強会 レッドハット株式会社 中井悦司 / Etsuji Nakai Senior Solution Architect and Cloud Evangelist v1.1 2016/02/10
  2. 2. 2 Docker with RHEL7 技術勉強会 自己紹介  中井悦司(なかいえつじ) – Twitter @enakai00  日々の仕事 – Senior Solution Architect and Cloud Evangelist at Red Hat K.K. 企業システムでオープンソースの活用を希望される お客様を全力でご支援させていただきます。  昔とった杵柄 – 素粒子論の研究(超弦理論とか) – 予備校講師(物理担当) – インフラエンジニア(Unix/Linux専門) 好評発売中!
  3. 3. 3 Docker with RHEL7 技術勉強会 Contents  Dockerが生まれた背景  Dockerの使い方  Linuxコンテナの内部構造  Dockerイメージの内部構造  Dokcerイメージの外部保管形式  コンテナイメージの設計  参考:OpenShiftが実現するアプリケーション開発の世界
  4. 4. Dockerが生まれた背景
  5. 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. 6 Docker with RHEL7 技術勉強会 Dockerに対するRed Hatの貢献  Red Hatの開発協力により、RHEL対応とさらなる機能拡張を継続 – RHEL7での正式サポート – RHELのThin Provisioning機能対応(ディスク性能の向上) – RHEL7のプロセス管理機能(systemd)との統合 – Docker専用Linuxディストリビューション(Atomic Host)の開発
  7. 7. 7 Docker with RHEL7 技術勉強会 Dockerが提供する基本機能 Dockerfile ① Dockerイメージを自動作成 OSイメージ アプリケーション ライブラリー アプリケーション フレームワーク イメージの 作成手順を記載 Docker イメージ OS上にインストール可能な ものはすべてイメージ化可能 ② Dockerイメージを保存・公開 ③ Dockerサーバーに  イメージを配布・実行
  8. 8. 8 Docker with RHEL7 技術勉強会 (参考)Linuxコンテナの仕組み コンテナ 物理サーバー/仮想マシン Linuxカーネル アプリケーション アプリケーション ・・・ 物理サーバー/仮想マシン Linuxカーネル ・・・ コンテナ 通常のLinux環境 コンテナで分割した環境 コンテナごとに 見える環境が異なる すべてのアプリケーション から同じ環境が見える  「Linuxコンテナ」は、プロセスグループごとに独立したOS環境を見せる技術 – ローカルディスクの内容(ディレクトリー内のファイル) – ネットワーク環境(NIC、IPアドレス) – CPU、メモリー割り当て ※ Dockerよりもずっと古くから存在する技術です。 アプリケーション アプリケーション
  9. 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. 10 Docker with RHEL7 技術勉強会 Dockerとコンテナの関係 コンテナ アプリケーション ディレクトリーツリー Linux上にマウント ルートディレクトリー として割り当て  「Dockerイメージ」の実体は、コンテナに割 り当てるディスクイメージに、ネットワーク 設定などの環境情報を付与したものにすぎま せん。  Dockerの真の価値は、次のような「イメージ 管理機能」にあります。 – Dockerfile: Dockerイメージを自動作成する仕組み – Docker Hub: Dockerイメージを共有・配布する仕組み Dockerイメージ
  11. 11. Dockerの使い方
  12. 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. 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. 14 Docker with RHEL7 技術勉強会 コンテナとイメージのライフサイクル 保存イメージ スナップ ショット コンテナ起動時に スナップショットを作成 × run commit rm プロセス スナップ ショット stop start 保存イメージ コンテナを停止するとプロセスが停止 (ディスクイメージは残っている) コンテナを削除すると ディスクイメージを破棄 ディスクイメージを複製して 保存イメージとして登録 参考:Dockerにおけるコンテナのライフサイクル http://d.hatena.ne.jp/enakai00/20140628/1403933390
  15. 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. 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. 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
  18. 18. Linuxコンテナの内部構造
  19. 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. 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. 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. 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. 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. 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. 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. 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 - - - ..(以下略)...
  27. 27. Dockerイメージの内部構造
  28. 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. 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. 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. 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. 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. 33 Docker with RHEL7 技術勉強会 共通のベースイメージから複数イメージを作った場合  RHEL6のイメージから「httpdを追加したイメージ」と「mysqlを追加したイメージ」をそれ ぞれ作成して保存すると、内部的には下記のような論理デバイスが構成されます。 RHEL6 論理デバイス#1 RHEL6 + mysql 論理デバイス#3 RHEL6 + httpd 論理デバイス#2 RHEL6の コンテンツ httpdの 追加ファイル msyqlの 追加ファイル
  34. 34. 34 Docker with RHEL7 技術勉強会 Dockerfileによるイメージ作成時の動作  Dockerfileからイメージをビルドする際は、1つの命令ごとに中間コンテナを起動して、新 しい中間イメージを作成していきます。 – Dockerfileの一部を修正してイメージを再ビルドする際に、中間イメージがキャッシュとして利用さ れます。 FROMで指定した イメージイメージ コンテナ起動 STEP1実行 コンテナ起動 STEP2実行 中間イメージ を保存 ×× ・・・ 中間コンテナは その都度破棄する 中間コンテナ 完成イメージ 中間イメージ を保存 コンテナ起動 STEP3実行 ×
  35. 35. 35 Docker with RHEL7 技術勉強会 イメージの親子関係  ローカルに保存したイメージは、どのイメージのスナップショットから作成されたのかとい う親子関係のツリー情報をメタデータとして保存しています。 – それぞれのイメージは、論理デバイスとしては独立しているので、サーバー上で使用する上では、親 子関係の情報は不要です。このようなツリー情報を保持している理由は、この後で・・・。 RHEL6 論理デバイス#1 RHEL6 + mysql 論理デバイス#3 RHEL6 + httpd 論理デバイス#2 親のイメージ 親のイメージ
  36. 36. Dockerイメージの外部保管形式
  37. 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. 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. 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. 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. 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. 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. 43 Docker with RHEL7 技術勉強会 exportイメージのインポート  exportイメージを「docker import」で読み込んだ場合は、新規の論理デバイスにルート ファイルシステムの内容を展開するだけです。 – ベースイメージを共有することができないので、ディスク容量の節約はできなくなります。  一方、Dockerを使用しない普通の物理サーバーや仮想マシンのルートファイルシステムを tarで固めて、無理やりインポートすることも可能です。 http://www.slideshare.net/Yuryu/ec2linux
  44. 44. コンテナイメージの設計
  45. 45. 45 Docker with RHEL7 技術勉強会 コンテナイメージ設計のポイント  コンテナ内では、特定のアプリケーションのみを実行します。 – 余計なものを動かすと実行環境が限定されてポータビリティが損なわれます。 – アプリケーションの監視・管理処理は、コンテナの外部から実施します。 – コンテナ内で何らかのメンテナンスジョブを実行する際は、「docker exec」を利用します。  コンテナ内で最初に起動するプロセス(PID=1のプロセス)には、特別な役割があります。 – これが停止するとコンテナ全体が停止します。 – 「docker stop」でコンテナを停止する際は、このプロセスにTERMシグナルが送られます。これによ り、アプリケーションの停止処理が実行されるように仕込んでおきます。  アプリケーション起動時は、環境変数で必要な情報を受け渡します。 – 「docker run」の-eオプションで環境変数がセットできます。 – OpenShift/Kubernetesなどのツールでも、環境変数をセットする仕組みが用意されています。
  46. 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. 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. 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. 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
  50. 50. 参考:OpenShiftが実現する アプリケーション開発の世界
  51. 51. 51 Docker with RHEL7 技術勉強会 OpenShiftが提供する主な追加機能  Dockerイメージのバージョン管理 – イメージストリームとイメージビルドシステム – 「開発環境」そのものを開発可能に  同一の開発環境のクラウド上への配布 – テンプレート機能 – それぞれの開発者に「自分専用」の開発/検証環境を提供  マルチテナントでの利用 – プロジェクト単位でのネームスペースの分割 – 開発機能(ブランチ)単位で独立した開発/検証環境を提供  サーバーの境界を意識しないコンテナのデプロイ – Kubernetesによるコンテナのオーケストレーション – マイクロサービス型アプリケーションのDevOps環境を実現
  52. 52. 52 Docker with RHEL7 技術勉強会 従来のPaaSの利用形態 アプリ開発者 開発環境 テンプレート 新しいコードをPushすると 開発・テスト環境に展開してビルド 開発したコードの 稼働確認
  53. 53. 53 Docker with RHEL7 技術勉強会 従来のPaaSの利用形態 アプリ開発者 開発環境 テンプレートテンプレートそのものの メンテナンスはどうする? 開発中に開発環境の アップデートは可能? 開発が終わったアプリは どうやって本番展開する?
  54. 54. 54 Docker with RHEL7 技術勉強会 OpenShiftにおける役割分担 アプリ開発者 開発環境 構成テンプレート テンプレート管理者 公式RHEL イメージ Dockerfile テスト担当者 開発環境 イメージ テスト環境 構成テンプレート 開発中 アプリイメージ ソースコード 動作確認 コード開発 テスト用 デプロイ環境 動作確認 本番環境 構成テンプレート 開発用デプロイ環境 本番用 デプロイ環境 開発済み アプリイメージ テスト済み アプリイメージ リリース担当者
  55. 55. 55 Docker with RHEL7 技術勉強会 テンプレートとGUIの組み合わせによるPaaSの提供  テンプレート機能とGUIを組み合わせることで、アプリケーション開発者には、従来型の 「PaaS」環境として見せることができます。 アプリケーション開発者は コードの開発のみに集中
  56. 56. EMPOWER PEOPLE, EMPOWER ENTERPRISE, OPEN INNOVATION.

×