Container Technologies

02/29

コンテナ技術は便利なのか

目次

経緯

何かをテストしたいときに仮想化の環境を用意したくて仮想マシンを作ってたんだけど数年前から知人からコンテナ技術が便利と言われてて、実際にdockerを使ってみたんだけど便利なのはわかったんだけどイマイチ使いどころがわからなかった。
本当に今更な感じだけどコンテナ技術のおさらいを。

そもそもコンテナってふぁふぃ?

ではコンテナ技術の基本を勉強する。

仮想化?コンテナ?

仮想化ってなんだっけって自分の感想も交えて紹介する。

仮想化とは - What is a virtualized infrastructure -

ホストマシン上にHypervisorが動いててその上で仮想マシンと呼ばれるプロセスが基本データ+HDDイメージのセットを基に他のプロセスとは別のメモリ空間(一部共有)でゲストOSを仮想的に実現することで、他のデータやメモリ空間に汚染されることなく独立したマシンを構築できる。これが仮想化技術。

ホストOSを汚さずにゲストOSを稼働・停止・コピー・削除ができるので、環境依存のシステムなどを構築しやすい反面、一から環境を構築する必要があるので最初の一歩の敷居が高い。

最近はディスクやネットワークも仮想化されるようになったので、環境自体を立ち上げたり落としたりコピーしたり削除したりが可能になっている。

対してコンテナってのはなんなんだよと。

コンテナとは - What about a container engine -

ホストOS上にコンテナエンジンと呼ばれるプロセスがコンテナイメージと呼ばれるHDDイメージを基に完全に独立したユーザメモリ空間で動く。

あれ?仮想化と一緒じゃん。いや違う。ハードウェアレイヤをエミュレートする仮想化技術とは違い、必要最低限のファイルのみ独立してあとはホストOS側を参照する。要するに他のアプリケーションと同じように動いてくれるので、起動停止が気軽にできる。で、もっと利便性があって環境を横展開することにも長けていてイメージをgithubなどにコミットしておけばいつでも誰でも環境を再現できる。なんかおかしな動きをしたらすぐ停止して最初からやり直しとかもすぐできる。共同開発時の効率が格段にアップする。すぐにスクラップアンドビルドできるこのフットワークの軽さが一番のメリットだと思う。

だが、いいことばかりではなくやはりデメリットもある。それは仮想化との違いからくるところなんだけどコンテナは所詮ホストOSのいろんなところを共有するので攻撃を受けたときの影響範囲が大きい。

このコンテナ技術のSandbox化が不十分という部分が仮想化技術のようにちゃんとゲストがホストからisolatedされているところと違い、コンテナのデメリットだと思う。

結局どっちがええの? - Anyway which is the best tech between VI and CI? -

こうやって考えると、仮想化技術がProduction向きで、コンテナ技術がDevelopment向きだなと。

コンテナ使ってみる

簡単に使ってみる。
環境はDebian GNU/Linux 10.3、根っからのデビアン子。

インストール

以下を実行。

$ sudo apt-get install docker.io

で、バージョンを見てみる。

$ sudo docker version
Client:
 Version:           18.09.1
 API version:       1.39
 Go version:        go1.11.6
 Git commit:        4c52b90
 Built:             Tue, 03 Sep 2019 19:59:35 +0200
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.09.1
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.11.6
  Git commit:       4c52b90
  Built:            Tue Sep  3 17:59:35 2019
  OS/Arch:          linux/amd64
  Experimental:     false

ビルド

では、環境を作ってみる。今回は最終的にDebian+Nginxを簡易的に作ってみた。

$ sudo docker pull debian
Using default tag: latest
latest: Pulling from library/debian
50e431f79093: Pull complete 
Digest: sha256:a63d0b2ecbd723da612abf0a8bdb594ee78f18f691d7dc652ac305a490c9b71a
Status: Downloaded newer image for debian:latest
$

これでDebianコンテナ環境に必要なイメージがダウンロードできた。

余談だが、なんでdockerってroot権限が必要なんだろう。

続いてイメージを使ったコンテナを起動する。

$ sudo docker run -it debian /bin/bash
root@a80b70d93750:/# hostname
a80b70d93750
root@a80b70d93750:/# exit
exit
$ sudo docker run -it debian /bin/bash
root@00ed264bf788:/# hostname
00ed264bf788
root@00ed264bf788:/# exit
exit
$ sudo docker run -it debian /bin/bash
root@cb56a8e79da4:/# hostname
cb56a8e79da4
root@cb56a8e79da4:/# exit
exit
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
cb56a8e79da4        debian              "/bin/bash"         7 seconds ago       Exited (0) 2 seconds ago                        reverent_shtern
00ed264bf788        debian              "/bin/bash"         12 seconds ago      Exited (0) 7 seconds ago                        cocky_lalande
a80b70d93750        debian              "/bin/bash"         25 seconds ago      Exited (0) 13 seconds ago                       dazzling_yalow

毎回違うコンテナが作られる感じ?かな。NAMESってところの名前は何だろうランダム?

CREATEDのところを見ると分かっていただけるかと思うが、イメージ指定してコンテナ起動してbashプロンプトが出るのにほんの数秒でできる。これはすごい。

ただ際限なくコンテナが増えそうなので、いっぺんに削除できないもんだろうか。

$ sudo docker ps -a |grep -v "^CONTAINER ID" |awk '{print $1;}' |while read i;do sudo docker rm $i;done

ちょっと乱暴かな。。。

環境を作りたいときはイメージにコミットしていけば変更したのを保存できる。
まずは自分用のコンテナを起動。

$ sudo docker run -itd --name="myos" debian /bin/bash
$ sudo docker attach myos
root@0b5af8710ec3:/# hostname
0b5af8710ec3
root@0b5af8710ec3:/# ps -ef 
bash: ps: command not found
root@0b5af8710ec3:/# 

myosというコンテナ名でログインしてみた。
psコマンドがないって言ってるので、インストールしてみる。

root@0b5af8710ec3:/# apt-get update
Get:1 http://deb.debian.org/debian buster InRelease [122 kB]
Get:3 http://deb.debian.org/debian buster-updates InRelease [49.3 kB]
Get:2 http://security-cdn.debian.org/debian-security buster/updates InRelease [65.4 kB]
Get:4 http://deb.debian.org/debian buster/main amd64 Packages [7907 kB]
Get:5 http://security-cdn.debian.org/debian-security buster/updates/main amd64 Packages [181 kB]
Get:6 http://deb.debian.org/debian buster-updates/main amd64 Packages [7380 B]
Fetched 8332 kB in 5s (1738 kB/s)                        
Reading package lists... Done
root@0b5af8710ec3:/# apt-get install procps
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libgpm2 libncurses6 libprocps7 lsb-base psmisc
Suggested packages:
  gpm
The following NEW packages will be installed:
  libgpm2 libncurses6 libprocps7 lsb-base procps psmisc
0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
Need to get 612 kB of archives.
After this operation, 1981 kB of additional disk space will be used.
Do you want to continue? [Y/n] 
Get:1 http://deb.debian.org/debian buster/main amd64 libncurses6 amd64 6.1+20181013-2+deb10u2 [102 kB]
Get:2 http://deb.debian.org/debian buster/main amd64 libprocps7 amd64 2:3.3.15-2 [61.7 kB]
Get:3 http://deb.debian.org/debian buster/main amd64 lsb-base all 10.2019051400 [28.4 kB]
Get:4 http://deb.debian.org/debian buster/main amd64 procps amd64 2:3.3.15-2 [259 kB]
Get:5 http://deb.debian.org/debian buster/main amd64 libgpm2 amd64 1.20.7-5 [35.1 kB]
Get:6 http://deb.debian.org/debian buster/main amd64 psmisc amd64 23.2-1 [126 kB]
Fetched 612 kB in 0s (1245 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package libncurses6:amd64.
(Reading database ... 6674 files and directories currently installed.)
Preparing to unpack .../0-libncurses6_6.1+20181013-2+deb10u2_amd64.deb ...
Unpacking libncurses6:amd64 (6.1+20181013-2+deb10u2) ...
Selecting previously unselected package libprocps7:amd64.
Preparing to unpack .../1-libprocps7_2%3a3.3.15-2_amd64.deb ...
Unpacking libprocps7:amd64 (2:3.3.15-2) ...
Selecting previously unselected package lsb-base.
Preparing to unpack .../2-lsb-base_10.2019051400_all.deb ...
Unpacking lsb-base (10.2019051400) ...
Selecting previously unselected package procps.
Preparing to unpack .../3-procps_2%3a3.3.15-2_amd64.deb ...
Unpacking procps (2:3.3.15-2) ...
Selecting previously unselected package libgpm2:amd64.
Preparing to unpack .../4-libgpm2_1.20.7-5_amd64.deb ...
Unpacking libgpm2:amd64 (1.20.7-5) ...
Selecting previously unselected package psmisc.
Preparing to unpack .../5-psmisc_23.2-1_amd64.deb ...
Unpacking psmisc (23.2-1) ...
Setting up lsb-base (10.2019051400) ...
Setting up libgpm2:amd64 (1.20.7-5) ...
Setting up psmisc (23.2-1) ...
Setting up libprocps7:amd64 (2:3.3.15-2) ...
Setting up libncurses6:amd64 (6.1+20181013-2+deb10u2) ...
Setting up procps (2:3.3.15-2) ...
update-alternatives: using /usr/bin/w.procps to provide /usr/bin/w (w) in auto mode
Processing triggers for libc-bin (2.28-10) ...
root@0b5af8710ec3:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 08:36 pts/0    00:00:00 /bin/bash
root       336     1  0 08:41 pts/0    00:00:00 ps -ef
root@0b5af8710ec3:/# 

psコマンドの結果が気持ち悪い。bash以外なにも動いてないなんて。

ここで Ctrl + pCtrl + q をタイプして抜ける。
んでdocker commitで今のカスタマイズをイメージに書き込んでおく。

root@0b5af8710ec3:/# read escape sequence
$ sudo docker commit myos mycustomos
sha256:25bff16f9e71b0a2e2e5bee9f0e2c2173e4721c53bb58d026dfe470fbc4fd891
$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mycustomos          latest              25bff16f9e71        7 seconds ago       134MB
debian              latest              971452c94376        30 minutes ago      114MB
$ sudo docker stop myos
$ sudo docker ps -a |grep -v "^CONTAINER ID" |awk '{print $1;}' |while read i;do sudo docker rm $i;done

確かめてみる。

$ sudo docker run -it debian /bin/bash
root@c1e44abcdda1:/# ps
bash: ps: command not found
root@c1e44abcdda1:/# exit
exit
$ sudo docker run -it mycustomos /bin/bash
root@ec9a70637492:/# ps
  PID TTY          TIME CMD
    1 pts/0    00:00:00 bash
    6 pts/0    00:00:00 ps
root@ec9a70637492:/# exit
exit
$ sudo docker ps -a |grep -v "^CONTAINER ID" |awk '{print $1;}' |while read i;do sudo docker rm $i;done
ec9a70637492
c1e44abcdda1
$ 

正に今こういう記事のときにコマンドサンプルとかをコピペするときとかにも大変重宝する。

で更にもう一歩進めてみる。
事前にコマンドを起動させておくこともできるし、しかもデーモン化できるようだ。
今回は簡便に試してみる。nginxをインストールしてさらにデフォルト設定だけどnginxをTCP80で起動してみる。

$ ss -ltn |grep 80
$ curl http://localhost/
curl: (7) Failed to connect to localhost port 80: 接続を拒否されました
$ sudo docker run -d -p 80:80 mycustomos /bin/bash -c "apt-get update; apt-get -y install nginx ;/usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf"
23a44f360aa72374acc0a0c116ab3b8eaae391d2df3021a101c1a594ac50fa6e
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
23a44f360aa7        mycustomos          "/bin/bash -c 'apt-g…"   35 seconds ago      Up 34 seconds       0.0.0.0:80->80/tcp   lucid_gauss
$ ss -ltn |grep 80
LISTEN    0         128                      *:80                     *:*                      
$ curl http://localhost/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
$ sudo docker stop $(sudo docker ps -a -q) |xargs -ICONTAINER sudo docker rm CONTAINER
23a44f360aa7
$ ss -ltn |grep 80
$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
$ 

若干nginxをインストールしている待ち時間があるのでcurlコマンドが失敗する場合があるけど今回は試しに行っているのでまぁ問題ない。

感想 - what is my impression -

めちゃくちゃ便利。

ちょっとコマンドの使用感やらを試したいときにSandbox的に試せるのが最高。

この年齢になると新しいものを覚えるのは非常に敷居が高いが、覚えてしまえば非常に使い勝手が良いと思う。
サイトのホスティングとかもこれでちゃちゃっとできそうだし。

本当今更知って感動しているっていうね。


コメント: