docker 奮闘記 ~コンテナ作成編~
docker の基礎を学びます。
docker 概要
docker はコンテナを提供するための OSS ソフトウェアである。
コンテナは仮想化といわれるが、その実は chroot し、隔離されただけの単なるプロセス。
通常のプロセス同様にホストのカーネル上で動く。
ホスト | コンテナ | コンテナ ユーザ空間
プロセス | |
-------------------------------
カーネル カーネル空間
隔離やリソースの制限には、chroot や cgroup といった Linux カーネル標準の技術が使われる。
カーネルや、CPU・メモリといったハードウェア資源のエミュレートは一切行っていない。
隔離されただけのただのプロセスなのである。
コンテナとは
コンテナはイメージ内の実行ファイルを実行することで生成される。
イメージはファイルシステムやメタ情報の詰め合わせである。
コンテナはメインプロセスとその実行環境から構成される。
+------------------------------+ +------------------------------+
| イメージ | | コンテナ |
+------------------------------+ +------------------------------+
| イメージID | | コンテナID |
| イメージ名 | | コンテナ名 |
| | | |
| メタ情報 | | メインプロセス(bash) -------- コンテナの中核。
| | | +-- 子プロセス | このプロセスが死ぬとコンテナは停止する。
| | | +-- 子プロセス |
| | | | docker stop
| filesystem | | filesystem (/) | <----------------
| +-- bin | | +-- bin | コンテナ(プロセスも)の停止
| +-- sbin | | +-- sbin |
| +-- usr | | +-- usr | docker start
| | +-- bin | docker run | | +-- bin | <----------------
| | | +-- bash -----------+----------------> | | | +-- bash | コンテナの起動
| | | +-- sleep | | コンテナ生成 | | | +-- sleep |
| | | +-- etc. | | | | | +-- etc. | docker rm
| | +-- sbin | | | | +-- sbin | <----------------
| +-- lib | | | +-- lib | コンテナの削除
| +-- etc | | | +-- etc |
| +-- var | | | +-- var | docker exec
| +-- etc. | | | +-- etc. | <----------------
+------------------------------+ | +------------------------------+ コンテナ内の実行ファイルを指定してプロセス起動
|
| docker run +------------------------------+
+----------------> | コンテナ |
| +------------------------------+
|
| docker run +------------------------------+
+----------------> | コンテナ |
| +------------------------------+
|
| docker run +------------------------------+
+----------------> | コンテナ |
| +------------------------------+
: :
コンテナのメインプロセスは、コンテナを作成した時点で決まる。
後から変更することはできない。
メインプロセスが死ぬか、docker stop で止められるとコンテナは停止するが、一度生成されたコンテナの情報はディスク上に保持される。
docker start で再度メインプロセスを立ち上げ、コンテナを起動することができる。
OS バージョンが違うコンテナについて
例えばリポジトリから適当にコンテナを落として以下のように構築できた(ように思えた)とする。
ホスト | CentOS | Debian | RHEL
プロセス | 6.5 | 9 | 7.2
-----------------------------------
RHEL 7.5(Linux 3.10.0-862)
実はこれ真っ赤な嘘。
カーネルは共通なので、コンテナの RHEL7.2 で動いているプロセスは RHEL7.2 のカーネル上で動いているかと思いきや実は RHEL7.5 のカーネル上で動いている。
この環境上に RHEL 7.2 のカーネルはどこにも存在しない。
コンテナの CentOS 6.5 やら RHEL 7.2 やらはカーネルバージョンに基づいたものではなく、
ただ単に CentOS 6.5 相当、RHEL 7.2 相当の /bin や /sbin や /usr や /lib が動いていますよ、という意味。
Linux 以外のコンテナについて
全コンテナで Linux カーネルは共有(という表現が正しいかわからないが)。
つまり、Linux 以外のコンテナは動かない。
以下は実現不可能である。
ホスト | FreeBSD | Mac | Windows
プロセス | | |
-----------------------------------
RHEL 7.5(Linux 3.10.0-862)
これがしたいならおとなしく KVM を使おう。
Windows 上での docker について
コンテナは Linux カーネルの機能によって実現されている。
docker は Linux 上でしか動かない。
つまり、docker on Windows だと思えたものは実は docker on Linux Kernel on Windows である。
コンテナ | コンテナ | コンテナ
-----------------------------------
Linux カーネル
-----------------------------------
仮想マシン
-----------------------------------
Windows
docker 実践
導入
インスコ
# yum install docker -y
docker.service プロキシ設定
# mkdir /etc/systemd/system/docker.service.d
# echo -e "[Service]\nEnvironment=\"HTTP_PROXY=http://***.***.***.***:8080/\"" | sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://***.***.***.***:8080/"
# systemctl daemon-reload
# systemctl restart docker
docker スタート
# systemctl start docker
docker 情報確認。プロキシ設定が反映されていることがわかる。
[root@hostname ~]# docker info
Containers: 0
Running: 0
Paused: 0
Stopped: 0
Images: 0
Server Version: 1.13.1
:
Http Proxy: http://***.***.***.***:8080/
:
ハローワールド
公式リポジトリからイメージをダウンロードし、コンテナを動かしてみる。
リポジトリのイメージを検索
[root@hostname ~]# docker search centos
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
docker.io docker.io/centos The official build of CentOS. 5421 [OK]
docker.io docker.io/ansible/centos7-ansible Ansible on Centos7 121 [OK]
docker.io docker.io/jdeathe/centos-ssh CentOS-6 6.10 x86_64 / CentOS-7 7.6.1810 x... 110 [OK]
:
イメージのダウンロード
[root@hostname ~]# docker pull centos
Using default tag: latest
Trying to pull repository registry.access.redhat.com/centos ...
Pulling repository registry.access.redhat.com/centos
Trying to pull repository docker.io/library/centos ...
latest: Pulling from docker.io/library/centos
8ba884070f61: Pull complete
Digest: sha256:b5e66c4651870a1ad435cd75922fe2cb943c9e973a9673822d1414824a1d0475
Status: Downloaded newer image for docker.io/centos:latest
ローカルにあるイメージ一覧
[root@hostname ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/centos latest 9f38484d220f 3 months ago 202 MB
コンテナの生成。
イメージ中に存在する /bin/bash をコンテナとして立ち上げる。
[root@hostname ~]# docker run -it centos:latest /bin/bash
動作の確認
当然カーネルはホストと同一のものである。
ホスト名はコンテナごとにホストとは別のホスト名が与えられる。"隔離" のひとつである。
[root@73230f43d596 /]# uname -a
Linux 73230f43d596 3.10.0-327.el7.x86_64 #1 SMP Thu Oct 29 17:29:29 EDT 2015 x86_64 x86_64 x86_64 GNU/Linux
ネットワークは仮想化されており、eth0 デバイスに 172.17.0.2 が割り与えられている。
コンテナの eth0 はホスト側の docker0 とつながっており、ping 等も疎通する。
[root@7666ac79ff57 net]# cat dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
eth0: 648 8 0 0 0 0 0 0 648 8 0 0 0 0 0 0
lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[root@7666ac79ff57 net]# cat fib_trie
Main:
+-- 0.0.0.0/0 2 0 2
|-- 0.0.0.0
/0 universe UNICAST
|-- 172.17.0.0
/16 link UNICAST
Local:
+-- 0.0.0.0/0 2 0 2
+-- 127.0.0.0/8 2 0 2
+-- 127.0.0.0/31 1 0 0
|-- 127.0.0.0
/32 link BROADCAST
/8 host LOCAL
|-- 127.0.0.1
/32 host LOCAL
|-- 127.255.255.255
/32 link BROADCAST
+-- 172.17.0.0/16 2 0 2
+-- 172.17.0.0/30 2 0 2
|-- 172.17.0.0
/32 link BROADCAST
|-- 172.17.0.2
/32 host LOCAL
|-- 172.17.255.255
/32 link BROADCAST
マウント状態は全く異なるが、コンテナ内から見える物理ディスクはホストと同じである。
物理ディスクの仮想化は行われておらず、コンテナが chroot されただけのプロセスであることを示す証左のひとつである。
[root@73230f43d596 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
fd0 2:0 1 4K 0 disk
sda 8:0 0 20G 0 disk
|-sda1 8:1 0 500M 0 part
|-sda2 8:2 0 17.5G 0 part /run/secrets
|-sda3 8:3 0 1G 0 part
`-sda4 8:4 0 1G 0 part
sdb 8:16 0 1G 0 disk
|-sdb1 8:17 0 100M 0 part
`-sdb2 8:18 0 200M 0 part
sdc 8:32 0 1G 0 disk
`-sdc1 8:33 0 1023M 0 part
`-md0 9:0 0 1022.4M 0 raid1
sdd 8:48 0 2G 0 disk
`-sdd1 8:49 0 1G 0 part
sde 8:64 0 1G 0 disk
`-sde1 8:65 0 1023M 0 part
`-md0 9:0 0 1022.4M 0 raid1
sr0 11:0 1 1024M 0 rom
"/" には overlay マウントされている。
overlay マウントに関しては以下が参考になります。
https://gihyo.jp/admin/serial/01/linux_containers/0018
[root@73230f43d596 secrets]# mount
overlay on / type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/UX5WTFVOLK7ZIK7JSLY5RY4NM2:/var/lib/docker/overlay2/l/WIJMYGLDI52JVYHCWVNVZAAO33,upperdir=/var/lib/docker/overlay2/a4e259dee9705431074082e0ce3b010da5a4c24d0394a4b64b281bdaa04c259a/diff,workdir=/var/lib/docker/overlay2/a4e259dee9705431074082e0ce3b010da5a4c24d0394a4b64b281bdaa04c259a/work)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev type tmpfs (rw,nosuid,mode=755)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=666)
sysfs on /sys type sysfs (ro,nosuid,nodev,noexec,relatime)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,relatime,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (ro,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/blkio type cgroup (ro,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/memory type cgroup (ro,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/cpuacct,cpu type cgroup (ro,nosuid,nodev,noexec,relatime,cpuacct,cpu)
cgroup on /sys/fs/cgroup/net_cls type cgroup (ro,nosuid,nodev,noexec,relatime,net_cls)
cgroup on /sys/fs/cgroup/freezer type cgroup (ro,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/devices type cgroup (ro,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/cpuset type cgroup (ro,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/perf_event type cgroup (ro,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (ro,nosuid,nodev,noexec,relatime,hugetlb)
mqueue on /dev/mqueue type mqueue (rw,nosuid,nodev,noexec,relatime)
/dev/sda2 on /etc/resolv.conf type xfs (rw,relatime,attr2,inode64,noquota)
/dev/sda2 on /etc/hostname type xfs (rw,relatime,attr2,inode64,noquota)
/dev/sda2 on /etc/hosts type xfs (rw,relatime,attr2,inode64,noquota)
shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k)
/dev/sda2 on /run/secrets type xfs (rw,relatime,attr2,inode64,noquota)
devpts on /dev/console type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
proc on /proc/bus type proc (ro,nosuid,nodev,noexec,relatime)
proc on /proc/fs type proc (ro,nosuid,nodev,noexec,relatime)
proc on /proc/irq type proc (ro,nosuid,nodev,noexec,relatime)
proc on /proc/sys type proc (ro,nosuid,nodev,noexec,relatime)
proc on /proc/sysrq-trigger type proc (ro,nosuid,nodev,noexec,relatime)
tmpfs on /proc/acpi type tmpfs (ro,relatime)
tmpfs on /proc/kcore type tmpfs (rw,nosuid,mode=755)
tmpfs on /proc/timer_list type tmpfs (rw,nosuid,mode=755)
tmpfs on /proc/timer_stats type tmpfs (rw,nosuid,mode=755)
tmpfs on /proc/sched_debug type tmpfs (rw,nosuid,mode=755)
tmpfs on /proc/scsi type tmpfs (ro,relatime)
tmpfs on /sys/firmware type tmpfs (ro,relatime)
ホスト側からは docker ps コマンドで稼働中のコンテナを確認できる。
[root@hostname ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
73230f43d596 centos:latest "/bin/bash" 3 seconds ago Up 2 seconds ecstatic_brattain
exit でコンテナ(bash)を終了すると、docker ps からもあっさり消える。
コンテナが仮想マシンではなく、単なるプロセスであることがよくわかる。
[root@73230f43d596 /]# exit
exit
[root@hostname ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
イメージ中に存在する実行ファイルであれば、何であってもコンテナとして実行可能である。
以下は ps コマンドを実行した例。
自身のプロセスだけしか表示されておらず、コンテナが task_struct 構造体のリンク構造からも隔離されていることがわかる。
[root@hostname ~]# docker run -it centos:latest /bin/ps alx
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
4 0 1 0 20 0 49616 1556 - Rs+ ? 0:00 /bin/ps alx
コンテナは単にプロセスなので、ps コマンドに映る。
[root@hostname ~]# docker run -it centos:latest /bin/sleep 1234
[root@hostname ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
131a35b8006c centos:latest "/bin/sleep 1234" About a minute ago Up About a minute cranky_tesla
[root@hostname ~]# ps alx|grep sleep|grep -v grep
4 0 26912 18475 20 0 221844 12960 ep_pol Sl+ pts/0 0:00 /usr/bin/docker-current run -it centos:latest /bin/sleep 1234
4 0 26956 26939 20 0 4364 360 hrtime Ss+ pts/1 0:00 /bin/sleep 1234
0 0 27076 4818 20 0 107892 620 hrtime S ? 0:00 sleep 60
コンテナは単なるプロセスなので、SIGKILL で死ぬ
[root@hostname ~]# kill -KILL 26956
[root@hostname ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
コンテナのメインプロセスから子プロセスを生成する。
この場合、1コンテナ = nプロセス となる。
コンテナでは PID も隔離されており、ホストとは異なるシリアルで PID が割り振られる。
コンテナ内で生成された子プロセスも、ただのプロセスなので ps に映る。
つまりコンテナ内で生成されたプロセスは、コンテナ内としての PID と、コンテナ外(ホスト)としての PID のふたつをもつ
[root@hostname ~]# docker run -it centos:latest /bin/bash
[root@4c1ca7643ceb /]# sleep 1234 &
[1] 13
[root@4c1ca7643ceb /]# sleep 12345 &
[2] 14
[root@4c1ca7643ceb /]# sleep 123456 &
[3] 15
[root@hostname ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4c1ca7643ceb centos:latest "/bin/bash" 31 seconds ago Up 30 seconds angry_jepsen
[root@hostname ~]# ps alx|grep sleep|grep -v grep
0 0 27451 4818 20 0 107892 616 hrtime S ? 0:00 sleep 60
0 0 27657 27616 20 0 4364 360 hrtime S pts/1 0:00 sleep 1234
0 0 27663 27616 20 0 4364 360 hrtime S pts/1 0:00 sleep 12345
0 0 27665 27616 20 0 4364 356 hrtime S pts/1 0:00 sleep 123456
同じイメージから同じコマンドで生成したコンテナでも、生成するたびに違うコンテナが生成されている。
ホスト名は生成するたびに変わるし、あるコンテナで作成したファイルは別のコンテナからは見えない。
[root@hostname ~]# docker run -it centos:latest /bin/bash
[root@5b5388494463 /]# echo test > test
[root@5b5388494463 /]# cat /test
test
[root@5b5388494463 /]# exit
exit
[root@hostname ~]# docker run -it centos:latest /bin/bash
[root@d213b445f351 /]# cat /test
cat: /test: No such file or directory
コンテナの停止や再起動をしてもファイルシステムのデータは保持される。
docker start -i で interactive モードでコンテナを起動できる。
[root@hostname ~]# docker start 7666ac79ff57 -i
[root@7666ac79ff57 /]# echo test > /test
[root@7666ac79ff57 /]# cat test
test
[root@7666ac79ff57 /]# exit
exit
[root@hostname ~]# docker start 7666ac79ff57 -i
[root@7666ac79ff57 /]# cat test
test
[root@7666ac79ff57 /]# exit
exit
参考
以下を参考にさせていただきました。
https://jp-redhat.com/migration/docker/article.html
https://qiita.com/homines22/items/00eebe3c36a9591c3803