Docker入門
緑川 京太
Dockerとは
Linux上で独立したLinux環境を作ることができ
るコンテナ型仮想化ソフトウェア
コンテナ型仮想化とは...
カーネルをホストと共有しつつ、ルートファイルシステムや、プロセス、
ネットワークなどの隔離された空間作ることで、仮想化を実現
Dockerのライフサイクル1
DockerHub
保存
起動
アップロード
ダウンロード
コンテナ
起動した状態VM
イメージ
停止した状態のVM
リポジトリ
いろんな人が作った
イメージが保存
されている
編集
DockerはClient/Serverアプリケーション
Docker Client Docker Server
● Docker Server (daemon)
- 実際にコンテナを操作する
● Docker Client
- CLIでサーバーに命令を与える
操作
命令
(CLI)
Dockeのポリシー
●
一度作ったイメージはどこでも動く
- 他のマシンでもDockerServerさえ動けば同じ環境を再現できる
●
一度作ったコンテナは変更しない
- コンテナに変更を加えたら必ずイメージに固めてイメージから再起動
● 1コンテナ1プロセスを推奨している
- コンテナはできるだけ単純に作り、保守・スケールしやすいようにする
(個人的には役割ごとにコンテナを分けるのがいいと思う)
開発での便利さ
● リソースの少ないPCでも本番の環境を再現できる
●
失敗しても、前のバージョンに戻ることがができる
●
スクラップ&ビルドが高速
●
ローカルのコンテナをそのままサーバーで動かせる
●
メンバー同士で同じ環境を使うことができる
● SSHでログインしなくて良い
コンテナとVMの違い
● VM (ハイパーバイザ型仮想化)
●
ハイパーバイザー上で動作
●
ハードウェアまで仮想化
(nic,cpu,メモリ,カーネル)
● OSはホストとは別物
● コンテナ (コンテナ型仮想化)
● ホストOS(Linux)上で動作
(カーネルはホストと共有)
●
ユーザ空間の資源を仮想化
(PID,UID,network,etc...)
ハードウェア
OS+ハイパーバイザ(kvm)
OS
App App
VM
ハードウェア
OS
OS
App App
VM
App App
コンテナ
App App
コンテナ
VMのメリット・デメリット
●
メリット
●
限りなく物理マシンと同じように使うことができる
● ホストのOSと全く別のOSをインストールできる
- Linuxホスト上にwindowsのVMとかできる
● VM上の操作はホストには影響しない
●
デメリット
●
仮想化のオーバーヘッドが大きい
● 立ち上げに時間がかかる(isoから作ると30分程)
● CPUが仮想化に対応している必要がある(Intel VT , AMD-V)
コンテナのメリット・デメリット
●
メリット
●
オーバーヘッドが少ない
- 言ってしまえばただのプロセス
●
立ち上げが高速
●
作る→捨てるが簡単
● VM上でも動かせる
●
デメリット
●
ホストに欠陥があると全てのコンテナが影響を受ける
- カーネルをホストと共有しているため、カーネルパラメータやカーネルモジュール
をコンテナ固有の設定にすることは出来ない。
● ホストと共通のカーネルを利用できるOSのみ動作可
- Linuxホスト上にwindowsやMacとかはできない
ハードウェア
OS
App App
コンテナ
App App
コンテナ
Dockerの中身
● Dockerはkernelの機能の一部で実装されている
chroot
namespacecgroup
指定したディレクトリをルート
ファイルシステムとする機能
プロセスごとに CPU、メモリな
どのリソースを割り当てること
ができる機能
ネットワーク, PID, UID, GID, mnt
などのリソースを区切ってお互いが
認識できないようにする
その気になれば、これらの
コマンドで、コンテナっぽい
ものを作ることも可能
chroot
指定したディレクトリをルートファイルシステムとする機能
(OSのイメージファイルなどを編集できて便利!)
/
/bin /usr /var /mnt
/bin /usr /var /etc
sda1
sdb1
chroot /mnt bin/sh
を実行すると、当該shellでは、
「/mnt」が「/」とみなされる
例えば、/mntに
qcow2イメージ
をマウントして。。。
namespace
リソースを区切って、 お互いが認識できないようにするもの
(仮想ネットワークの実験でお世話になる)
- IPC : プロセス間通信リソースの分離
- mount : ファイルシステムツリーの分離
- network : ネットワークデバイス、IP、ルーティングテーブル、iptablesの分離
- PID : プロセスID空間の分離
- UID : UID・GIDの分離
- UTS : ホスト名
IPC mnt net
PID UTSUID
namespace_1
IPC mnt net
PID UTSUID
namespace_2
※namespaceの実体は
/proc/<PID>/ns配下に存在
1と2は同一ホスト内にあるにも関わらずお互いのユーザー、
プロセス、ネットワーク、マウントされているデバイスを認識できない
cgroup
プロセスごとに、CPUやメモリなどのリソースを割り当てる
PID : 19
PID : 1903
PID : 2567
PID : 905
PID : 21
PID : 193
PID : 2960
PID : 1576
メモリ4GB メモリ12GB
※実体は/sys/fs/cgroup配下に存在
同一ホストで動いているプロセスでもそれぞれ
割り当てられているメモリの上限が異なる
Dockerのネットワーク
docker0
コンテナ1
eth0
コンテナ3
eth0
eth0
コンテナ2
eth0
LinuxBridge
172.17.0.1
iptables(NAT)
172.17.0.2 172.17.0.3 172.17.0.4
ホスト
Dockerのライフサイクル2
コンテナ イメージ リポジトリ
DockerHub
Dockerfile
commit
run
push
pull
build
rm rmi
設計書
export
import
実際に触ってみる1
コンテナでWebサーバーあを立ててみる
作るもの
eth0
eth0
iptables(NAT)
172.17.0.2
ホスト:ubuntu14.04LTS
172.17.0.1
docker0
port : 80
port : 10080
フォワーディング
コンテナ:centos7.2
インストール
# ルートユーザーになる
sudo su
# インストール
wget -qO- http://get.docker.com/ | sh
# インストールできたか確認
docker -v
# ユーザーをdockerグループに追加
gpasswd -a <user-name> docker
# グループに追加したユーザーでdockerが操作できるか確認
su - <user-name>
docker ps
イメージのダウンロード
# イメージはdockerhubからダウンロード
ブラウザでhttps://hub.docker.com/にアクセス
# docker pullでcentos:7をダウンロード
docker pull centos:7
# ダウンロードされたことを確認
docker images
イメージ リポジトリ
DockerHub
pull
コンテナ起動
# ダウンロードしたイメージからコンテナを起動
docker run -ti --name=demo centos:7 /bin/bash
※docker runのオプション
-t : コンソールを割り当てる
-i : detach状態でも標準入力を受け付ける
--name : コンテナの名前
コンテナ イメージ
run
コンテナにnginxをインストール
■ここからコンテナ内の操作■
# コンテナのプロセスを確認
ps aux
# nginxをインストール
yum check-update
yum install -y http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-
centos-7-0.el7.ngx.noarch.rpm
yum install -y --enablerepo=nginx nginx
# nginx起動スクリプトを作成
vi start.sh
----
#!/bin/bash
/usr/sbin/nginx
while true; do sleep 10; done
----
chmod 755 start.sh
./start.sh&
# 確認
ps aux
curl localhost
# コンテナをデタッチ
exit
■ここまでコンテナ内の操作■
コンテナをイメージ化
# コンテナが終了したことを確認
docker ps -a
# コンテナをイメージに固める
docker commit demo demo_nginx
# イメージを確認
docker images
コンテナ イメージcommit
イメージからコンテナを再起動
# イメージからhttpdのみ動いているコンテナを起動する
docker run -d --name=demo_nginx -p 10080:80 demo_nginx
/start.sh
# コンテナが起動しているか確認
docker ps
# フォワーディングしたホストのポートにリクエストを投げる
curl localhost:10080
※docker runのオプション
-d : コンテナをバックグラウンドで実行する
-p <ホスト>:<コンテナ> : コンテナのポートをホストにフォワードする
コンテナにアタッチ
# バックグラウンドで動いているコンテナにアタッチする
docker exec -ti demo_nginx /bin/bash
■ここからコンテナ内の操作■
# プロセスを確認
ps aux
# コンテナをデタッチ
exit
■ここからコンテナ内の操作■
# コンテナを表示
docker ps
# コンテナを停止する
docker stop demo_nginx
実際に触ってみる2
systemdでプロセスを管理するコンテナを作ってみる
作るもの
eth0
eth0
iptables(NAT)
172.17.0.2
ホスト:ubuntu14.04LTS
172.17.0.1
docker0
port : 80
port : 8080
フォワーディング
コンテナ:centos7.2
プロセスをsystemd
で管理する
Dockerfileを作成
# docker buildでsystemdで起動するイメージを作成する
mkdir dockerfile_test
cd dockerfile_test
vi Dockerfile
--
FROM centos:7
ENV container docker
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $
{i}==systemd-tmpfiles-setup.service ] || rm -f $i; done); 
rm -f /lib/systemd/system/multi-user.target.wants/*;
rm -f /etc/systemd/system/*.wants/*;
rm -f /lib/systemd/system/local-fs.target.wants/*; 
rm -f /lib/systemd/system/sockets.target.wants/*udev*; 
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; 
rm -f /lib/systemd/system/basic.target.wants/*;
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]
--
Dockerfileからイメージをbuild
# Dockerfile(設計書)からイメージをbuild
docker build --rm -t systemd ./
# イメージからコンテナを起動
docker run -d --name=systemd --privileged systemd
docker ps
# コンテナにアタッチ
docker exec -ti systemd /bin/bash
※docker buildのオプション
--rm : 中間イメージを削除する
-t <image>[:<tag>] : イメージ名を指定する
Dockerfile(設計書)
build
イメージ
コンテナにapacheをインストール
■ここからコンテナ内の操作■
# systemdが起動しているか確認
ps aux
#nginxをインストール
yum check-update
yum install -y http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-
centos-7-0.el7.ngx.noarch.rpm
yum install -y --enablerepo=nginx nginx
# サービスを有効化&起動
systemctl enable nginx
systemctl start nginx
ps aux
# リクエストを投げてみる
curl localhost
# コンテナをデタッチ
exit
■ここまでコンテナ内の操作■
コンテナをイメージに固めて再起動
# コンテナをイメージに固める
docker stop systemd
docker commit systemd systemd_nginx
# イメージからコンテナを再起動
docker run -d --name=systemd_nginx --privileged -p 8080:80
systemd_nginx
docker ps
# リクエストを投げてみる
curl localhost:8080

Docker入門