Docker コンテナ内のプロセス監視を考える

# Dockerとは
多くの解説サイトでは、ハードウェアの仮想をしないので、 VMWareやVirtualBoxなどより軽いとあり、ハードウェア的な解説図があるので、似たモノで軽いモノと思っていたが、立ち上げてプロセスを見てみると実は全く概念が違うものではないかと思われる。

### Virtualboxをプロセスを基準に見ると

ホストマシン上で、仮想マシンを起動させ、それぞれnginxとapacheを起動させると

![v1.jpg](https://qiita-image-store.s3.amazonaws.com/0/137052/8ab25992-f0fa-440e-bac2-84868c440e77.jpeg)



上図のような、単純に想像できるような、状態で起動する

### Dockerをプロセス基準に見ると

ホストマシン上で、nginxのコンテナとapacheのコンテナを起動させると
![d1.jpg](https://qiita-image-store.s3.amazonaws.com/0/137052/95378213-cf96-a324-e6b3-339845b7e7a5.jpeg)


上図のように、コンテナに入って見ると、virtualboxの仮想マシンのような状態も確認できるが、ホスト側でプロセスの確認をしてみると、コンテナのみでホストマシン上にはインストールしていないnginxとapacheという名のプロセスが起動しているのが確認できる。

### Dockerfileでコンテナを作成する場合

よくマニュアルを読まずにDockerfileでコンテナを作成した際に、ぶつかってしまったことだが、Dockerのコンテナはフォアグラウンドでのプロセスがあるもののみ、常駐するようになっている。
つまり、常駐プロセスがないコンテナだけのものや、プロセスがデーモン起動するものに関しては、常駐せず、即終了してしまう、これを把握せずに、Dockerfileでコンテナを作成しても、即終了してしまうコンテナになって希望通りのものがつくれない。

### コンテナ内のプロセスを強制終了してみる

- nginxのコンテナに入り、コンテナプロセスをkillしてみる

```shell-session
# nginx1という名前のコンテナにログイン
docker exec -ti nginx1 /bin/bash

# プロセスの確認 
root@78aa948fde09:/# ps ax
#=>  PID TTY      STAT   TIME COMMAND
#=>    1 ?        Ss     0:00 nginx: master process nginx -g daemon off;
#=>    5 ?        S      0:00 nginx: worker process
#=>    6 ?        Ss     0:00 /bin/bash
#=>   10 ?        R+     0:00 ps ax

# プロセスkill
root@78aa948fde09:/# kill -9 1 5

# プロセスの確認
root@78aa948fde09:/# ps ax
#=>  PID TTY      STAT   TIME COMMAND
#=>    1 ?        Ss     0:00 nginx: master process nginx -g daemon off;
#=>    6 ?        Ss     0:00 /bin/bash
#=>   11 ?        S      0:00 nginx: worker process
#=>   12 ?        R+     0:00 ps ax
```
親プロセスはkillできないのか、再起動されるのか、落ちないで起動しつづける

- nginxのコンテナに入り、nginxサービスを停止させる

```shell-session
# nginx1という名前のコンテナにログイン
docker exec -ti nginx1 /bin/bash

# nginxの停止
root@78aa948fde09:/# /usr/sbin/nginx -s stop
```
コンテナをストップしていないにもかかわらず、コンテナが停止してしまう


- ホスト側で、nginxの子プロセスをkillしてみる

ホスト側

```shell-session
# kill前
ps ax|grep nginx
#=> 9809 ?        Ss     0:00 nginx: master process nginx -g daemon off;
#=> 9825 ?        S      0:00 nginx: worker process
#=> 9829 pts/0    R+     0:00 grep --color=auto nginx

# kill
kill -9 9825

# kill後
ps ax|grep nginx
#=> 9809 ?        Ss     0:00 nginx: master process nginx -g daemon off;
#=>16222 ?        S      0:00 nginx: worker process
#=>16224 pts/0    R+     0:00 grep --color=auto nginx
```

コンテナ側

```shell-session
# kill前
root@78aa948fde09:/# ps ax
#=>  PID TTY      STAT   TIME COMMAND
#=>    1 ?        Ss     0:00 nginx: master process nginx -g daemon off;
#=>    5 ?        S      0:00 nginx: worker process
#=>    6 ?        Ss     0:00 /bin/bash
#=>   10 ?        R+     0:00 ps ax

# kill後
root@78aa948fde09:/# ps ax
#=>  PID TTY      STAT   TIME COMMAND
#=>    1 ?        Ss     0:00 nginx: master process nginx -g daemon off;
#=>   11 ?        S      0:00 nginx: worker process
#=>   12 ?        Ss     0:00 /bin/bash
#=>   16 ?        R+     0:00 ps ax
```
プロセスIDより、ホスト側の親プロセスが子プロセスを再起動していることが、わかる

また、コンテナに入り、コンテナ内のプロセスIDを確認しても子プロセスが再起動されていることが、確認できる

- ホスト側で、nginxの親プロセスをkillしてみる

```shell-session
# kill前
# dockerコンテナの確認
#=>docker ps
#=>CONTAINER ID        IMAGE               #=>COMMAND                  CREATED             STATUS              PORTS                         NAMES
#=>78aa948fde09        nginx               "nginx -g 'daemon off"   30 hours ago        Up 58 minutes       443/tcp, 0.0.0.0:81->80/tcp   nginx1

# プロセス確認
ps ax|grep nginx
#=> 9809 ?        Ss     0:00 nginx: master process nginx -g daemon off;
#=>16222 ?        S      0:00 nginx: worker process
#=>16268 pts/0    S+     0:00 grep --color=auto nginx

# kill
kill -9 9809
# kill後
# プロセス確認
ps ax|grep nginx
#=>16289 pts/0    S+     0:00 grep --color=auto nginx

# dockerコンテナの確認
docker ps
#=>CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```

コンテナをストップしていないにもかかわらず、コンテナが停止してしまう


### これらを総合してみると
dockerのコンテナで動かすサービスとは、仮想マシンのようなもの上で稼働していると考えるのではなく、dockerというものでラッピングされたサービスプロセスがホストマシン上で稼働しつつ、dockerプロセスが入出力やポート空間などの管理制御をおこなっているようなものではないかなと、思うべきかもしれない


# Dockerのコンテナ内のプロセス監視

- 一般的な、監視ソフトで、クライアントプロセスが常駐する必要があるもの
  
  Dockerらしい使い方は、1サービス1コンテナなのでサービス以外の監視クライアントプロセスを起動させるのはらしくない

- あえてコンテナ側クライアントプロセスをインストールしたとしても

  Dockerでは一般的にコンテナにipをもたせえないので、完全にクライアントのプッシュ型のみ以外に、サーバー側のプル型の設定が必要なものは使えない

- プッシュ型をコンテナのcronを使って自作して監視をするのは

  一般的なdockerではcronが入ってない(自分でいれてまでするのはdockerらしくない)

つまり、また前段のdockerというもの自体の考え方からして、コンテナ内からプロセスを監視しようとする考え方自体が良くないのではないだろうか

# ホスト側からコンテナ内のサービス監視

- 目的のプロセスを監視する

 前段のように、結局ホストマシン側で動いているプロセスであるので、ホスト側のpsでプロセスチェックが可能ではあるが、同じサービスを別コンテナで起動するような場合(例えばnginxコンテナを複数起動させる)、サービス用プロセスは複数稼働するので、どちらのサービスが落ちたかなどの確認ができなくなる。


- 使用portを監視する

 コンテナと割り当てたホストマシンのポートのみ動いていて、コンテナ内でプロセスのみ落ちるという状況は、前段の検証と考察からないのでこちらで問題ないと思われる


- dockerコマンドでコンテナを確認する

 また、上記のportと同じような意味合いで、カスタムスクリプト監視が可能ならば、docker psコマンドで、dockerのコンテナの稼働状況を確認できるので、コンテナのみ上がりサービスプロセスのみ落ちる状況はありえないので、こちらでも十分だと思われる。

ただし、ここまでで取り上げているプロセス監視については、プロセスの死活監視という意味合いであるので、プロセスは立ち上がっているが、サービスとして稼働できていない状態(ゾンビ状態や高負荷によりサービス不能状態)についての監視については、カスタムスクリプトなどで、実際に接続やリクエストして希望の回答が返ってくるか監視する必要はある

# 結局
上記は、コンテナ知識がまだ浅い時期に書いていたので、ある程度知識感覚をもって考えると、
コンテナとは仮想マシンではなく、プロセスをカプセル化したものなので、コンテナの鉄則である、
「１コンテナ内単一プロセスとする」をしていると、メインプロセスが死んだらコンテナが死ぬので、k8sのようにコンテナ管理してくれるツールでコンテナ管理していると、
コンテナ内のプロセスの死活はコンテナの死活なので管理する必要ない。
なので、やらなくてはいけないのはサービスパフォーマンス監視のみとなるのではないだろうか