LoginSignup
170
212

More than 1 year has passed since last update.

Docker ノウハウ集

Last updated at Posted at 2016-11-19

#1. ホスト版数、Docker版数

[root@master1 ~]# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)

[root@master1 ~]# docker -v
Docker version 1.10.3, build cb079f6-unsupported

#2. 基本編
##2.1 Dockerコマンドのヘルプの使い方

dockerコマンドに--helpを指定する。attach等のサブコマンド一覧が表示される。
[root@master1 ~]# docker --help
-中略-
Commands:
    attach    Attach to a running container
    build     Build an image from a Dockerfile
以下、略


サブコマンドに--helpを指定する。
[root@master1 ~]# docker attach --help

Usage:  docker attach [OPTIONS] CONTAINER

Attach to a running container

  --detach-keys       Override the key sequence for detaching a container
  --help              Print usage
  --no-stdin          Do not attach STDIN
  --sig-proxy=true    Proxy all received signals to the process
[root@master1 ~]#

networkサブコマンドは、networkサブコマンドの下に、さらにサブコマンドがある。
[root@master1 ~]# docker network ls --help

Usage:  docker network ls [OPTIONS]

Lists networks

  -f, --filter=[]    Filter output based on conditions provided
  --help             Print usage
  --no-trunc         Do not truncate the output
  -q, --quiet        Only display numeric IDs
[root@master1 ~]#

#3. 応用編
##3.1 Dockerレジストリを使う(イメージのアップロード/ダウンロード)


------------------------------------------------------
1. 設定ファイル編集(/etc/sysconfig/docker)
------------------------------------------------------
定義ファイルを編集する。
[root@master1 ~]# vi /etc/sysconfig/docker

【変更前】
INSECURE_REGISTRY='--insecure-registry'

【変更後】
INSECURE_REGISTRY='--insecure-registry master1:12345'

  --insecure-registry <ホスト名>:<TCPポート番号>

   ホスト名:dockerデーモンが動作しているホスト名を指定する。
             /etc/hostsに定義されている名前を指定する。
   ポート番号:ホストのTCPポート番号を指定する。
              既存ポート番号と重複しないように選択する。


設定変更したらdockerを再起動する。
[root@master1 ~]# systemctl restart docker


------------------------------------------------------
2. Dockerレジストリを準備する
------------------------------------------------------
Dockerレジストリのイメージをダウンロードする。
[root@master1 ~]# docker pull registry:2.4.1
Trying to pull repository docker.io/library/registry ...
2.4.1: Pulling from docker.io/library/registry
-以下、略-

Dockerレジストリを起動する。
[root@master1 ~]# docker run -d -p 12345:5000 --name test-registry registry:2.4.1
894bcb0a2a4830013991ac827315ff7287d623d1031dc32e1d4848ccf93f013f

Dockerレジストリの状態を確認する。
[root@master1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
894bcb0a2a48        registry:2.4.1      "/bin/registry serve "   7 seconds ago       Up 4 seconds        0.0.0.0:12345->5000/tcp   test-registry


------------------------------------------------------
3. Dockerレジストにイメージをアップロードする
------------------------------------------------------
テスト用イメージをダウンロードする。イメージサイズが小さいbusyboxを使う。
[root@master1 ~]# docker pull busybox
Using default tag: latest
Trying to pull repository docker.io/library/busybox ...
-以下、略-

イメージにtag付けをする
[root@master1 ~]# docker tag busybox master1:12345/hana_shin/busybox:ver1

イメージを確認する。
[root@master1 ~]# docker images |grep busybox
docker.io/busybox                            latest            e02e811dd08f        8 weeks ago         1.093 MB
master1:12345/hana_shin/busybox              ver1              e02e811dd08f        8 weeks ago         1.093 MB

イメージをアップロードする。
[root@master1 ~]# docker push master1:12345/hana_shin/busybox:ver1
The push refers to a repository [master1:12345/hana_shin/busybox]
e88b3f82283b: Pushed
ver1: digest: sha256:9393222c6789842b16bcf7306b6eb4b486d81a48d3b8b8f206589b5d1d5a6101 size: 505


-------------------------------------------------------------
4. アップロードしたイメージを確認する。
-------------------------------------------------------------
Dockerレジストリに登録したイメージを確認する。
[root@master1 ~]# curl http://localhost:12345/v2/_catalog
{"repositories":["hana_shin/busybox"]}

tagを取得する。
[root@master1 ~]# curl http://localhost:12345/v2/hana_shin/busybox/tags/list
{"name":"hana_shin/busybox","tags":["ver1"]}


-------------------------------------------------------------
5. Dockerレジストリからイメージをダウンロードする。
-------------------------------------------------------------
ホスト側のイメージを削除する。
[root@master1 ~]# docker images |grep busybox
docker.io/busybox                                     latest                             e02e811dd08f        8 weeks ago         1.093 MB
master1:12345/hana_shin/busybox                       ver1                               e02e811dd08f        8 weeks ago         1.093 MB
[root@master1 ~]# docker rmi -f e02e811dd08f
Untagged: docker.io/busybox:latest
Untagged: master1:12345/hana_shin/busybox:ver1
Deleted: sha256:e02e811dd08fd49e7f6032625495118e63f597eb150403d02e3238af1df240ba
Deleted: sha256:e88b3f82283bc59d5e0df427c824e9f95557e661fcb0ea15fb0fb6f97760f9d9

busyboxのイメージを確認する。削除できたことがわかる。
[root@master1 ~]# docker images |grep busybox
[root@master1 ~]#

Dockerレジストリからイメージをダウンロードする。
[root@master1 ~]# docker pull master1:12345/hana_shin/busybox:ver1
Trying to pull repository master1:12345/hana_shin/busybox ...
ver1: Pulling from master1:12345/hana_shin/busybox
56bec22e3559: Pull complete
Digest: sha256:9393222c6789842b16bcf7306b6eb4b486d81a48d3b8b8f206589b5d1d5a6101
Status: Downloaded newer image for master1:12345/hana_shin/busybox:ver1

イメージを確認する。Dockerレジストリからイメージをpullできたことがわかる。
[root@master1 ~]# docker images |grep busybox
master1:12345/hana_shin/busybox                       ver1                               e02e811dd08f        8 weeks ago         1.093 MB


-------------------------------------------------------------
6. dockerコマンドのパラメータの説明
-------------------------------------------------------------
docker run -d -p 12345:5000 --name test-registry registry
            A      A            A                  A
            |      |            |                  +--- イメージの名前を指定する。
            |      |            +---------------------- コンテナの名前を指定する。任意の名前でOK
            |      +----------------------------------- ホスト側TCPポート番号(12345)をコンテナのポート番号(5000)に対応付けする。
            +------------------------------------------ コンテナをバックグラウンドで動かすための指定


docker tag busybox localhost:12345/test/busybox:ver1
             A       A         A     A    A      A
             |       |         |     |    |      +------ tag名
             |       |         |     |    +------------- イメージ名
             |       |         |     +------------------ リポジトリ名
             |       |         +------------------------ ホストのTCPポート番号(ホストとはDockerサーバが動作しているサーバのIPアドレスです)
             |       +---------------------------------- ホストのIPアドレス
             +------------------------------------------ 元のイメージの名前

##3.2 ホストからコンテナへのルーティング(2の続き)

registryサーバを起動すると、DNATテーブルが作られます。DNATの変換ルールの意味は次のとおり。
ホストの任意(0.0.0.0)のインタフェースに到着したIPパケットで宛先TCPポート番号が12345のパケットは、
宛先IPアドレスを172.17.0.2,宛先ポート番号を5000に変換する。
[root@master1 ~]# iptables -L -t nat -n |grep -B3 12345
Chain DOCKER (2 references)
target     prot opt source               destination
RETURN     all  --  0.0.0.0/0            0.0.0.0/0
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:12345 to:172.17.0.2:5000


コンテナにログインしてIPアドレスを調べる。コンテナのIPアドレスは"172.17.0.2"であることがわかる。
[root@master1 ~]# docker exec -it test-registry sh
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
20: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link
       valid_lft forever preferred_lft forever
/ #

コンテナのプロセスが使用しているポート番号を調べる。
/ # netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 :::5000                 :::*                    LISTEN      1/registry
/ #

さらにもう1つregistryサーバを起動したときのホストの様子を以下に示します。

[root@master1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
467b1628f13b        registry            "/entrypoint.sh /etc/"   30 minutes ago      Up 30 minutes       0.0.0.0:22222->5000/tcp   test2-registry
b00c90063f16        registry            "/entrypoint.sh /etc/"   3 hours ago         Up 33 minutes       0.0.0.0:12345->5000/tcp   test-registry

[root@master1 ~]# iptables -L -t nat -n |grep -e 12345 -e 22222
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:12345 to:172.17.0.2:5000
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22222 to:172.17.0.3:5000

docker0はブリッジです。containerは起動すると、このブリッジに接続されます。
ブリッジにはポートが割り当てられます。container1とvethXXX,container2とvethYYYがそれぞれつながっています。


 +---------- Host(CentOS7.2)-------------+
 |                                       |
 |  +- container1 -+   +- container2 -+  |
 |  |              |   |              |  |
 |  |   port=5000  |   |   port=5000  |  |
 |  |              |   |              |  |
 |  +---- eth0 ----+   +---- eth0 - --+  |   -*-
 |    A    | .2               | .3  A    |    |
 |    |    |                  |     |    | 172.16.0.0/16のサブネット
 |  +-|- vethXXX --------- vethYYY -|-+  |    |
 |  | |    docker0(172.17.0.1/16)   | |  |    |
 |  +-|-----------------------------|-+  |   -*-
 |    |              |              |    |
 |    +----+         |          +---+    |
 |         |         |          |        |
 |  +------|--------------------|-----+  |
 |  |      |       Routing      |     | ========> +----------------------------------------------------------------------------------------+
 |  +------|--------------------|-----+  |        |【ルーティングテーブル】宛先IPアドレスより、出力するデバイス(eth0,dcoker0)を決める            |
 |         |         |          |        |        | [root@master1 ~]# route -n                                                             |
 |  port=12345       |      port=22222   |        | Kernel IP routing table                                                                |
 |         |         |          |        |        | Destination     Gateway         Genmask         Flags Metric Ref    Use Iface          |
 +----- eth0 (192.168.0.10/24) -|--------+        | 0.0.0.0         192.168.0.1     0.0.0.0         UG    100    0        0 eth0           |
           |         |          |                 | 172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0        |
                     |                            | 192.168.0.0     0.0.0.0         255.255.255.0   U     100    0        0 eth0           |
                     |                            +----------------------------------------------------------------------------------------+



##3.3 コンテナIDからプロセスIDを求める方法

コンテナを起動する。
[root@master1 ~]# docker run -it --name test-con centos:centos7 bash

別ターミナルを起動して、コンテナIDを求める
[root@master1 ~]# CID=$(docker ps --no-trunc=true|grep "test-con"|awk '{print $1}')

コンテナIDを確認する。
[root@master1 ~]# echo $CID
22914bed7a73ee10382d23a1066dfb3ec94e44de0390af087ccfb4b2b751384b

PIDを求める。
[root@master1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

PIDを確認する。
[root@master1 ~]# echo $PID
2857

##3.4 コンテナがホストのディレクトリをマウントする方法

-------------------------------------------------------------
1. マウントするディレクトリを明示的に指定する方法(-vオプション)
-------------------------------------------------------------

マウントするディレクトリに"svirt_sandbox_file_t"というSElinuxのタイプを設定する。
[root@master1 ~]# ls -ldZ registry/
drwxr-xr-x. root root unconfined_u:object_r:admin_home_t:s0 registry/
[root@master1 ~]# chcon -Rt svirt_sandbox_file_t registry
[root@master1 ~]# ls -ldZ registry/
drwxr-xr-x. root root unconfined_u:object_r:svirt_sandbox_file_t:s0 registry/

コンテナを起動する。
[root@master1 ~]# docker run -it -v $HOME/registry:/var/lib/registry --name test centos:centos7 bash


マウントしたディレクトリにファイルを作成する。
[root@08497e222b5e /]# touch /var/lib/registry/test.txt
[root@08497e222b5e /]# echo "This is container" > /var/lib/registry/test.txt
[root@08497e222b5e /]# cat /var/lib/registry/test.txt
This is container


別ターミナルで作成したファイルの中身を確認する。コンテナで作成したファイルの中身が確認できた。
[root@master1 ~]# pwd
/root
[root@master1 ~]# cat registry/test.txt
This is container


-------------------------------------------------------------
2. マウントするディレクトを明示的に指定しない方法。
-------------------------------------------------------------

この場合、コンテナはホストの/var/lib/docker/volumes配下のディレクトリをマウントします。


--------------------------------------------------------------------------------------
2.1 DockerfileでVOLUMEを指定する方法
--------------------------------------------------------------------------------------
Dockerfileを作成する。
[root@master1 ~]# vi Dockerfile
[root@master1 ~]# cat Dockerfile
FROM centos:centos7
VOLUME /root/dir01
VOLUME /root/dir02

イメージをビルドする。
[root@master1 ~]# docker build -t test-image:v1 .
Sending build context to Docker daemon  84.3 MB
Step 1 : FROM centos:centos7
 ---> 0584b3d2cf6d
Step 2 : VOLUME /root/dir01
 ---> Using cache
 ---> 226d9d64338d
Step 3 : VOLUME /root/dir02
 ---> Using cache
 ---> 6584f874444e
Successfully built 6584f874444e
[root@master1 ~]#

コンテナを起動する。
[root@master1 ~]# docker run -itd --name test-con test-image:v1
45f6382fd50f21361a911080bf1a3e5d8b91781df0677f6d63ebca5fb334cb64

コンテナの状態を確認する。
[root@master1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
45f6382fd50f        test-image:v1       "/bin/bash"         26 seconds ago      Up 24 seconds                           test-con

jqコマンドがのインストール
[root@master1 ~]# yum -y install jq

ホスト側ディレクトリを確認する。/var/lib/docker/volumes配下(★印)にマッピングされていることがわかる。
[root@master1 ~]# docker inspect test-con | jq .|less

-中略-
    "Mounts": [
      {
        "Name": "d7b8625f00b37f7648fbb5b7d92e1204c7d5b4b2c314051208929080e2d3d82d",
      ★"Source": "/var/lib/docker/volumes/d7b8625f00b37f7648fbb5b7d92e1204c7d5b4b2c314051208929080e2d3d82d/_data",
        "Destination": "/root/dir01",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
      },
      {
        "Name": "761db694fb793079933981ce9094920c1814f964eba4635bf292e1a038a8f428",
      ★"Source": "/var/lib/docker/volumes/761db694fb793079933981ce9094920c1814f964eba4635bf292e1a038a8f428/_data",
        "Destination": "/root/dir02",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
      }
    ],
以下、略


コンテナのbashに接続する。
[root@master1 ~]# docker exec -it test-con bash

VOLUMEで指定したディレクトが作成されていることを確認する。
[root@45f6382fd50f /]# cd /root/
[root@45f6382fd50f ~]# ls
anaconda-ks.cfg  dir01  dir02


dir01配下にファイル(file01)を作成する
[root@45f6382fd50f ~]# cd dir01/
[root@45f6382fd50f dir01]# touch file01
[root@45f6382fd50f dir01]# echo "This is file01" > file01
[root@45f6382fd50f dir01]# cat file01
This is file01


作成したファイルの中身をホスト側で確認する。もう1つターミナルを起動する。
コンテナで書いたファイルの内容がホストで読めた。
[root@master1 ~]# cat /var/lib/docker/volumes/d7b8625f00b37f7648fbb5b7d92e1204c7d5b4b2c314051208929080e2d3d82d/_data/file01
This is file01


--------------------------------------------------------------------------------------
2.2. docker run実行時に指定する方法.  確認方法は2.1を参考にしてください。
--------------------------------------------------------------------------------------
[root@master1 ~]# docker run -it --rm -v /root/dir01 -v /root/dir02 centos:centos7 bash
[root@0e646e283a53 /]# cd root/
[root@0e646e283a53 ~]# ls
anaconda-ks.cfg  dir01  dir02
[root@0e646e283a53 ~]#


##3.5 ホストのディレクトリをリードオンリー(roオプション)でマウントする。

コンテナでマウントするディレクトリを作成する。
[root@master1 ~]# mkdir /hostdir
[root@master1 ~]# chcon -Rt svirt_sandbox_file_t /hostdir
[root@master1 ~]# ls -ldZ /hostdir
drwxr-xr-x. root root unconfined_u:object_r:svirt_sandbox_file_t:s0 /hostdir

ホストのディレクトリをリードオンリー(roオプション)でマウントする。エラーが発生してファイルの作成ができない。
[root@master1 ~]# docker run -it -v /hostdir:/tmp:ro busybox sh
/ # echo "This is container" > /tmp/test.txt
sh: can't create /tmp/test.txt: Read-only file system
/ # exit

今度は、書き込み可でマウントする。コンテナでファイルを作成することができた。
[root@master1 ~]# docker run -it -v /hostdir:/tmp busybox sh
/ # echo "This is container" > /tmp/test.txt
/ # exit
[root@master1 ~]# cat /hostdir/test.txt
This is container
[root@master1 ~]#

##3.6 データ保存専用コンテナの作成方法

data_conコンテナの/data_dirに対して、conコンテナからファイルの読み書きをする。

    conコンテナ                data_conコンテナ(データ保存専用)
                 -------->     /data_dir
                read/write


データ保存専用コンテナを起動する。-vオプションを使って、/data_dirを他コンテナから参照できるようにする。
[root@master1 ~]# docker run -it -v /data_dir --name data_con busybox sh
/ # ls /data_dir/
/ # echo "This is data-container" > /data_dir/data.txt
/ # exit

もう1つコンテナを起動する。データ保存専用コンテナに保存した
[root@master1 ~]# docker run -it --volumes-from data_con --name con busybox sh
/ # cat /data_dir/data.txt
This is data-container
/ # exit


##3.7 同一ホストでnginxコンテナを複数起動する。

ホストのTCPポート番号11111をコンテナのポート番号80にマップする。
[root@master1 ~]# docker run -d -p 11111:80 --name web1 nginx
498c3d59429b7756d63a83cbd8285f68a0a6a4470227fa58cc62c3f1cf682164

ホストのTCPポート番号22222をコンテナのポート番号80にマップする。
[root@master1 ~]# docker run -d -p 22222:80 --name web2 nginx
cc5d925c88ca18542931dba346f0ae011cd414f7aad3d00fc95172e4d7fc6d69

コンテナを確認する。それぞれ、11111->80,22222->80 にマップされていることがわかる。
[root@master1 ~]# docker ps |grep -e web1 -e web2
cc5d925c88ca        nginx               "nginx -g 'daemon off"   15 seconds ago      Up 13 seconds       443/tcp, 0.0.0.0:22222->80/tcp   web2
498c3d59429b        nginx               "nginx -g 'daemon off"   26 seconds ago      Up 23 seconds       443/tcp, 0.0.0.0:11111->80/tcp   web1

[root@master1 ~]# curl http://localhost:11111
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
以下、略

[root@master1 ~]# curl http://localhost:22222
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
以下、略

[root@master1 ~]# docker rm -f web1 web2
web1
web2
[root@master1 ~]#


##3.8 コンテナが動作するCPUを指定する方法(--cpuset-cpusオプション)


----------------------------------------------------
1. ddコマンドでCPU負荷をかける
----------------------------------------------------
コンテナがどのCPUで動いているかを確認するため、htopパッケージをインストールする。
[root@master1 ~]# yum -y install epel-release
[root@master1 ~]# yum -y install htop

ホストのCPUを確認する。CPUが4個あることがわかる。
[root@master1 ~]# cat /proc/cpuinfo |grep processor
processor       : 0
processor       : 1
processor       : 2
processor       : 3
[root@master1 ~]#


CPU=0でコンテナを動かす。--cpuset-cpusに0を指定する。
[root@master1 ~]# docker run -it -d --name con0 --cpuset-cpus=0 busybox dd if=/dev/zero of=/dev/null
06ef3f9b7cd70b3b2e0df2917aaef8702491e34f9019ee0361266e86081d0a42

コンテナがどのCPUで動いているかの確認方法の説明。
htopの画像を張り付けて説明したいけど、貼り付けつけ方がわからないので、言葉で説明する。

1. htopを起動する。
[root@master1 ~]# htop

2. F2キーを押下する。画面が切り替わる。
3. ↑↓キーを操作して、"Setup"列の"Columns"にカーソルを合わせ、Enterキーを押下する。
4. <-->キーを選択して、右端の"Available Columens"列にカーソルを移動する。
5. "Available Columens"列の"PROCESSOR"という項目にカーソルを移動してEnterキーを押下する。
6. F5キーを押下する。"PROCESSOR"項目を表示項目に追加する。
7. F10キーを押下して、設定を保存する。
8. 画面が切り替わる。プロセス一覧が表示される。"CPU"列が追加されている。
9. ddプロセスを検索するためF3キーを押下する。続けて、"dd"と入力する。
10. ddプロセスが画面の一番上に表示される。
11. ddコマンドが動作しているCPU番号を確認する。CPU=0で動いていることが確認できる。

CPU番号の数え方が、ホストとhtopでは異なるので(ホストは0,1,..htopは1,2..)、
ホストに合わせる場合は"Display options" -> "Count CPUs from 0 instead of 1"を選択する。
htopでもCPU番号が0,1,2...と表示されるようになる。


他にも、以下のようにCPU番号を変化させて、htopで確認する。指定したCPUでコンテナが動いていることが確認できる。
[root@master1 ~]# docker run -it -d --name con1 --cpuset-cpus=1 busybox dd if=/dev/zero of=/dev/null
[root@master1 ~]# docker run -it -d --name con2 --cpuset-cpus=2 busybox dd if=/dev/zero of=/dev/null
[root@master1 ~]# docker run -it -d --name con3 --cpuset-cpus=3 busybox dd if=/dev/zero of=/dev/null


----------------------------------------------------
2. opensslコマンドでCPU負荷をかける
----------------------------------------------------
[root@master1 ~]# vi Dockerfile
[root@master1 ~]# cat Dockerfile
FROM centos:centos7
ENV container docker
RUN yum -y install openssl && yum clean all
[root@master1 ~]#


イメージをビルドする。
[root@master1 ~]# docker build -t test --no-cache=true .
Sending build context to Docker daemon 84.29 MB
Step 1 : FROM centos:centos7
 ---> 0584b3d2cf6d
Step 2 : ENV container docker
 ---> Running in f75f52ceffb5
 ---> 49803a7122bf
Removing intermediate container f75f52ceffb5
Step 3 : RUN yum -y install openssl && yum clean all
 ---> Running in 3cae1e4c3680
以下、略


[root@master1 ~]# docker run -it -d --name cpuload --cpuset-cpus=0-1 test /usr/bin/openssl speed -multi 2
7cc24954486249466f4c8f31586ae73a34be7eb0eee5c9155d88df0f4aa61115
[root@master1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
7cc249544862        test                "/usr/bin/openssl spe"   4 seconds ago       Up 2 seconds                            cpuload
[root@master1 ~]#


htopを起動する。
[root@master1 ~]# htop

CPU=0,1でopensslコマンドの使用率が100%になっていることがわかる。


今度は、CPU0とCPU3でopensslコマンドを実行する。
[root@master1 ~]# docker run -it -d --name cpuload --cpuset-cpus=0,3 test /usr/bin/openssl speed -multi 2
041d17acb164c629ac9d1d8052439961c8881b7d124e57268214abeffb3e066c
[root@master1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
041d17acb164        test                "/usr/bin/openssl spe"   6 seconds ago       Up 3 seconds                            cpuload
[root@master1 ~]#

htopを起動する。
[root@master1 ~]# htop

CPU0とCPU3でopensslコマンドの使用率が100%になっていることがわかる。

##3.9 コンテナが動作するCPUの確認方法

コンテナを起動する。
[root@master1 ~]# docker run -it --rm --name test-con1 centos:centos7 bash
[root@0b9b40152ac4 /]#

コンテナIDを取得する。
[root@master1 ~]# CID=$(docker ps -a --no-trunc=true |grep test-con1 | awk '{print $1}')

コンテナIDを確認する。
[root@master1 ~]# echo $CID
0b9b40152ac4377080bb77ba8fca267d1c4cf11cb2d6314f3ad8ac064efe5b35

コンテナが動作するCPUを確認する。CPU=0,1,2,3で動く設定であることがわかる。
[root@master1 ~]# cat /sys/fs/cgroup/cpuset/system.slice/docker-${CID}.scope/cpuset.cpus
0-3


コンテナを起動する。コンテナはCPU=0で動く設定。
[root@master1 ~]# docker run -it --rm --cpuset-cpus=0 --name test-con1 centos:centos7 bash
[root@923a81f60736 /]#

コンテナIDを取得する。
[root@master1 ~]# CID=$(docker ps -a --no-trunc=true |grep "test-con1" | awk '{print $1}')

コンテナIDを確認する。
[root@master1 ~]# echo $CID
923a81f60736846eaf10627fe8408173180e08163f285252f1cb5b6a52730608

コンテナが動作するCPUを確認する。CPU=0で動く設定であることがわかる。
[root@master1 ~]# cat /sys/fs/cgroup/cpuset/system.slice/docker-${CID}.scope/cpuset.cpus
0

##3.10 コンテナが使うCPU割り当て時間指定する(--cpu--sharesオプション)

コンテナを3つ起動する。CPU割り当て時間を1024:1024:1024の割合で割り当てる。
[root@master1 ~]# docker run -it -d --name con0 --cpuset-cpus=0 --cpu-shares=1024  busybox dd if=/dev/zero of=/dev/null
b0d0b5c19b2504066b5b78c908fc5e7bb2cba44efacb3c334dd093986f354956
[root@master1 ~]# docker run -it -d --name con1 --cpuset-cpus=0 --cpu-shares=1024  busybox dd if=/dev/zero of=/dev/null
d61db7e92a491934a80168580b2a6f3fa2941ce3984b822e8b65916a1e7f602a
[root@master1 ~]# docker run -it -d --name con3 --cpuset-cpus=0 --cpu-shares=1024  busybox dd if=/dev/zero of=/dev/null
64d2d6c2dde6bd2ea4b3b1e98fa4a205290d3fcb024f4d0254b85a5f343c7c3b
[root@master1 ~]#

htopを起動する。
[root@master1 ~]# htop


CPU=0でddプロセスが3つ動いていることが確認できる。
その時の各プロセスのCPU使用率が33%前後になっている。

-------------------------------------------------------------------------
今度は--cpu-shares=128を指定する。
[root@master1 ~]# docker run -it -d --name con0 --cpuset-cpus=0 --cpu-shares=128  busybox dd if=/dev/zero of=/dev/null
96e2a54cdd306b39e04cdbd16e5b9a013e8109197c6f9966aedba6dd6620286f
[root@master1 ~]# docker run -it -d --name con1 --cpuset-cpus=0 --cpu-shares=128  busybox dd if=/dev/zero of=/dev/null
ed1fbce1deb59563ca327a740bb7ef02bb665d6dc7c432539bdfc2c2feef8c48
[root@master1 ~]# docker run -it -d --name con2 --cpuset-cpus=0 --cpu-shares=128  busybox dd if=/dev/zero of=/dev/null
591136e723f0ff2371ae127721924423fc2337b7d856240d1578ab715d7b5752
[root@master1 ~]#

htopを起動する。
[root@master1 ~]# htop

CPU=0でddプロセスが3つ動いていることが確認できる。
--cpu-shares=128と指定した場合でも、各プロセスのCPU使用率が33%前後になっている。



-------------------------------------------------------------------------
今度は、--cpu-sharesを128:128:256に指定する。
[root@master1 ~]# docker run -it -d --name con1 --cpuset-cpus=0 --cpu-shares=128  busybox dd if=/dev/zero of=/dev/null
f1e0c7a0ebfb51502eab81f9d4138f290d8edfffce466c15dc02395e935a5a61
[root@master1 ~]# docker run -it -d --name con2 --cpuset-cpus=0 --cpu-shares=128  busybox dd if=/dev/zero of=/dev/null
f0515a66cb18af7f88affa944567b557fc5ebaf5b8a23e7909de1b44e485f33d
[root@master1 ~]# docker run -it -d --name con3 --cpuset-cpus=0 --cpu-shares=256  busybox dd if=/dev/zero of=/dev/null
bf35847b04244840d2fdc69107bc37366b612269a6cb090a481dc12c1662aa19

htopを起動する。
[root@master1 ~]# htop

CPU=0でddプロセスが3つ動いていることが確認できる。
CPU使用率を確認すると、con1:con2:con3が1:1:2の割合になった。

##3.11 コンテナが出力するログをsyslogやjournaldに出力する(--log-driverオプション)


-----------------------------------------------------------
1. コンテナ単位で有効にする方法
-----------------------------------------------------------
[root@master1 ~]# docker pull centos:centos7
[root@master1 ~]# docker run --log-driver=syslog centos:centos7 echo 'bbbbbbbbbb'

[root@master1 ~]# grep bbbbbbbbbb /var/log/messages
-中略-
Nov 20 22:23:47 master1 docker-current/978df20ce856[1037]: bbbbbbbbbb


毎回起動時にパラメータを指定するのは面倒なので、設定ファイルにsyslogへのログ出力を指定する。
[root@master1 ~]# vi /etc/sysconfig/docker
-中略-
DOCKER_OPTS="--log-driver syslog"

[root@master1 ~]# systemctl restart docker
[root@master1 ~]# docker run centos:centos7 echo 'cccccccccc'
cccccccccc

[root@master1 ~]# grep cccccccccc /var/log/messages
Nov 20 22:27:47 master1 journal: cccccccccc


-----------------------------------------------------------
2. 全てのコンテナで有効にする
-----------------------------------------------------------
[root@master1 ~]# vi /etc/sysconfig/docker
DOCKER_OPTS="--log driver syslog"

[root@master1 ~]# systemctl restart docker

##3.12 コンテナが使うメモリ量に制限をかける(-mオプション)

コンテナが使うメモリ量を256Mに制限する。
[root@master1 ~]# docker run -it -m 256m --name memload centos:centos7 bash
[root@f020e33fb040 /]#

下記コマンドを実行する。
[root@af2e80e36842 /]# /dev/null < $(yes)

htopを起動する。
[root@master1 ~]# htop

メモリが256M近くまで消費するのを繰り返したあと、bashがkillされる。
[root@f020e33fb040 /]# /dev/null < $(yes)
Killed

##3.13 コンテナが使うfd(ファイルディスクリプタ)数に制限をかける(--ulimitオプションを使う)

オプションを指定せず、コンテナを起動する。
[root@master1 test2]# docker run -it --rm centos:centos7 bash

デフォルトのfd数は1048576であることがわかる。
[root@290563aa925e /]# ulimit -n
1048576

コンテナを起動する。fd数が512に制限されていることがわかる。
[root@master1 test2]# docker run -it --rm --ulimit="nofile=512" centos:centos7 bash
[root@master1 test2]# docker run -it --rm --ulimit="nofile=512" centos:centos7 bash
[root@2621ef057b15 /]# ulimit -n
512

コンテナを起動する。fd数が1024に制限されていることがわかる。
[root@master1 test2]# docker run -it --rm --ulimit="nofile=1024" centos:centos7 bash
[root@38c6f57b1af8 /]# ulimit -n
1024

##3.14 コンテナのイメージを削除するスクリプト

これから作成するスクリプト(rmcon)が存在しないことを確認する。
[root@master1 ~]# which rmcon
/usr/bin/which: no rmcon in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)

[root@master1 ~]# touch /usr/local/bin/rmcon
[root@master1 ~]# chmod 744 /usr/local/bin/rmcon
[root@master1 ~]# vi /usr/local/bin/rmcon
[root@master1 ~]# cat /usr/local/bin/rmcon
#!/usr/bin/bash
docker rm $(docker ps -qa)


[root@master1 ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
54851f2549eb        nginx               "nginx -g 'daemon off"   14 seconds ago      Exited (0) 10 seconds ago                       test

自作スクリプトを実行する。イメージが削除できたことがわかる。
[root@master1 ~]# rmcon
54851f2549eb
[root@master1 ~]#

##3.15 dockerブリッジを流れるパケットを見る。

コンテナ起動前のDNAT定義を確認する。ポート番号11111,22222宛は定義されていない。
[root@master1 ~]# iptables -L -t nat -n |grep -e 11111 -e 22222
[root@master1 ~]#


80番ポートで待つコンテナを2つ起動する。それぞれのホスト側ポート番号は11111,22222
[root@master1 ~]# docker run -d --name nginx1 -p 11111:80 nginx
[root@master1 ~]# docker run -d --name nginx2 -p 22222:80 nginx


コンテナを起動すると、DNATの定義は以下のようになる。
[root@master1 ~]# iptables -L -t nat -n |grep -e 11111 -e 22222
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:11111 to:172.17.0.2:80
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:22222 to:172.17.0.3:80



コンテナを起動したときのホスト内のネットワークは以下のようになる。

  +--- nginx1 ---+   +--- nginx2 ---+
  |    port=80   |   |    port=80   |
  |              |   |              |
  +---- eth0 ----+   +---- eth0 ----+
      172.17.0.2        172.17.0.3
          |  A               |   A
          |  |               |   |
  +-------+--|---------------+---|--+
  |          |  docker0(Bridge)  |  | <=== tcpdump -i docker0 tcp port 80 -nn
  +----------|-------+-----------|--+
             |       |           |
             |       |           |
 [after]     |       |           | [after]
   DstIP=172.17.0.2  |           |   DstIP=172.17.0.3
   DstPort=80        |           |   DstPort=80
             |       |           |
 +-------------------------- DNAT -----------------------------------------------+
 |  [root@master1 ~]# iptables -L -t nat -n |grep -e 11111 -e 22222              |
 |  DNAT   tcp  --  0.0.0.0/0      0.0.0.0/0     tcp dpt:11111 to:172.17.0.2:80  |
 |  DNAT   tcp  --  0.0.0.0/0      0.0.0.0/0     tcp dpt:22222 to:172.17.0.3:80  |
 +-------------------------------------------------------------------------------+
                     |
            eth0(192.168.0.10/24)
              A                A
              |                |
              |                |
  [before]    |                | [before]
     DstIP=192.168.0.10        |   DstIP=192.168.0.10
     DstPort=11111             |   DstPort=22222


tcpdumpを起動する。
[root@master1 ~]# tcpdump -i docker0 tcp port 80 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on docker0, link-type EN10MB (Ethernet), capture size 65535 bytes


別のターミナルでNginxにcurlコマンドでアクセスする。
[root@master1 ~]# curl http://192.168.0.10:11111
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

この時、tcpdumpで採取したパケットは以下のとおり。TCPコネクション確立時のみ抜粋
21:12:08.660096 IP 192.168.0.10.57391 > 172.17.0.2.80: Flags [S], seq 1382156843, win 43690, options [mss 65495,sackOK,TS val 5452241 ecr 0,nop,wscale 7], length 0
21:12:08.660252 IP 172.17.0.2.80 > 192.168.0.10.57391: Flags [S.], seq 3030911224, ack 1382156844, win 14480, options [mss 1460,sackOK,TS val 5452241 ecr 5452241,nop,wscale 7], length 0
21:12:08.660301 IP 192.168.0.10.57391 > 172.17.0.2.80: Flags [.], ack 1, win 342, options [nop,nop,TS val 5452241 ecr 5452241], length 0


次に宛先ポート番号を22222に変更してコンテナにアクセスする。
[root@master1 ~]# curl http://192.168.0.10:22222
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

宛先TCPポート番号が22222のときのtcpdumpで採取したパケット
21:14:13.673223 IP 192.168.0.10.42175 > 172.17.0.3.80: Flags [S], seq 2685052290, win 43690, options [mss 65495,sackOK,TS val 5577254 ecr 0,nop,wscale 7], length 0
21:14:13.673333 IP 172.17.0.3.80 > 192.168.0.10.42175: Flags [S.], seq 1261474781, ack 2685052291, win 14480, options [mss 1460,sackOK,TS val 5577254 ecr 5577254,nop,wscale 7], length 0
21:14:13.673375 IP 192.168.0.10.42175 > 172.17.0.3.80: Flags [.], ack 1, win 342, options [nop,nop,TS val 5577255 ecr 5577254], length 0


##3.16 Dockerクライアント <=> Dockerサーバ間のUNIX domainソケットを流れるパケットを見る。

Dockerクライアントとサーバの間にproxyを作成する。
[root@master1 ~]# socat -v UNIX-LISTEN:/tmp/dockerapi.sock UNIX-CONNECT:/var/run/docker.sock&
[1] 9449


Dockerサーバにアクセスする.HTTPリクエストとレスポンスが観測できる。
[root@master1 ~]# docker -H unix:///tmp/dockerapi.sock ps -a
> 2016/11/21 21:37:09.017349  length=95 from=0 to=94           ======> HTTPリクエストの開始
GET /v1.22/containers/json?all=1 HTTP/1.1\r
Host: \r
User-Agent: Docker-Client/1.10.3 (linux)\r
\r
< 2016/11/21 21:37:09.019849  length=141 from=0 to=140          ========> HTTPレスポンスの開始
HTTP/1.1 200 OK\r
Content-Type: application/json\r
Server: Docker/1.10.3 (linux)\r
Date: Mon, 21 Nov 2016 12:37:09 GMT\r
Content-Length: 3\r
\r
[]
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@master1 ~]#




socatの使い方
[root@master1 ~]# socat tcp-listen:11111 stdout

別のターミナルで以下のように実行する。
[root@master1 ~]# socat tcp-connect:localhost:11111 stdin
test

もう一方のターミナル
[root@master1 ~]# socat tcp-listen:11111 stdout
test

##3.17 コンテナのMACアドレスとIPアドレスを確認する方法(docker network inspect bridge)

コンテナを3つ起動する。
[root@master1 ~]# docker run -d --name nginx1 nginx
4b93774b8e7ac70ba0f70f5ead741e3a82a10a19cf4a940ca9cb6c4ca16b6329
[root@master1 ~]# docker run -d --name nginx2 nginx
2f12861523f1f019d89a4dec32233c09eccad44e0a792b12a9a5e19eb857014d
[root@master1 ~]# docker run -d --name nginx3 nginx
f8d753a23cbcd71810d8c04d411b3a71d9908211bbeb3244cc510e21e2170e2e
[root@master1 ~]#


docker network inspect bridgeを実行する。コンテナがどんなIP/MACアドレスをもっているのかわかる。
[root@master1 ~]# docker network inspect bridge
[
-中略-
        "Containers": {
            "2f12861523f1f019d89a4dec32233c09eccad44e0a792b12a9a5e19eb857014d": {
                "Name": "nginx2",
                "EndpointID": "53001e97e15fd900134f01884b208277796ead9795ab78c6d03631829429b6ed",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "4b93774b8e7ac70ba0f70f5ead741e3a82a10a19cf4a940ca9cb6c4ca16b6329": {
                "Name": "nginx1",
                "EndpointID": "4f3b361b89607f78f15f3cacbbcc76e261bc75c7093ad32f32bc2e6c15135ea9",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "f8d753a23cbcd71810d8c04d411b3a71d9908211bbeb3244cc510e21e2170e2e": {
                "Name": "nginx3",
                "EndpointID": "bd49d3847cf5372376bcf12a93414dc7eb432ad23352639c5515ea25acbc33b9",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/16",
                "IPv6Address": ""
            }
以下、略

##3.18 コンテナが使用するディスクサイズ(dm.basesize)を変更する

コンテナを起動する。
[root@master3 ~]# docker run -it --name centos centos:centos7 bash

ルートパーティションのサイズを確認する。10G(★印)であることがわかる。
[root@144e5f96041b /]# df -h
Filesystem                                                                                         Size  Used Avail Use% Mounted on
/dev/mapper/docker-8:3-202336481-871f24af84360d9307d0015d201d28088fdbe73c6684110afb2c4fdffa13d81a ★10G  240M  9.8G   3% /
tmpfs                                                                                              490M     0  490M   0% /dev
tmpfs                                                                                              490M     0  490M   0% /sys/fs/cgroup
/dev/sda3                                                                                           40G  1.7G   38G   5% /etc/hosts
shm                                                                                                 64M     0   64M   0% /dev/shm
[root@144e5f96041b /]# exit
exit

docker infoコマンドでも確認してみる。10.74 GBであることが確認できる。
[root@master3 ~]# docker info |grep "Base Device Size:"
 Base Device Size: 10.74 GB


ディスクサイズを10G->20Gに変更する。
[root@master3 ~]# vi /etc/sysconfig/docker-storage
DOCKER_STORAGE_OPTIONS=--storage-opt dm.basesize=20G

Dockerを停止する。停止しないと、/var/lib/docker配下が削除できない。
[root@master3 ~]# systemctl stop docker

/var/lib/docker配下を削除する。今まで作成したイメージが全て消去されるので注意!!!
[root@master3 ~]# rm -f -r /var/lib/docker/

Dockerを再起動する。
[root@master3 ~]# systemctl start docker

コンテナを起動する。/var/lib/docker配下を削除したので、再度、イメージのダウンロードが始まる。
[root@master3 ~]# docker run -it --name centos centos:centos7 bash
Unable to find image 'centos:centos7' locally
Trying to pull repository docker.io/library/centos ...
centos7: Pulling from docker.io/library/centos
08d48e6f1cff: Pull complete
Digest: sha256:b2f9d1c0ff5f87a4743104d099a3d561002ac500db1b9bfa02a783a46e0d366c
Status: Downloaded newer image for docker.io/centos:centos7


ディスクサイズを確認する。20G(★印)になっていることが確認できる。
[root@13f57f8cd4fb /]# df -h
Filesystem                                                                                         Size  Used Avail Use% Mounted on
/dev/mapper/docker-8:3-135722635-214924edf11302e77f89a1d577930cd48168d4d4987cd175cb67f6d937d21aa9 ★20G  240M   20G   2% /
tmpfs                                                                                              490M     0  490M   0% /dev
tmpfs                                                                                              490M     0  490M   0% /sys/fs/cgroup
/dev/sda3                                                                                           40G  1.7G   38G   5% /etc/hosts
shm                                                                                                 64M     0   64M   0% /dev/shm
[root@13f57f8cd4fb /]# exit
exit

docker infoコマンドでも確認してみる。21.47 GBであることが確認できる。
[root@master3 ~]# docker info |grep "Base Device Size:"
 Base Device Size: 21.47 GB

-------------------------------------------------------------------------------------------
0.  truncateコマンドの使い方。知らなかったのでメモ
-------------------------------------------------------------------------------------------
1Kサイズのファイル作成
[root@master1 ~]# truncate --size 1K /root/file_1K
[root@master1 ~]# ls -la file_1K
-rw-r--r--. 1 root root 1024 11月 23 09:02 file_1K

1Mサイズのファイル作成
[root@master1 ~]# truncate --size 1M /root/file_1M
[root@master1 ~]# ls -la file_1M
-rw-r--r--. 1 root root 1048576 11月 23 09:02 file_1M

1Gサイズのファイル作成
[root@master1 ~]# truncate --size 1G /root/file_1G
[root@master1 ~]# ls -la file_1G
-rw-r--r--. 1 root root 1073741824 11月 23 09:02 file_1G


ちなみに、どのファイルも実際にディスク領域は消費していない。
[root@master1 ~]# du file_1K
0       file_1K
[root@master1 ~]# du file_1M
0       file_1M
[root@master1 ~]# du file_1G
0       file_1G



-------------------------------------------------------------------------------------------
1. ルートパーティションのサイズ(10G)より小さなサイズ(500M)のファイルは作成できることを確認する。
-------------------------------------------------------------------------------------------
[root@master3 ~]# vi Dockerfile
[root@master3 ~]# docker build -t small .
Sending build context to Docker daemon 24.06 kB
Step 1 : FROM centos:centos7
 ---> 0584b3d2cf6d
Step 2 : RUN truncate --size 500M /root/file
 ---> Running in 72309990b267
 ---> d9e74f07cb1a
Removing intermediate container 72309990b267
Successfully built d9e74f07cb1a

コンテナを起動する。
[root@master3 ~]# docker run -it --rm samll bash

ルートパーティションのサイズを確認する。サイズは10G(★印)であることがわかる。
[root@4a6240b311cb /]# df -h
Filesystem                                                                                         Size  Used Avail Use% Mounted on
/dev/mapper/docker-8:3-135722635-c8ee47480aa38ff8849f715f2d93d4ece493b25a3adde1bb72b783841bfae129 ★10G  740M  9.3G   8% /
tmpfs                                                                                              490M     0  490M   0% /dev
tmpfs                                                                                              490M     0  490M   0% /sys/fs/cgroup
/dev/sda3                                                                                           40G  3.2G   37G   9% /etc/hosts
shm                                                                                                 64M     0   64M   0% /dev/shm
[root@4a6240b311cb /]# exit
exit

ファイルサイズを確認する。500Mのファイルを作成することができた。
[root@2d0e98bd08bd /]# ls -la /root/file
-rw-r--r--. 1 root root 524288000 Nov 22 13:14 /root/file



-------------------------------------------------------------------------------------------
2. ルートパーティションのサイズ(10G)より大きなファイル(11G)を作成して、エラーが発生することを確認する。
-------------------------------------------------------------------------------------------
今度は11Gのファイルを作成するDockerfileを作成する。
[root@master3 ~]# vi Dockerfile
[root@master3 ~]# cat Dockerfile
FROM centos:centos7
RUN truncate --size 11G /root/file

ルートパーティションのサイズ(10G)より大きなファイル(11G)を作成することはできない。
[root@master3 ~]# docker build --no-cache -t big .
Sending build context to Docker daemon 24.06 kB
Step 1 : FROM centos:centos7
 ---> 0584b3d2cf6d
Step 2 : RUN truncate --size 11G /root/file
 ---> Running in 40ebcbd0670c
ApplyLayer exit status 1 stdout:  stderr: write /root/file: no space left on device
[root@master3 ~]#


-------------------------------------------------------------------------------------------
3. 実際にどこが消費されるか確認してみる。
-------------------------------------------------------------------------------------------
[root@e2f80a45bad0 /]# df -h
Filesystem                                                                                      Size  Used Avail Use% Mounted on
/dev/mapper/docker-8:3-713942-3c889cab414769b972f8b76f02a67365ffbbf868f10737e29bd959ff761ac7bc   10G  240M★9.8G   3% /
tmpfs                                                                                           490M     0  490M   0% /dev
tmpfs                                                                                           490M     0  490M   0% /sys/fs/cgroup
/dev/sda3                                                                                        40G  5.0G   35G  13% /etc/hosts
shm                                                                                              64M     0   64M   0% /dev/shm

1Gのファイルを作成する。
[root@e2f80a45bad0 /]# dd if=/dev/zero of=test.txt bs=1024k count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 90.7417 s, 11.8 MB/s

/dev/mapper配下が使われたことがわかる。
[root@e2f80a45bad0 /]# df -h
Filesystem                                                                                      Size  Used Avail Use% Mounted on
/dev/mapper/docker-8:3-713942-3c889cab414769b972f8b76f02a67365ffbbf868f10737e29bd959ff761ac7bc   10G  1.3G★8.8G  13% /
tmpfs                                                                                           490M     0  490M   0% /dev
tmpfs                                                                                           490M     0  490M   0% /sys/fs/cgroup
/dev/sda3                                                                                        40G  6.0G   34G  16% /etc/hosts
shm                                                                                              64M     0   64M   0% /dev/shm



##3.19 コンテナのプロセスをstraceでデバッグする方法(nsenter)
nginxのコンテナには、straceコマンドが入っていない。
yumコマンドも入っていないので、そもそも、straceをダウンロードすることができない。
たとえば、コンテナのNginxをデバッグするとき、どのようにしたら良いか?
そのような場合、nsenterを使うことで解決できる。

Nginxコンテナでstrace,yumコマンドを実行する。コンテナにstraceは入っていないことがわかる。
[root@master1 ~]# docker run -it --rm nginx bash
root@a42cfaf8c6f8:/# strace
bash: strace: command not found
root@a42cfaf8c6f8:/# yum
bash: yum: command not found
root@a42cfaf8c6f8:/#


ホストにnsenterをインストールする。
[root@master1 ~]# docker run -v /usr/local/bin:/target --privileged jpetazzo/nsenter
Unable to find image 'jpetazzo/nsenter:latest' locally
Trying to pull repository docker.io/jpetazzo/nsenter ...
latest: Pulling from docker.io/jpetazzo/nsenter
5c90d4a2d1a8: Downloading [===============>                                   ] 15.73 MB/51.35 MB
-中略-

Digest: sha256:a30e7da907a9abb715027677c21468005beee06251b7737c86f84fa148d572b0
Status: Downloaded newer image for docker.io/jpetazzo/nsenter:latest
Installing nsenter to /target
Installing docker-enter to /target
Installing importenv to /target

ダウンロードしたnsenterのイメージを確認する。
[root@master1 ~]# docker images |grep nsenter
docker.io/jpetazzo/nsenter                            latest                             c16fe938c1a5        4 months ago        370.8 MB

nsenterコマンドは、以下のパスにインストールされる。
[root@master1 ~]# ls /usr/local/bin/nsenter
/usr/local/bin/nsenter


Nginxコンテナを起動する。ホスト側ポート番号11111,コンテナ側ポート番号80で起動する。
[root@master1 ~]# CID=$(docker run -d --name test -p 11111:80 nginx)
[root@master1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                            NAMES
900ae34b590a        nginx               "nginx -g 'daemon off"   13 seconds ago      Up 11 seconds       443/tcp, 0.0.0.0:11111->80/tcp   test
[root@master1 ~]# echo $CID
900ae34b590a567ad396f6a02015d545b82a75608f660d5275f9a96914acc667

[root@master1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)
[root@master1 ~]# echo $PID
15780

nsenterを起動して、Nginxコンテナに接続する。
[root@master1 ~]# nsenter --target $PID --uts --ipc --net /bin/bash

straceを実行するため、NginxのPIDを調べる。
[root@900ae34b590a ~]# ps aux|grep nginx
root      15780  0.4  0.2  31752  2868 ?        Ss   11:17   0:00 nginx: master process nginx -g daemon off;
104       15796  0.0  0.1  32144  1664 ?        S    11:17   0:00 nginx: worker process
root      15875  0.0  0.0 112656   972 pts/0    S+   11:18   0:00 grep --color=auto nginx

Nginxのプロセスに対して、straceを実行する。epollでイベント待ち。
[root@900ae34b590a ~]# strace -ttT -f -p 15796
Process 15796 attached
11:18:48.761204 epoll_wait(8, {{EPOLLIN, {u32=1517506576, u64=140502782660624}}}, 512, -1) = 1 <4.638268>


このとき、別ターミナルよりcurlコマンドでNginxにアクセスする。
[root@master1 ~]#
[root@master1 ~]# curl http://localhost:11111
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

Nginxのイベント待ちが解除される。
[root@900ae34b590a ~]# strace -ttT -f -p 15796
11:18:48.761204 epoll_wait(8, {{EPOLLIN, {u32=1517506576, u64=140502782660624}}}, 512, -1) = 1 <4.638268> ★イベント待ちでブロック

curlコマンドで80番ポートにアクセスすると、Nginxのブロックが解除され、以下のトレースが表示された。
11:18:53.399994 accept4(6, {sa_family=AF_INET, sin_port=htons(44234), sin_addr=inet_addr("172.17.0.1")}, [16], SOCK_NONBLOCK) = 3 <0.000048>
11:18:53.400279 epoll_ctl(8, EPOLL_CTL_ADD, 3, {EPOLLIN|EPOLLRDHUP|EPOLLET, {u32=1517507056, u64=140502782661104}}) = 0 <0.000033>
11:18:53.400514 epoll_wait(8, {{EPOLLIN, {u32=1517507056, u64=140502782661104}}}, 512, 60000) = 1 <0.000033>
11:18:53.400742 recvfrom(3, "GET / HTTP/1.1\r\nUser-Agent: curl"..., 1024, 0, NULL, NULL) = 79 <0.000039>
11:18:53.401093 stat("/usr/share/nginx/html/index.html", {st_mode=S_IFREG|0644, st_size=612, ...}) = 0 <0.013186>
11:18:53.414573 open("/usr/share/nginx/html/index.html", O_RDONLY|O_NONBLOCK) = 11 <0.000241>
11:18:53.419455 fstat(11, {st_mode=S_IFREG|0644, st_size=612, ...}) = 0 <0.000029>
11:18:53.419783 writev(3, [{"HTTP/1.1 200 OK\r\nServer: nginx/1"..., 238}], 1) = 238 <0.000212>
11:18:53.420595 sendfile(3, 11, [0], 612) = 612 <0.000958>
11:18:53.421907 write(5, "172.17.0.1 - - [23/Nov/2016:02:1"..., 91) = 91 <0.002888>
11:18:53.424934 close(11)               = 0 <0.000082>
11:18:53.425137 setsockopt(3, SOL_TCP, TCP_NODELAY, [1], 4) = 0 <0.000038>
11:18:53.425293 epoll_wait(8, {{EPOLLIN|EPOLLRDHUP, {u32=1517507056, u64=140502782661104}}}, 512, 65000) = 1 <0.009390>
11:18:53.434845 recvfrom(3, "", 1024, 0, NULL, NULL) = 0 <0.000039>
11:18:53.434999 close(3)                = 0 <0.000194>
11:18:53.435281 epoll_wait(8,   ★ここで、またイベント待ちでブロックする。

##3.20 コンテナが出力するログを確認する。(docker logs)

-------------------------------------------------------------
1. ログ末尾(-fオプション)や時刻表示(-tオプション)のログを出力する.
-------------------------------------------------------------

コンテナを起動する。
[root@master1 ~]# docker run -itd -p 11111:80 --name test-con nginx
c21e8fd203992631946deb0e9eb91c6cc34eceb5cb57b56e9071a5e74867fe18
[root@master1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                            NAMES
c21e8fd20399        nginx               "nginx -g 'daemon off"   4 seconds ago       Up 1 seconds        443/tcp, 0.0.0.0:11111->80/tcp   test-con


別のターミナルから、Nginxコンテナにアクセスする。
[root@master1 ~]# curl http://localhost:11111

Nginxが出力するログを確認する。-fはログの末尾を表示する。-tは時刻を表示するオプション
[root@master1 ~]# docker logs -ft test-con
2016-11-23T07:43:51.860181000Z 172.17.0.1 - - [23/Nov/2016:07:43:51 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
2016-11-23T07:44:12.619368000Z 172.17.0.1 - - [23/Nov/2016:07:44:12 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
2016-11-23T07:44:14.394863000Z 172.17.0.1 - - [23/Nov/2016:07:44:14 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"

-------------------------------------------------------------
2. ある時刻以降のログだけを出力する。(--sinceオプション)
-------------------------------------------------------------
全てのログを表示する。
[root@master1 ~]# docker logs -t test-con
2016-11-23T07:43:51.860181000Z 172.17.0.1 - - [23/Nov/2016:07:43:51 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
2016-11-23T07:44:12.619368000Z 172.17.0.1 - - [23/Nov/2016:07:44:12 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
2016-11-23T07:44:14.394863000Z 172.17.0.1 - - [23/Nov/2016:07:44:14 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
2016-11-23T07:44:23.147067000Z 172.17.0.1 - - [23/Nov/2016:07:44:23 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
2016-11-23T07:44:29.820801000Z 172.17.0.1 - - [23/Nov/2016:07:44:29 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
2016-11-23T07:54:26.968246000Z 172.17.0.1 - - [23/Nov/2016:07:54:26 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
★
2016-11-23T07:54:28.472748000Z 172.17.0.1 - - [23/Nov/2016:07:54:28 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
2016-11-23T07:54:29.249195000Z 172.17.0.1 - - [23/Nov/2016:07:54:29 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
2016-11-23T07:57:23.897494000Z 172.17.0.1 - - [23/Nov/2016:07:57:23 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"

たとえば、★以降のログだけを表示するには、--sinceオプションを使う。
[root@master1 ~]# docker logs --since 2016-11-23T07:54:28.472748000Z test-con
172.17.0.1 - - [23/Nov/2016:07:54:28 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
172.17.0.1 - - [23/Nov/2016:07:54:29 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
172.17.0.1 - - [23/Nov/2016:07:57:23 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"

正確な時刻を指定しなくても、07:54:28.000000000Z のように指定することもできる。
[root@master1 ~]# docker logs --since 2016-11-23T07:54:28.000000000Z test-con
172.17.0.1 - - [23/Nov/2016:07:54:28 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
172.17.0.1 - - [23/Nov/2016:07:54:29 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
172.17.0.1 - - [23/Nov/2016:07:57:23 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
[root@master1 ~]#

他に以下のような省略した場合でも、期待通りのログを表示できた。".0Z"
[root@master1 ~]# docker logs --since 2016-11-23T07:54:28.0Z test-con
172.17.0.1 - - [23/Nov/2016:07:54:28 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
172.17.0.1 - - [23/Nov/2016:07:54:29 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
172.17.0.1 - - [23/Nov/2016:07:57:23 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"

".00Z"
[root@master1 ~]# docker logs --since 2016-11-23T07:54:28.00Z test-con
172.17.0.1 - - [23/Nov/2016:07:54:28 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
172.17.0.1 - - [23/Nov/2016:07:54:29 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"
172.17.0.1 - - [23/Nov/2016:07:57:23 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.29.0" "-"

##3.21 コンテナの状態をtarファイルに保存したり、tarファイルからイメージを取り出す(export/import)

---------------------------------------------------------------------
1. コンテナイメージをファイルに書き出す(export)
---------------------------------------------------------------------
コンテナを起動する。
[root@master1 test]# docker run -it --name test-con centos:centos7 bash

コンテナ内でファイルを作成する。
[root@7066811e42e1 /]# touch test.txt
[root@7066811e42e1 /]# echo "This is container" > test.txt
[root@7066811e42e1 /]# cat test.txt
This is container

Ctrlキーを押下しながら、PキーとQキーを押下して、コンテナから抜ける。
[root@7066811e42e1 /]# 

コンテナの状態を確認する。
[root@master1 test]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
7066811e42e1        centos:centos7      "bash"              28 seconds ago      Up 25 seconds                           test-con

コンテナを停止する。停止してから、コンテナイメージをファイルに書き出す。
[root@master1 test]# docker stop test-con
test-con

コンテナのファイルシステムをファイルに書き出す。
[root@master1 test]# docker export test-con > test-img.tar

ファイルを確認する。
[root@master1 test]# file test-img.tar
test-img.tar: POSIX tar archive

コンテナで作成したファイルを取り出す。
[root@master1 test]# tar xvf test-img.tar test.txt
test.txt

ファイルの中身を確認する。
[root@master1 test]# cat test.txt
This is container


---------------------------------------------------------------------
2. ファイルからコンテナイメージを取りだす(import)
---------------------------------------------------------------------
[root@master1 test]# ls
test-img.tar

ファイルからコンテナイメージを取り出す。
[root@master1 test]# cat test-img.tar | docker import - test-img:ver2
sha256:37a6835802e35b05a3e095705774f4002a0e5a1799cb569d30e57dc310174ac8

取り出したイメージを確認する。
[root@master1 test]# docker images
REPOSITORY                                            TAG                                IMAGE ID            CREATED             SIZE
test-img                                              ver2                               37a6835802e3        28 seconds ago      196.5 MB
以下、略

登録したイメージからコンテナを起動する。
[root@master1 test]# docker run -it --rm test-img:ver2 bash

[root@5e12df260b97 /]# ls
anaconda-post.log  bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  test.txt  tmp  usr  var

作成したファイルの中身を確認する。
[root@5e12df260b97 /]# cat test.txt
This is container

##3.22 イメージをtarファイルに保存したり、tarファイルからイメージを取り出す(save/load)
###3.22.1 基本的な使い方

------------------------------------------------------
0. 全体像
------------------------------------------------------
master1,master2は仮想マシン(CentOS7.2)です。
 (1) イメージをtarに保存(save)
 (2) tarをscpで転送(master1->master2)
 (3) tarからイメージを取り出す(load)

    master1   ----------------------- master2

     <save>   ------- (scp) -------->  <load>

------------------------------------------------------
1. master1の操作
------------------------------------------------------
tarファイルに保存するイメージを確認する
[root@master1 test2]# docker images |grep busybox
docker.io/busybox                                     latest                             e02e811dd08f        7 weeks ago         1.093 MB

イメージをtarに保存する。
[root@master1 test2]# docker save busybox > busybox_ver1.tar
[root@master1 test2]# ls
busybox_ver1.tar

tarファイルを別ホスト(master2)に転送する。
[root@master1 test2]# scp busybox_ver1.tar root@master2:/root/test

------------------------------------------------------
2. master2の操作
------------------------------------------------------
master1から転送したファイルを確認する。
[root@master2 test]# ls
busybox_ver1.tar

tarファイルからイメージを復元する。
[root@master2 test]# docker load -i busybox_ver1.tar
[root@master2 test]# docker images |grep busybox
docker.io/busybox                                     latest                             e02e811dd08f        7 weeks ago         1.093 MB

コンテナにログインする
[root@master2 test]# docker run -it busybox sh
/ # exit

###3.22.2 登録済イメージをtarファイルに変換

登録済イメージを確認する。
[root@master1 ~]# docker images |grep skydns
gcr.io/google_containers/skydns                       2015-03-11-001      d808d12f05f0        22 months ago       8.811 MB

イメージをtarファイルに保存する。
[root@master1 ~]# docker save gcr.io/google_containers/skydns:2015-03-11-001 > skydns.tar
[root@master1 ~]# ls skydns.tar
skydns.tar

登録済みイメージを削除する。
[root@master1 ~]# docker rmi d808d12f05f0
Untagged: gcr.io/google_containers/skydns:2015-03-11-001
Deleted: sha256:d808d12f05f04a0f99443d803c49ac557540f0453de1599d07c0b761ddf89625
Deleted: sha256:81a0d366188e44745f6c5ef56f7509002b96886c662697c9dbb8faf0878e8ffa
Deleted: sha256:327cc3abb2d292aca8af2e4342914d4239e22c45d49b4b2eea53435d471c47a7

イメージが削除できたかどうかを確認する。削除できた。
[root@master1 ~]# docker images |grep skydns
[root@master1 ~]#

イメージをロードする。
[root@master1 ~]# docker load -i skydns.tar

イメージが登録できたかどうかを確認する。
[root@master1 ~]# docker images |grep skydns
gcr.io/google_containers/skydns                       2015-03-11-001      d808d12f05f0        22 months ago       8.811 MB
[root@master1 ~]#


ちなみに、tarファイルの中身を見てみる。
[root@master1 ~]# tar tvf skydns.tar
drwxr-xr-x 0/0               0 2015-03-11 14:51 0db03cc7860ce2e801eb4f0ce4b84943cec176fcdf6db56fc37b7cf9490b7354/
-rw-r--r-- 0/0               3 2015-03-11 14:51 0db03cc7860ce2e801eb4f0ce4b84943cec176fcdf6db56fc37b7cf9490b7354/VERSION
-rw-r--r-- 0/0            1220 2015-03-11 14:51 0db03cc7860ce2e801eb4f0ce4b84943cec176fcdf6db56fc37b7cf9490b7354/json
-rw-r--r-- 0/0            1024 2015-03-11 14:51 0db03cc7860ce2e801eb4f0ce4b84943cec176fcdf6db56fc37b7cf9490b7354/layer.tar
drwxr-xr-x 0/0               0 2015-03-11 14:51 768d4f50f65f00831244703e57f64134771289e3de919a576441c9140e037ea2/
-rw-r--r-- 0/0               3 2015-03-11 14:51 768d4f50f65f00831244703e57f64134771289e3de919a576441c9140e037ea2/VERSION
-rw-r--r-- 0/0             388 2015-03-11 14:51 768d4f50f65f00831244703e57f64134771289e3de919a576441c9140e037ea2/json
-rw-r--r-- 0/0            1024 2015-03-11 14:51 768d4f50f65f00831244703e57f64134771289e3de919a576441c9140e037ea2/layer.tar
drwxr-xr-x 0/0               0 2015-03-11 14:51 8189e88be4567d5094319a378e339a729c56a4cfb1e4514ff1dfdb5338a9ba20/
-rw-r--r-- 0/0               3 2015-03-11 14:51 8189e88be4567d5094319a378e339a729c56a4cfb1e4514ff1dfdb5338a9ba20/VERSION
-rw-r--r-- 0/0             464 2015-03-11 14:51 8189e88be4567d5094319a378e339a729c56a4cfb1e4514ff1dfdb5338a9ba20/json
-rw-r--r-- 0/0         6382592 2015-03-11 14:51 8189e88be4567d5094319a378e339a729c56a4cfb1e4514ff1dfdb5338a9ba20/layer.tar
drwxr-xr-x 0/0               0 2015-03-11 14:51 96c5134b442cd6446dfae4b1ae1de0aad4b0f408ccd0cf6126566a096da7a209/
-rw-r--r-- 0/0               3 2015-03-11 14:51 96c5134b442cd6446dfae4b1ae1de0aad4b0f408ccd0cf6126566a096da7a209/VERSION
-rw-r--r-- 0/0             464 2015-03-11 14:51 96c5134b442cd6446dfae4b1ae1de0aad4b0f408ccd0cf6126566a096da7a209/json
-rw-r--r-- 0/0         2643968 2015-03-11 14:51 96c5134b442cd6446dfae4b1ae1de0aad4b0f408ccd0cf6126566a096da7a209/layer.tar
drwxr-xr-x 0/0               0 2015-03-11 14:51 b3bbc4636fc59ec067f4a877899f2e008bf3e2fe55451ef78c090dd9709b3818/
-rw-r--r-- 0/0               3 2015-03-11 14:51 b3bbc4636fc59ec067f4a877899f2e008bf3e2fe55451ef78c090dd9709b3818/VERSION
-rw-r--r-- 0/0             464 2015-03-11 14:51 b3bbc4636fc59ec067f4a877899f2e008bf3e2fe55451ef78c090dd9709b3818/json
-rw-r--r-- 0/0            1024 2015-03-11 14:51 b3bbc4636fc59ec067f4a877899f2e008bf3e2fe55451ef78c090dd9709b3818/layer.tar
drwxr-xr-x 0/0               0 2015-03-11 14:51 b888703acbfd97fc1bce3fb2badfcf7f98da8cb6529af2be1a56ab82422a1504/
-rw-r--r-- 0/0               3 2015-03-11 14:51 b888703acbfd97fc1bce3fb2badfcf7f98da8cb6529af2be1a56ab82422a1504/VERSION
-rw-r--r-- 0/0             464 2015-03-11 14:51 b888703acbfd97fc1bce3fb2badfcf7f98da8cb6529af2be1a56ab82422a1504/json
-rw-r--r-- 0/0            1024 2015-03-11 14:51 b888703acbfd97fc1bce3fb2badfcf7f98da8cb6529af2be1a56ab82422a1504/layer.tar
-rw-r--r-- 0/0            2473 2015-03-11 14:51 d808d12f05f04a0f99443d803c49ac557540f0453de1599d07c0b761ddf89625.json
drwxr-xr-x 0/0               0 2015-03-11 14:51 f65db1fc72e498be5329bab6c2f9f5aa6bb4d4747644a984e53fd9dbb17db8bc/
-rw-r--r-- 0/0               3 2015-03-11 14:51 f65db1fc72e498be5329bab6c2f9f5aa6bb4d4747644a984e53fd9dbb17db8bc/VERSION
-rw-r--r-- 0/0             464 2015-03-11 14:51 f65db1fc72e498be5329bab6c2f9f5aa6bb4d4747644a984e53fd9dbb17db8bc/json
-rw-r--r-- 0/0            1024 2015-03-11 14:51 f65db1fc72e498be5329bab6c2f9f5aa6bb4d4747644a984e53fd9dbb17db8bc/layer.tar
-rw-r--r-- 0/0             697 1970-01-01 09:00 manifest.json
-rw-r--r-- 0/0             122 1970-01-01 09:00 repositories
[root@master1 ~]#

##3.23 Nginxイメージのつくり方

[root@master1 ~]# mkdir nginx
[root@master1 ~]# cd nginx/

Dockerfileを編集する。
[root@master1 nginx]# vi Dockerfile
[root@master1 nginx]# cat Dockerfile
FROM centos:centos7
RUN yum -y install epel-release
RUN yum -y install nginx
ADD index.html /usr/share/nginx/html/
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
[root@master1 nginx]#

index.htmlファイルを編集する。
[root@master1 nginx]# vi index.html
[root@master1 nginx]# cat index.html
Hello hana_shin

[root@master1 nginx]# ls
Dockerfile  index.html

イメージをビルドする。
[root@master1 nginx]# docker build -t nginx-img:v1 --no-cache=true .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM centos:centos7
 ---> 0584b3d2cf6d
Step 2 : RUN yum -y install epel-release
 ---> Running in e48a494481c1
Loaded plugins: fastestmirror, ovl
-以下、略


イメージを確認する。
[root@master1 nginx]# docker images
REPOSITORY                                            TAG                                IMAGE ID            CREATED             SIZE
nginx-img                                             v1                                 3df7144df03d        18 seconds ago      400.8 MB

コンテナを起動する。
[root@master1 nginx]# docker run -d -p 11111:80 nginx-img:v1
a6f13663ca199463519f08ca81f33f1fa5133440ed1ddf58f1d6f1d7a064d760

コンテナにHTTPアクセスする。
[root@master1 nginx]# curl http://localhost:11111
Hello hana_shin

##3.24 ビルドに不要なファイルの除外方法(.dockerignoreファイルを使う)

ビルドする時間は4秒
[root@master1 ~]# time docker build -t test-img --no-cache=true .
Sending build context to Docker daemon 83.64 MB
Step 1 : FROM busybox
 ---> e02e811dd08f
Successfully built e02e811dd08f

real    0m4.368s
user    0m0.363s
sys     0m0.882s


ビルドするディレクトリに1Gのファイルを作成する。
[root@master1 ~]# dd if=/dev/zero of=./file_1G bs=1024k count=1024
1024+0 レコード入力
1024+0 レコード出力
1073741824 バイト (1.1 GB) コピーされました、 3.67382 秒、 292 MB/秒

ファイルサイズを確認する。
[root@master1 ~]# ls -la file_1G
-rw-r--r--. 1 root root 1073741824 11月 23 20:33 file_1G

イメージをビルドする。ビルドに47秒かかる。
[root@master1 ~]# time docker build -t test-img --no-cache=true .
Sending build context to Docker daemon 1.157 GB
Step 1 : FROM busybox
 ---> e02e811dd08f
Successfully built e02e811dd08f

real    0m47.847s
user    0m2.671s
sys     0m8.364s
[root@master1 ~]#


ビルド対象外のファイルを作成する。
[root@master1 ~]# vi .dockerignore
[root@master1 ~]# cat .dockerignore
file_1G

イメージをビルドする。今度は3.7秒しかかからない。
[root@master1 ~]# time docker build -t test-img --no-cache=true .
Sending build context to Docker daemon 83.64 MB
Step 1 : FROM busybox
 ---> e02e811dd08f
Successfully built e02e811dd08f

real    0m3.764s
user    0m0.209s
sys     0m1.398s

##3.25 systemdからコンテナを起動する。

サービス定義ファイルを作成する。
[root@master1 system]# pwd
/etc/systemd/system
[root@master1 system]# touch test.service
[root@master1 system]# vi test.service
[root@master1 system]# cat test.service
[Unit]
Description=Simple Nginx Test
After=docker.service
Requires=docker.service

[Service]
Restart=always
ExecStart=/usr/bin/docker run --name nginx-con -p 11111:80 nginx
ExecStop=/usr/bin/docker rm -f nginx-con

[Install]
WantedBy=multi-user.target


[root@master1 system]# systemctl enable /etc/systemd/system/test.service
Created symlink from /etc/systemd/system/multi-user.target.wants/test.service to /etc/systemd/system/test.service.

コンテナを起動する。
[root@master1 system]# systemctl start test.service

コンテナの状態を確認する。
[root@master1 system]# systemctl status test.service
● test.service - Simple Nginx Test
   Loaded: loaded (/etc/systemd/system/test.service; enabled; vendor preset: disabled)
   Active: active (running) since 金 2016-11-25 22:47:25 JST; 7s ago
 Main PID: 20391 (docker-current)
   Memory: 9.8M
   CGroup: /system.slice/test.service
           mq20391 /usr/bin/docker-current run --name nginx-con -p 11111:80 nginx

11月 25 22:47:25 master1 systemd[1]: Started Simple Nginx Test.
11月 25 22:47:25 master1 systemd[1]: Starting Simple Nginx Test...


コンテナの状態を確認する。Nginxのコンテナが起動している。
[root@master1 system]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                            NAMES
ddd3608f807d        nginx               "nginx -g 'daemon off"   48 seconds ago      Up 44 seconds       443/tcp, 0.0.0.0:11111->80/tcp   nginx-con

コンテナにアクセスする。
[root@master1 ~]# curl http://localhost:11111
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>

コンテナを停止する。
[root@master1 system]# systemctl stop test.service

コンテナの状態を確認する。
[root@master1 system]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

##3.26 コンテナイメージから履歴を削除する方法(秘密情報を削除したい場合に使う)


--------------------------------------------------
1. テスト用イメージを作成する。
--------------------------------------------------
Dockerfileを作成する。
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
RUN echo "This is secret information" >> /tmp/secret_key
RUN cat /tmp/secret_key
RUN rm /tmp/secret_key

イメージをビルドする。
[root@master1 test2]# docker build -t test-img:ver1 .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM centos:centos7
 ---> 0584b3d2cf6d
Step 2 : RUN echo "This is secret information" >> /tmp/secret_key
 ---> Running in ed00cad28d24
 ---> 9c6db5e3cad3
Removing intermediate container ed00cad28d24
Step 3 : RUN cat /tmp/secret_key
 ---> Running in 7641391a877c
This is secret information
 ---> 99b9ea91137e
Removing intermediate container 7641391a877c
Step 4 : RUN rm /tmp/secret_key
 ---> Running in 041fc96f4ce2
 ---> 06d81d6769f1
Removing intermediate container 041fc96f4ce2
Successfully built 06d81d6769f1

イメージに対する操作履歴を確認する。
[root@master1 test2]# docker history test-img:ver1
IMAGE               CREATED              CREATED BY                                      SIZE                COMMENT
06d81d6769f1        About a minute ago   /bin/sh -c rm /tmp/secret_key                   0 B
99b9ea91137e        About a minute ago   /bin/sh -c cat /tmp/secret_key                  0 B
9c6db5e3cad3        About a minute ago   /bin/sh -c echo "This is secret information"    27 B
0584b3d2cf6d        3 weeks ago          /bin/sh -c #(nop)  CMD ["/bin/bash"]            0 B
<missing>           3 weeks ago          /bin/sh -c #(nop)  LABEL name=CentOS Base Ima   0 B
<missing>           3 weeks ago          /bin/sh -c #(nop) ADD file:54df3580ac9fb66389   196.5 MB
<missing>           12 weeks ago         /bin/sh -c #(nop)  MAINTAINER https://github.   0 B

履歴の上から2番目の操作を実行する。情報が読めてしまう!!!
[root@master1 test2]# docker run 99b9ea91137e cat /tmp/secret_key
This is secret information


--------------------------------------------------
2. イメージから履歴を削除する。
--------------------------------------------------
コンテナを起動する。
[root@master1 test2]# docker run -d test-img:ver1 /bin/true
8cb069ea1ef9bf058b7515fb6061a33a9512df956fef7b13413c926cd7403805

コンテナの状態を確認する。
[root@master1 test2]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                 CREATED             STATUS                     PORTS               NAMES
8cb069ea1ef9        test-img:ver1       "/bin/true"             10 seconds ago      Exited (0) 7 seconds ago                       focused_chandrasekhar

イメージから履歴を削除する。
[root@master1 test2]# docker export 8cb069ea1ef9 | docker import - test-img:ver1
sha256:a1691c449d092903e16522566a747a85dbbf69486a7b1122984cf147a33594fe
[root@master1 test2]#

コンテナイメージの履歴を確認する。履歴が削除されたことがわかる。
[root@master1 test2]# docker history test-img:ver1
IMAGE               CREATED             CREATED BY          SIZE                COMMENT
a1691c449d09        38 seconds ago                          196.5 MB            Imported from -

##3.27 イメージ一覧に"none:none"というエントリが作成される理由
同じ名前のイメージをビルドすると、イメージ一覧の中に"none:none"というエントリが作成される。

----------------------------------------------
1. 1回目のビルド実行
----------------------------------------------
[root@master1 test2]# less Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
RUN echo "This is V1" >> /tmp/version
RUN cat /tmp/version
RUN rm /tmp/version

[root@master1 test2]# docker build -t test-img:ver1 .
以下、略

[root@master1 test2]# docker images
REPOSITORY                                            TAG                                IMAGE ID            CREATED             SIZE
test-img                                              ver1                               ada297f58022        9 seconds ago       196.5 MB


------------------------------------------------
2. Dockerfileの中身を書き換えて、2回目のビルド実行
------------------------------------------------
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
RUN echo "This is V2" >> /tmp/version
RUN cat /tmp/version
RUN rm /tmp/version

[root@master1 test2]# docker build -t test-img:ver1 .
以下、略

1回目に作成したイメージの"リポジトリ名:TAG"が"none:none"にかわっていることがわかる。
[root@master1 test2]# docker images
REPOSITORY                                            TAG                                IMAGE ID            CREATED              SIZE
test-img                                              ver1                               7a09677e71ac        8 seconds ago        196.5 MB
<none>                                                <none>                             ada297f58022        About a minute ago   196.5 MB
以下、略


------------------------------------------------
3. Dockerfileの中身を書き換えて、3回目のビルド実行
------------------------------------------------
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
RUN echo "This is V3" >> /tmp/version
RUN cat /tmp/version
RUN rm /tmp/version

[root@master1 test2]# docker build -t test-img:ver1 .
以下、略

1回目,2回目に作成したイメージの"リポジトリ名:TAG"が"none:none"にかわっていることがわかる。
[root@master1 test2]# docker images
REPOSITORY                                            TAG                                IMAGE ID            CREATED              SIZE
test-img                                              ver1                               77f33e665cac        7 seconds ago        196.5 MB
<none>                                                <none>                             7a09677e71ac        About a minute ago   196.5 MB
<none>                                                <none>                             ada297f58022        About a minute ago   196.5 MB
以下、略


##3.28 コンテナのユーザIDを調べる方法

コンテナを起動する。
[root@master ~]# docker run -d --name test-con nginx
e509a143aec99f60494ffb7ece7ad4798ba7a251a84dda3b12682448fcfd940b

コンテナの名前(●印)を確認する。
[root@master ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
e509a143aec9        nginx               "nginx -g 'daemon off"   5 seconds ago       Up 2 seconds        80/tcp, 443/tcp   ●test-con

名前("test-con")をもとにコンテナIDを求める。
[root@master ~]# CID=$(docker ps --no-trunc=true|grep "test-con"|awk '{print $1}')

コンテナIDを表示する。
[root@master ~]# echo $CID
e509a143aec99f60494ffb7ece7ad4798ba7a251a84dda3b12682448fcfd940b

プロセスIDを求める。
[root@master ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

プロセスIDを表示する。
[root@master ~]# echo $PID
20648

コンテナのユーザID(UID)を調べる。ユーザID(UID)は0であることがわかる。つまりrootユーザと同じ
[root@master ~]# ps -p $PID -o cmd,pid,ppid,uid,euid
CMD                            PID   PPID   UID  EUID
nginx: master process nginx  20648  20632     0     0

##3.29 コンテナのIPアドレスを調べる方法

コンテナを起動する。
[root@master1 ~]# docker run -it --rm --name test-con centos:centos7 bash

別ターミナルを開いて、コンテナの名前(●印)を確認する。
[root@master1 ~]# docker ps
CONTAINER ID      IMAGE              COMMAND        CREATED             STATUS          PORTS     NAMES
bf30021d03ac      centos:centos7     "bash"         9 seconds ago       Up 6 seconds            ●test-con

名前("test-con")をもとにIPアドレスを確認する。IPアドレスが172.17.0.2であることがわかる(★印)。
[root@master1 ~]# IP=$(docker inspect -f {{.NetworkSettings.IPAddress}} test-con)
[root@master1 ~]# echo $IP
172.17.0.2 ★


コンテナに入って、コンテナの中からもIPアドレスを確認してみる。
[root@bf30021d03ac /]# yum -y install iproute
[root@bf30021d03ac /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
40: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
  ★inet 172.17.0.2/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link
       valid_lft forever preferred_lft forever
[root@bf30021d03ac /]#


##3.30 コンテナのリソース消費を調べる方法(htopを使うより、こっちのほうが簡単かも)

コンテナ(con0)を起動する。
[root@master1 ~]# docker run -it -d --name con0 --cpu-shares=1024  busybox dd if=/dev/zero of=/dev/null
b67ad54132fc2d05797f32830d15306484e17678af75b6505559ef8f80216f1c

コンテナ(con1)を起動する。
[root@master1 ~]# docker run -it -d --name con1 --cpu-shares=1024  busybox dd if=/dev/zero of=/dev/null
f3b736c38bee1b713d9da908f14bc846ad6c3522ccbe9b41410e0b6967145d20

コンテナの状態を確認する。
[root@master1 ~]# docker ps
CONTAINER ID     IMAGE         COMMAND                  CREATED             STATUS           PORTS           NAMES
f3b736c38bee     busybox       "dd if=/dev/zero of=/"   5 seconds ago       Up 2 seconds                     con1
b67ad54132fc     busybox       "dd if=/dev/zero of=/"   12 seconds ago      Up 10 seconds                    con0

コンテナの統計情報を確認する。CPU使用率、メモリ使用量等といった情報が取得できる。
[root@master1 ~]# docker stats $(docker inspect -f {{.Name}} $(docker ps -q))
CONTAINER           CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O
/con0               51.97%              1.057 MB / 1.027 GB   0.10%               1.296 kB / 648 B    1.108 MB / 0 B
/con1               48.78%              1.118 MB / 1.027 GB   0.11%               718 B / 648 B       1.108 MB / 0 B

##3.31 タグなしのイメージをすべて削除する

タグなしイメージ一覧を確認する。
[root@master1 test2]# docker images |grep none
<none>                                                <none>                             987633f4efac        About a minute ago   196.5 MB
<none>                                                <none>                             817a3d2131b4        2 minutes ago        196.5 MB
<none>                                                <none>                             98a0ac2e3be6        7 minutes ago        196.5 MB

タグなしイメージを全て削除する
[root@master1 test2]# docker rmi $(docker images | grep '<none>' | awk '{print$3}')
Deleted: sha256:987633f4eface07f7d53b84cc7464182ccbcd8c2c63ae319ad324f255fce815b
-以下、略-

イメージを確認する。タグなしのイメージが全て削除できた。
[root@master1 test2]# docker images |grep none
[root@master1 test2]#

##3.32 コンテナが終了するときの終了コードについて

Exit Codes With Special Meanings

----------------------------------------------------------------
1. コンテナを正常終了する
----------------------------------------------------------------
[root@master1 ~]# docker run --rm busybox /bin/sh -c 'uname -r'
3.10.0-229.el7.x86_64

終了コードを確認する。正常終了したことがわかる。
[root@master1 ~]# echo $?
0

----------------------------------------------------------------
2. コンテナを異常終了(終了コード=1)する
----------------------------------------------------------------
意図的にコンテナを異常終了(終了コード=1)する。
[root@master1 ~]# docker run busybox /bin/sh -c 'exit 1'

終了コードを確認する。
[root@master1 ~]# echo $?
1

コンテナの状態を確認する。STATUSが"Exited (1)"となっていることがわかる。
[root@master1 ~]# docker ps -a
CONTAINER ID      IMAGE        COMMAND                 CREATED           STATUS                     PORTS         NAMES
1528b8e7a77f      busybox      "/bin/sh -c 'exit 1'"   10 seconds ago  ★Exited (1) 8 seconds ago                 stupefied_visvesvaraya

後始末。コンテナを削除する。
[root@master1 ~]# docker rm 1528b8e7a77f
1528b8e7a77f

----------------------------------------------------------------
3. コンテナを異常終了(終了コード=5)する
----------------------------------------------------------------
意図的にコンテナを異常終了(終了コード=5)する。
[root@master1 ~]# docker run busybox /bin/sh -c 'exit 5'

終了コードを確認する。
[root@master1 ~]# echo $?
5

コンテナの状態を確認する。STATUSが"Exited (5)"となっていることがわかる。
[root@master1 ~]# docker ps -a
CONTAINER ID      IMAGE        COMMAND                 CREATED           STATUS                     PORTS         NAMES
720f0ea21f28      busybox      "/bin/sh -c 'exit 5'"   9 seconds ago   ★Exited (5) 7 seconds ago                 fervent_engelbart

後始末。コンテナを削除する。
[root@master1 ~]# docker rm 720f0ea21f28
720f0ea21f28

----------------------------------------------------------------------------
4. コンテナ内でコマンドが見つからない場合で終了する場合  (終了コード=127)
----------------------------------------------------------------------------
実在しないコマンドlllを実行する。
[root@master1 ~]# docker run busybox /bin/sh -c 'lll'
/bin/sh: lll: not found

終了コードを確認する。
[root@master1 ~]# echo $?
127

[root@master1 ~]# docker ps -a
CONTAINER ID      IMAGE       COMMAND             CREATED            STATUS                       PORTS        NAMES
bb22f6b73563      busybox     "/bin/sh -c lll"    12 seconds ago   ★Exited (127) 9 seconds ago                jovial_thompson

----------------------------------------------------------------
5. Docker自身のエラーの場合(終了コード=125)
----------------------------------------------------------------
[root@master1 ~]# docker run --rm --foo busybox
flag provided but not defined: --foo
See '/usr/bin/docker-current run --help'.

終了コードを確認する。
[root@master1 ~]# echo $?
125

##3.33 コンテナ終了時の挙動について(--restart=on-failure,no)

--restart=on-failure:X (Xは再起動の回数を表す) コンテナが異常終了(終了コードが0以外)した場合の再起動の回数を指定するオプション。
--restart=noは、コンテナが異常終了しても再起動しないようにするオプション。

---------------------------------------------------------
1. 異常終了時の --restart=on-failure の動作を確認する。
---------------------------------------------------------
docker eventsを実行する。コンテナの開始、終了のイベントを得るため、grepで絞り込む。
[root@master1 ~]# docker events |grep -e start -e die

別ターミナルを開く。on-failure:3を付けてコンテナを起動する。
[root@master1 ~]# docker run --restart=on-failure:3 busybox /bin/sh -c 'exit 1'

コンテナの状態を確認する。
[root@master1 ~]# docker ps -a
CONTAINER ID     IMAGE       COMMAND                 CREATED           STATUS                              PORTS      NAMES
2e8167f2125b     busybox     "/bin/sh -c 'exit 1'"   6 seconds ago   ★Exited (1) Less than a second ago              thirsty_ardinghelli

docker eventsを確認する。コンテナが3回再起動をしたことがわかる。再起動は●印の部分
[root@master1 ~]# docker events |grep -e start -e die
2016-12-06T22:11:09.171061352+09:00 container  start 2e8167f2125bf21f05193ca43e63a665685e05a94f356b48623cde97b1539615 (image=busybox, name=thirsty_ardinghelli)
2016-12-06T22:11:09.991771696+09:00 container  die 2e8167f2125bf21f05193ca43e63a665685e05a94f356b48623cde97b1539615 (image=busybox, name=thirsty_ardinghelli)
2016-12-06T22:11:10.193297589+09:00 container●start 2e8167f2125bf21f05193ca43e63a665685e05a94f356b48623cde97b1539615 (image=busybox, name=thirsty_ardinghelli)
2016-12-06T22:11:10.738386606+09:00 container  die 2e8167f2125bf21f05193ca43e63a665685e05a94f356b48623cde97b1539615 (image=busybox, name=thirsty_ardinghelli)
2016-12-06T22:11:11.139880436+09:00 container●start 2e8167f2125bf21f05193ca43e63a665685e05a94f356b48623cde97b1539615 (image=busybox, name=thirsty_ardinghelli)
2016-12-06T22:11:11.788550292+09:00 container  die 2e8167f2125bf21f05193ca43e63a665685e05a94f356b48623cde97b1539615 (image=busybox, name=thirsty_ardinghelli)
2016-12-06T22:11:12.848497457+09:00 container●start 2e8167f2125bf21f05193ca43e63a665685e05a94f356b48623cde97b1539615 (image=busybox, name=thirsty_ardinghelli)
2016-12-06T22:11:13.528665703+09:00 container  die 2e8167f2125bf21f05193ca43e63a665685e05a94f356b48623cde97b1539615 (image=busybox, name=thirsty_ardinghelli)
以下、何も出力されない。


---------------------------------------------------------
2. 正常終了時の --restart=on-failure の動作を確認する。
---------------------------------------------------------
docker eventsを実行する。コンテナの開始、終了のイベントを得るため、grepで絞り込む。
[root@master1 ~]# docker events |grep -e start -e die

別ターミナルを開く。on-failure:3を付けてコンテナを起動する。
[root@master1 ~]# docker run --restart=on-failure:3 busybox /bin/sh -c 'exit 0'
[root@master1 ~]# echo $?
0

コンテナの状態を確認する。
[root@master1 ~]# docker ps -a
CONTAINER ID      IMAGE        COMMAND                 CREATED           STATUS                     PORTS       NAMES
e9bef69f4b79      busybox      "/bin/sh -c 'exit 0'"   9 seconds ago   ★Exited (0) 7 seconds ago               sick_davinci

docker eventsを確認する。コンテナが再起動していないことがわかる。
[root@master1 ~]# docker events |grep -e start -e die
2016-12-06T22:23:51.403847392+09:00 container start e9bef69f4b79595cfac312c39550e567229c44f5569de009f565b8b6dea38967 (image=busybox, name=sick_davinci)
2016-12-06T22:23:52.449435115+09:00 container die e9bef69f4b79595cfac312c39550e567229c44f5569de009f565b8b6dea38967 (image=busybox, name=sick_davinci)
以下、何も出力されない。


------------------------------------------------------
3. --restart=no(デフォルト)の動作を確認する。
------------------------------------------------------
docker eventsを実行する。コンテナの開始、終了のイベントを得るため、grepで絞り込む。
[root@master1 ~]# docker events |grep -e start -e die

別ターミナルを開く。コンテナを起動する。
[root@master1 ~]# docker run busybox /bin/sh -c 'exit 1'
[root@master1 ~]# echo $?
1

コンテナの状態を確認する。
[root@master1 ~]# docker ps -a
CONTAINER ID       IMAGE       COMMAND                 CREATED            STATUS                      PORTS         NAMES
af4d7b72ebf7       busybox     "/bin/sh -c 'exit 1'"   16 seconds ago   ★Exited (1) 14 seconds ago                 big_mirzakhani

docker eventsを確認する。コンテナが再起動していないことがわかる。
[root@master1 ~]# docker events |grep -e start -e die
2016-12-06T22:17:32.421207276+09:00 container start af4d7b72ebf78122596b9c90370f1511bf9e454a272e2940f80fed0cc5af9243 (image=busybox, name=big_mirzakhani)
2016-12-06T22:17:33.363000228+09:00 container die af4d7b72ebf78122596b9c90370f1511bf9e454a272e2940f80fed0cc5af9243 (image=busybox, name=big_mirzakhani)
以下、何も出力されない。

##3.34 一般ユーザ権限でコンテナを起動する(ただし起動したコンテナは特権ユーザ権限で動作)
Docker-docs-ja参照

-----------------------------------------------------
1. 準備(特権ユーザ(root)で行う)
-----------------------------------------------------
groupを確認する。dockerグループは存在しない。
[root@master1 ~]# cat /etc/group|grep docker
dockerroot:x:993:

dockerグループを追加する。
[root@master1 ~]# groupadd docker

groupを確認する。dockerグループが追加されたことがわかる。
[root@master1 ~]# cat /etc/group|grep docker
dockerroot:x:993:
docker:x:1002:

ユーザを追加する。
[root@master1 ~]# adduser hana_shin
[root@master1 ~]# passwd hana_shin

dockerグループにユーザ(hana_shin)を追加する。
[root@master1 ~]# usermod -aG docker hana_shin
[root@master1 ~]# cat /etc/group|grep docker
dockerroot:x:993:
docker:x:1002:hana_shin

Dockerを再起動する。
[root@master1 ~]# systemctl restart docker
[root@master1 ~]#

-----------------------------------------------------
2. 一般ユーザ権限でDockerを起動する。
-----------------------------------------------------
別ターミナルより、一般ユーザでログインする。
[hana_shin@master1 ~]$
[hana_shin@master1 ~]$ id
uid=1001(hana_shin) gid=1001(hana_shin) groups=1001(hana_shin),1002(docker) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

コンテナを起動する。
[hana_shin@master1 ~]$ docker run -it --name test-con centos:centos7 bash

Ctrlを押下しながら、PキーとQキーを押下して、コンテナから抜ける。
[root@f1e13169655f /]# [hana_shin@master1 ~]$

ホストで、コンテナのユーザID等を確認する。
[hana_shin@master1 ~]$ CID=$(docker ps --no-trunc=true|grep "test-con"|awk '{print $1}')
[hana_shin@master1 ~]$ PID=$(docker inspect --format {{.State.Pid}} $CID)

一般ユーザ(hana_shin)権限でコンテナを起動できた。
[hana_shin@master1 ~]$ ps -p $PID -o comm,pid,ppid,uid,euid
COMMAND            PID   PPID   UID  EUID
bash              2079   1655     0     0

親プロセスを確認する。親プロセスはdocker-currentであることがわかる。
[hana_shin@master1 ~]$ ps -p 1655 -o comm,pid,ppid,uid,euid
COMMAND            PID   PPID   UID  EUID
docker-current    1655      1     0     0

後始末。コンテナを終了する。
[hana_shin@master1 ~]$ docker stop f1e13169655f
f1e13169655f
[hana_shin@master1 ~]$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                       PORTS               NAMES
f1e13169655f        centos:centos7      "bash"              16 minutes ago      Exited (137) 3 seconds ago                       test-con

イメージを削除する。
[hana_shin@master1 ~]$ docker rm f1e13169655f
f1e13169655f
[hana_shin@master1 ~]$

-----------------------------------------------------
3. 後始末(グループからユーザを削除する)
-----------------------------------------------------
[root@master1 ~]# gpasswd -d hana_shin docker
ユーザ hana_shin をグループ docker から削除
[root@master1 ~]# cat /etc/group|grep docker
dockerroot:x:993:
docker:x:1002:

##3.35 userns-remap(使い方がいまいちわからない。。)
--userns-remap パラメータを指定することで、 /etc/subuid と /etc/subguid ファイルがユーザとオプションのグループ用に使われます。

Docker for your users - Introducing user namespace/a>
Oracleのドキュメント


------------------------------------------------------------------------
1. 準備(CentOS7.2以上が必要)
------------------------------------------------------------------------
[root@master1 ~]# uname -r
3.10.0-327.36.3.el7.x86_64

docker定義ファイルを編集する。"--userns-remap=default"を追加する。
[root@master1 ~]# vi /etc/sysconfig/docker
OPTIONS='--userns-remap=default'

--userns-remap=defaultを指定すると、dockremapというユーザとグループがつくれるので
それぞれのIDを設定ファイルに定義しておく。
[root@master1 ~]# echo dockremap:500000:65536 > /etc/subuid
[root@master1 ~]# echo dockremap:500000:65536 > /etc/subgid

カーネルのオプションパラメータ(user_namespace.enable=1)を追加する。
[root@master1 ~]# vi /etc/sysconfig/grub
GRUB_CMDLINE_LINUX="rhgb quiet biosdevname=0 net.ifnames=0 user_namespace.enable=1"

設定を有効にする。
[root@master1 ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-229.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-229.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-f9ce816285894f709c0fd8ecf27b8212
Found initrd image: /boot/initramfs-0-rescue-f9ce816285894f709c0fd8ecf27b8212.img
done

カーネルを再起動する。
[root@master1 ~]# shutdown -r now

------------------------------------------------------------------------
2. カーネル再起動後
------------------------------------------------------------------------
カーネルのパラメータを確認する。見やすくするため途中で折り返しています。
[root@master1 ~]# cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-3.10.0-327.36.3.el7.x86_64 root=UUID=c2cb61fd-0e07-4e92-bd38-f76181d9be81 
    ro rhgb quiet biosdevname=0 net.ifnames=0 user_namespace.enable=1 systemd.debug LANG=ja_JP.UTF-8

Dockerの状態を確認する。見やすくするため途中で折り返しています。
[root@master1 ~]# ps aux|grep docker
root       1066  2.9  3.2 586576 32460 ?        Ssl  18:26   0:09 /usr/bin/docker-current daemon 
  --exec-opt native.cgroupdriver=systemd 
  --userns-remap=default 
  --storage-opt dm.basesize=50G 
  --insecure-registry master1:12345

コンテナを起動する。
[root@master1 ~]# docker run -it --name test-con busybox sh
/ # id
uid=0(root) gid=0(root) groups=10(wheel)

別ターミナルを起動する。コンテナのUIDを確認する。UID=500000であることがわかる。
[root@master1 ~]# CID=$(docker ps --no-trunc=true|grep "test-con"|awk '{print $1}')
[root@master1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)
[root@master1 ~]# ps -p $PID -o comm,pid,ppid,uid,euid
COMMAND            PID   PPID   UID  EUID
sh                1489   1067 500000 500000

あと始末。コンテナを削除する。
[root@master1 ~]# docker rm -f test-con
test-con

-----------------------------------------------------
3. UID,GIDを変更する。
-----------------------------------------------------
UIDを変更する。
[root@master1 ~]# vi /etc/subuid
[root@master1 ~]# cat /etc/subuid
dockremap:510000:65536

GIDを変更する。
[root@master1 ~]# vi /etc/subgid
[root@master1 ~]# cat /etc/subgid
dockremap:510000:65536

Dockerを再起動する。
[root@master1 ~]# systemctl restart docker
[root@master1 ~]#

コンテナを起動する
[root@master1 ~]# docker run -it --name test-con busybox sh
/ # id
uid=0(root) gid=0(root) groups=10(wheel)

Ctrlキーを押下しながら、PキーとQキーを押下する。
/ # [root@master1 ~]#

コンテナのUIDを確認する。コンテナがUID=510000で動作していることがわかる。
[root@master1 ~]# CID=$(docker ps --no-trunc=true|grep "test-con"|awk '{print $1}')
[root@master1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)
[root@master1 ~]# ps -p $PID -o comm,pid,ppid,uid,euid
COMMAND            PID   PPID   UID  EUID
sh                4707   4540 510000 510000

##3.36 --userオプションの使い方
--userに指定するユーザ(またはUID)は、コンテナ内のユーザ(またはUID)を指定する。
以下の例では、centos7とnginxのコンテナでは、daemonユーザのUIDが違うことを示している。

----------------------------------------------------
1. centos7コンテナでは、daemonユーザのUIDは2。
----------------------------------------------------
コンテナを起動する。
[root@master1 ~]# docker run -it --user=daemon:daemon --name test-con centos:centos7 bash

UIDを確認する。UID=2であることがわかる。
bash-4.2$ id
uid=2(daemon) gid=2(daemon) groups=2(daemon)

passwdファイルでUIDを確認する。UID=2であることがわかる。
bash-4.2$ grep daemon /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin

Ctrlキーを押下しながらPキーとQキーを押して、コンテナから抜ける。
bash-4.2$ [root@master1 ~]#

コンテナIDを求める。
[root@master1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@master1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

コンテナのUIDを求める。UID=2であることがわかる。
[root@master1 ~]# ps -p $PID -o comm,pid,ppid,uid,euid
COMMAND            PID   PPID   UID  EUID
bash              6396   1028   ★2     2

----------------------------------------------------
2. nginxコンテナでは、daemonユーザのUIDは1。
----------------------------------------------------
コンテナを起動する。
[root@master1 ~]# docker run -it --user=daemon:daemon --name test-con nginx bash

UIDを確認する。UID=1であることがわかる。
daemon@6acee3f32043:/$ id
uid=1(daemon) gid=1(daemon) groups=1(daemon)

passwdファイルでUIDを確認する。UID=1であることがわかる。
daemon@929d7b11ba72:/$ grep daemon /etc/passwd
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

Ctrlキーを押下しながらPキーとQキーを押して、コンテナから抜ける。
/ $ [root@master1 ~]#

コンテナIDを求める。
[root@master1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@master1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

コンテナのUIDを求める。UID=1であることがわかる。
[root@master1 ~]# ps -p $PID -o comm,pid,ppid,uid,euid
COMMAND            PID   PPID   UID  EUID
sh                6957   1028   ★1     1

##3.37 コンテナの情報を整形して出力する方法(--format)

[root@master1 ~]# docker ps --format "table {{.ID}}\t{{.Status}}\t{{.Image}}"
CONTAINER ID        STATUS              IMAGE
847c578f3c8f        Up About a minute   gcr.io/google_containers/skydns:2015-03-11-001
517e07f64736        Up 4 minutes        gcr.io/google_containers/kube2sky:1.11
cca839d03bac        Up 28 minutes       nginx
27727fcf9348        Up 28 minutes       registry.access.redhat.com/rhel7/pod-infrastructure:latest
bdefbe6a6e33        Up 28 minutes       nginx
4bbd8a95cc0f        Up 28 minutes       registry.access.redhat.com/rhel7/pod-infrastructure:latest

##3.38 dockerイメージからPodを起動する

Dockerfileを作成する。
[root@master1 dockerfile]# vi Dockerfile
[root@master1 dockerfile]# cat Dockerfile
FROM centos:centos7
RUN useradd user1
USER user1

イメージをビルドする。
[root@master1 dockerfile]# docker build -t hana/test-img:v1 --no-cache=true .
Sending build context to Docker daemon 3.072 kB
-以下、略-

イメージを確認する。
[root@master1 dockerfile]# docker images hana/test-img:v1
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hana/test-img       v1                  d8de1bc46638        43 seconds ago      196.5 MB

Pod定義ファイルを作成する。
[root@master1 dockerfile]# vi test.yaml
[root@master1 dockerfile]# cat test.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test
spec:
  restartPolicy: Never
  containers:
  - name: test
    image: hana/test-img:v1
    command: ["sleep", "3600"]

Podを起動する。
[root@master1 dockerfile]# kubectl create -f test.yaml
pod "test" created

Podの状態を確認する。
[root@master1 dockerfile]# kubectl get pod
NAME      READY     STATUS    RESTARTS   AGE
test      1/1       Running   0          7s

Podでbashを実行する。
[root@master1 dockerfile]# kubectl exec -it test bash
[user1@test /]$ id
uid=1000(user1) gid=1000(user1) groups=1000(user1)
[user1@test /]$ cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
[user1@test /]$

##3.39 コンテナのGUIを利用する。
上手くいかない。。。


Dockerfileを作成する。
[root@master1 dockergui]# vi Dockerfile
[root@master1 dockergui]# cat Dockerfile
FROM centos:centos7.2.1511
RUN yum -y install firefox
RUN groupadd -g 2002 guiuser
RUN useradd -d /home/guiuser -s /bin/bash -m guiuser -u 2002 -g 2002
USER guiuser
ENV HOME /home/guiuser
CMD /usr/bin/firefox

ユーザを追加する。
[root@master1 dockergui]# adduser guiuser
[root@master1 dockergui]# cat /etc/passwd|grep guiuser
guiuser:x:2002:2002::/home/guiuser:/bin/bash
[root@master1 dockergui]# cat /etc/group|grep guiuser
guiuser:x:2002:

イメージをビルドする。
[root@master1 dockergui]# docker build -t gui .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM centos:centos7.2.1511
 ---> feac5e0dfdb2
Step 2 : RUN yum -y install firefox
 ---> Running in 5e3c45a8b3e8
Loaded plugins: fastestmirror

-中略-

Complete!
 ---> 5edd4cd2c3c9
Removing intermediate container 5e3c45a8b3e8
Step 3 : RUN groupadd -g 2002 guiuser
 ---> Running in 27c81dd37230
 ---> 93a3a4a1b09d
Removing intermediate container 27c81dd37230
Step 4 : RUN useradd -d /home/guiuser -s /bin/bash -m guiuser -u 2002 -g 2002
 ---> Running in 127631b45428
 ---> afa1633e5c1c
Removing intermediate container 127631b45428
Step 5 : USER guiuser
 ---> Running in f6be57dabc5b
 ---> 3110bf85d8fb
Removing intermediate container f6be57dabc5b
Step 6 : ENV HOME /home/guiuser
 ---> Running in 27a5cdd1c695
 ---> d5700b8b5316
Removing intermediate container 27a5cdd1c695
Step 7 : CMD /usr/bin/firefox
 ---> Running in 0df2f2d03910
 ---> fcf6a8321176
Removing intermediate container 0df2f2d03910
Successfully built fcf6a8321176

[root@master1 dockergui]# docker images gui
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
gui                 latest              fcf6a8321176        58 seconds ago      421.9 MB

[root@master1 dockergui]# docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY -h $HOSTNAME -v $HOME/.Xauthority:/home/$USER/.Xauthority gui
Error: cannot open display:

##3.xx 仮想化環境で利用しているゲストOSのイメージをDocker環境への移植

1.virt-tar-outを使って、qcow2を圧縮ファイル(tgz)に変換
2.docker importを使って、圧縮ファイル(tgz)をイメージに変換

#4 Dockerfile
##4.1 CMD (コンテナ起動時に自動的に実行するコマンドを指定する)

Dockerfile リファレンスより抜粋

Dockerfile で CMD 命令を一度だけ指定できます。複数の CMD がある場合、最も後ろの CMD のみ有効です。

---------------------------------------------------
1. CMD ["-a"] -> CMD ["-r"]の順番
---------------------------------------------------
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
ENTRYPOINT ["/usr/bin/uname"]
CMD ["-a"]
CMD ["-r"]

イメージをビルドする。
[root@master1 test2]# docker build -t test-img:ver1 --no-cache=true .
-中略 -

コンテナを起動する。uname -rが実行されていることがわかる。
[root@master1 test2]# docker run --rm test-img:ver1
3.10.0-229.el7.x86_64


---------------------------------------------------
2. 順番を入れ替える( CMD ["-r"] -> CMD ["-a"])
---------------------------------------------------
Dockerfileを作成する。
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
ENTRYPOINT ["/usr/bin/uname"]
CMD ["-r"]
CMD ["-a"]

イメージをビルドする。
[root@master1 test2]# docker build -t test-img:ver1 --no-cache=true .
-中略 -

コンテナを起動する。uname -aが実行されていることがわかる。
[root@master1 test2]# docker run --rm test-img:ver1
Linux bafbe7f69bb2 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36:42 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

##4.2 CMDとENTRYPOINTの使い方

CMDもENTRYPOINTもコンテナ起動時に自動的に実行するコマンドを指定する。
コンテナ起動時に実行するコマンドをENTRYPOINTに指定して、
あとから変更可能なコマンドの引数のデフォルト値をCMDに指定する、というように使う。

--------------------------------------------------------------
1. CMDで指定したコマンド引数は変更可能であることを確認する。
--------------------------------------------------------------
Dockerfileを作成する。
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
ENTRYPOINT ["/usr/bin/uname"]
CMD ["-a"]

イメージを作成する。
[root@master1 test2]# docker build -t test-img:ver1 .
-中略-

コンテナを起動する。コンテナの起動パラメータに何も指定しなければ、uname -aが実行される。
[root@master1 test2]# docker run --rm test-img:ver1
Linux 9496baeb4980 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36:42 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

起動パラメータ(uname -rの"-r")を指定してコンテナを起動する。uname -rが実行される。
つまり、CMD ["-a"]が上書きされたことがわかる。
[root@master1 test2]# docker run --rm test-img:ver1 -r
3.10.0-229.el7.x86_64


--------------------------------------------------------------
2. ENTRYPOINTで指定したコマンド引数は変更不可であることを確認する。
--------------------------------------------------------------
Dockerfileを作成する。
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
ENTRYPOINT ["/usr/bin/uname","-a"]

イメージをビルドする。
[root@master1 test2]# docker build -t test-img:ver1 --no-cache=true .
-中略-

引数なしでコンテナを起動する。
[root@master1 test2]# docker run --rm test-img:ver1
Linux 4a7180accb88 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36:42 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

引数ありでコンテナを起動する。しかし、引数(-r)が無視されていることが確認できる。
ENTRYPOINTで指定したコマンド引数は変更できないことがわかる。
[root@master1 test2]# docker run --rm test-img:ver1 -r
Linux 4b71de2fda69 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36:42 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

##4.3 ADDとCOPYの違い
ADDはアーカイブファイルを展開してしまうが、COPYは展開せず、そのままをイメージにコピーする。

---------------------------------------------------------
1. アーカイブファイルの準備
---------------------------------------------------------
ファイルを2つ作成する。
[root@master1 test2]#  head -c 1000 /dev/urandom > a.txt
[root@master1 test2]#  head -c 1000 /dev/urandom > b.txt

アーカイブファイルを作成する。
[root@master1 test2]# tar cvfz test.tar.gz a.txt b.txt
a.txt
b.txt

作成したファイルを確認する。
[root@master1 test2]# ls -lt
合計 12
-rw-r--r--. 1 root root 2207 11月 26 16:47 test.tar.gz
-rw-r--r--. 1 root root 1000 11月 26 16:47 b.txt
-rw-r--r--. 1 root root 1000 11月 26 16:47 a.txt

---------------------------------------------------------
2. ADDを使った場合 (アーカイブが展開されてしまう)
---------------------------------------------------------
Dockerfileを作成する。
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
RUN mkdir /opt/test
ADD test.tar.gz /opt/test/
RUN ls -lRt /opt/test

カレントディレクトリのファイルを確認する
[root@master1 test2]# ls
Dockerfile  a.txt  b.txt  test.tar.gz

イメージをビルドする。圧縮ファイルが展開されていることがわかる。
[root@master1 test2]# docker build -t test-img:ver1 .
Sending build context to Docker daemon 8.192 kB
Step 1 : FROM centos:centos7
 ---> 0584b3d2cf6d
Step 2 : RUN mkdir /opt/test
 ---> Running in f6129d2aa4c3
 ---> af19cbd77e74
Removing intermediate container f6129d2aa4c3
Step 3 : ADD test.tar.gz /opt/test/
 ---> c21b8d439958
Removing intermediate container e6810a0aabec
Step 4 : RUN ls -lRt /opt/test
 ---> Running in 9b751e97e690
/opt/test:
total 8
-rw-r--r--. 1 root root 1000 Nov 26 07:47 b.txt  <=== アーカイブが展開された。
-rw-r--r--. 1 root root 1000 Nov 26 07:47 a.txt  <=== アーカイブが展開された。
 ---> 995292e70c54
Removing intermediate container 9b751e97e690
Successfully built 995292e70c54

コンテナに入って確認する。圧縮ファイルが展開されていることがわかる。
[root@master1 test2]# docker run -it --rm test-img:ver1 bash
[root@16fc609ba268 /]# cd /opt/test/
[root@16fc609ba268 test]# ls -lt
total 8
-rw-r--r--. 1 root root 1000 Nov 26 07:47 b.txt   <=== アーカイブが展開された。
-rw-r--r--. 1 root root 1000 Nov 26 07:47 a.txt   <=== アーカイブが展開された。


---------------------------------------------------------
3. COPYを使った場合 (アーカイは展開されない)
---------------------------------------------------------
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
RUN mkdir /opt/test
COPY test.tar.gz /opt/test/
RUN ls -lRt /opt/test

イメージをビルドする。アーカイブは展開されないことがわかる。
[root@master1 test2]# docker build -t test-img:ver1 .
Sending build context to Docker daemon 8.192 kB
Step 1 : FROM centos:centos7
 ---> 0584b3d2cf6d
Step 2 : RUN mkdir /opt/test
 ---> Running in 9acb716ae732
 ---> a9f38033cf21
Removing intermediate container 9acb716ae732
Step 3 : COPY test.tar.gz /opt/test/
 ---> 47f2b98dee82
Removing intermediate container b7129e471f34
Step 4 : RUN ls -lRt /opt/test
 ---> Running in 175575dda529
/opt/test:
total 4
-rw-r--r--. 1 root root 2207 Nov 26 07:47 test.tar.gz  <=== アーカイブは展開されない。
 ---> 2b55986f826b
Removing intermediate container 175575dda529
Successfully built 2b55986f826b

コンテナに入って確認する。アーカイブファイルが展開されないことがわかる。
[root@master1 test2]# docker run -it --rm test-img:ver1 bash
[root@1dc516c1a917 /]# cd /opt/test/
[root@1dc516c1a917 test]# ls -lt
total 4
-rw-r--r--. 1 root root 2207 Nov 26 07:47 test.tar.gz  <=== アーカイブは展開されない


---------------------------------------------------------------------------------
4. ADDコマンドを使って、インターネット上のアーカイブファイルをイメージに追加する
   COPYコマンドではできない。
---------------------------------------------------------------------------------
Dockerfileを作成する。
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
RUN mkdir /opt/test
ADD http://tamacom.com/global/global-6.5.5.tar.gz /opt/test/
RUN ls -lRt /opt/test

イメージをビルドする。
[root@master1 test2]# docker build -t test-img:ver1 .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM centos:centos7
 ---> 0584b3d2cf6d
Step 2 : RUN mkdir /opt/test
 ---> Using cache
 ---> a9f38033cf21
Step 3 : ADD http://tamacom.com/global/global-6.5.5.tar.gz /opt/test/
Downloading [==================================================>] 2.935 MB/2.935 MB
 ---> 74f57a040737
Removing intermediate container ffba4d6a3c60
Step 4 : RUN ls -lRt /opt/test
 ---> Running in db028ae06a11
/opt/test:
total 2868
-rw-------. 1 root root 2934542 Sep 21 04:57 global-6.5.5.tar.gz  <===アーカイブが追加された。
 ---> d4c6f9b643ea
Removing intermediate container db028ae06a11
Successfully built d4c6f9b643ea

コンテナを起動する。
[root@master1 test2]# docker run -it --rm test-img:ver1 bash

イメージに追加したアーカイブを確認する。
[root@d05a61cfe82f /]# cd /opt/test/
[root@d05a61cfe82f test]# ls -lt
total 2868
-rw-------. 1 root root 2934542 Sep 21 04:57 global-6.5.5.tar.gz

##4.4 LABEL(イメージにコメントやバージョン情報をつける)

Dockerfileを作成する。
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
LABEL title="Test image"
LABEL version="1.0"
LABEL descriptuon="This is test"

イメージをビルドする。
[root@master1 test2]# docker build -t test-img:ver1 --no-cache=true .
-中略-

イメージの中身を調べる。コメント等が確認できる。
[root@master1 test2]# docker inspect --format="{{ .Config.Labels }}" test-img:ver1
map[build-date:20161102 descriptuon:This is test license:GPLv2 name:CentOS Base Image title:Test image vendor:CentOS version:1.0]

##4.5 WORKDIR(作業用ディレクトリを指定する。)

-----------------------------------------------
1. 絶対パスのあとに相対パスを使った場合
-----------------------------------------------
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
WORKDIR /first
WORKDIR second
WORKDIR third
CMD ["pwd"]

イメージをビルドする。
[root@master1 test2]# docker build -t test-img:ver1 --no-cache=true .
-以下、略-

コンテナを起動する。
[root@master1 test2]# docker run --rm test-img:ver1
/first/second/third

-----------------------------------------------
2. 絶対パスを続けて使った場合
-----------------------------------------------
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
WORKDIR /first
WORKDIR /second
WORKDIR /third
CMD ["pwd"]

イメージをビルドする。
[root@master1 test2]# docker build -t test-img:ver1 --no-cache=true .

コンテナを起動する。
[root@master1 test2]# docker run --rm test-img:ver1
/third

##4.6 USER(USER以降のコマンドをUSER権限で実行する)

----------------------------------------------------
1. ホストでユーザ(hana_shin)を作成する。
----------------------------------------------------
[root@master1 test]# useradd -u 2000 hana_shin
[root@master1 test]# grep hana_shin /etc/passwd
hana_shin:x:2000:2000::/home/hana_shin:/bin/bash
[root@master1 test]# grep hana_shin /etc/group
hana_shin:x:2000:

----------------------------------------------------
2. コンテナでホストと同じユーザ(hana_shin)を作成する。
----------------------------------------------------
[root@master1 test]# vi Dockerfile
[root@master1 test]# cat Dockerfile
FROM centos:centos7
RUN useradd -u 2000 hana_shin
USER hana_shin
CMD tail -f /dev/null

イメージをビルドする。
[root@master1 test]# docker build -t test-img:ver1 --no-cache=true .
-以下、略-

コンテナを起動する。
[root@master1 test]# docker run -it --rm --name test-con test-img:ver1 bash

UIDを確認する。UID=2000のユーザが作成できたことがわかる。
[hana_shin@4fbb369c1d2d /]$ id
uid=2000(hana_shin) gid=2000(hana_shin) groups=2000(hana_shin)

[hana_shin@4fbb369c1d2d /]$ grep hana_shin /etc/passwd
hana_shin:x:2000:2000::/home/hana_shin:/bin/bash

----------------------------------------------------
3. 別ターミナルでコンテナの状態を確認する。
----------------------------------------------------
コンテナの名前(test-con)を確認する。
[root@master1 ~]# docker ps
CONTAINER ID      IMAGE            COMMAND      CREATED           STATUS              PORTS         NAMES
4fbb369c1d2d      test-img:ver1    "bash"       4 minutes ago     Up 4 minutes                      test-con

コンテナIDを求める。
[root@master1 ~]# CID=$(docker ps --no-trunc=true|grep "test-con"|awk '{print $1}')

コンテナのPIDを求める。
[root@master1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

コンテナのpid,uid等を確認する。
[root@master1 ~]# ps -p $PID -o pid,ppid,uid,euid
   PID   PPID   UID  EUID
  3191   1028  2000  2000

親プロセスを確認する。親プロセスはdocker-current であることがわかる。
[root@master1 ~]# ps -p 1028 -o comm,pid,ppid,uid,euid
COMMAND            PID   PPID   UID  EUID
docker-current    1028      1     0     0

プロセスを確認する。
[root@master1 ~]# ps aux|grep hana
hana_sh+   1480  0.0  0.0   4328   648 ?        Ss   19:35   0:00 /bin/sh -c tail -f /dev/null
hana_sh+   1488  0.0  0.0   4260   352 ?        S    19:35   0:00 tail -f /dev/null
hana_sh+   3191  0.0  0.1  11776  1904 pts/1    Ss+  19:59   0:00 bash
root       3916  0.0  0.0 112664   960 pts/2    S+   20:11   0:00 grep --color=auto hana

##4.7 ARG(ビルド時の引数を指定する)
ビルド時に引数xを指定したらイメージX、引数yを指定したらイメージY、というように、
ビルド時の引数にしたがって異なるイメージを作ることができます。

###4.7.1 その1 (ARG xxx=yyy と定義した場合)

--------------------------------------------------
1. ARGを使ったDockerfile (下記2,3で同じものを使う)
--------------------------------------------------
[root@node1 test]# vi Dockerfile
[root@node1 test]# cat Dockerfile
FROM centos:centos7
ARG user=nginx
RUN useradd $user
USER $user

----------------------------------------------------
2. ビルド時に引数を指定しない(--build-argを使わない)
----------------------------------------------------
イメージをビルドする。イメージ内に、デフォルトのnginxユーザを作成する。
[root@node1 test]# docker build -t test-img:ver1 --no-cache=true .
Sending build context to Docker daemon 2.048 kB
-以下、略-

ユーザを確認する。デフォルトのユーザ名(nginx)になっている。
[root@node1 test]# docker run -it --rm test-img:ver1 bash
[nginx@a1a98aa3000d /]$ id
uid=1000(nginx) gid=1000(nginx) groups=1000(nginx)

----------------------------------------------------
3. ビルド時に引数を指定する。(--build-arg user=httpd)
----------------------------------------------------
イメージをビルドする。イメージ内に、引数で指定したhttpdユーザを作成する。
[root@node1 test]# docker build -t test-img:ver1 --no-cache=true --build-arg user=httpd .
Sending build context to Docker daemon 2.048 kB
-以下、略-

ユーザを確認する。ビルド時に指定したユーザ名(httpd)になっている。
[root@node1 test]# docker run -it --rm test-img:ver1 bash
[httpd@fb7fdb408f5b /]$ id
uid=1000(httpd) gid=1000(httpd) groups=1000(httpd)

###4.7.1 その2 (ARG xxx と定義した場合)

----------------------------------------------------
1. テスト用ファイルの準備 (下記2,3,4で同じものを使う)
----------------------------------------------------
[root@node1 test]# vi Dockerfile
[root@node1 test]# cat Dockerfile
FROM centos:centos7
ARG arg
COPY test_$arg /tmp

[root@node1 test]# touch test_10
[root@node1 test]# touch test_20
[root@node1 test]# echo 10 > test_10
[root@node1 test]# echo 20 > test_20
[root@node1 test]# ls
Dockerfile  test_10  test_20

------------------------------------------------------
2. 引数に10を指定(--build-arg arg=10)してビルドする
------------------------------------------------------
ビルドする。イメージ内に、/tmp/test_10というファイルを作成する。
[root@node1 test]# docker build -t test-img:ver1 --no-cache=true --build-arg arg=10 .
Sending build context to Docker daemon 4.096 kB
-以下、略-

コンテナを起動する。
[root@node1 test]# docker run -it --rm test-img:ver1 bash

テストファイルを読み出す。ビルド時に指定したファイルの中身がよめた。
[root@74312d24207d /]# cat /tmp/test_10
10
[root@74312d24207d /]# exit
exit

------------------------------------------------------
3. 引数に20を指定(--build-arg arg=20)してビルドする
------------------------------------------------------
ビルドする。イメージ内に、/tmp/test_20というファイルを作成する。
[root@node1 test]# docker build -t test-img:ver1 --no-cache=true --build-arg arg=20 .
Sending build context to Docker daemon 4.096 kB
-以下、略-

コンテナを起動する。
[root@node1 test]# docker run -it --rm test-img:ver1 bash

テストファイルを読み出す。ビルド時に指定したファイルの中身がよめた。
[root@636350430fc3 /]# cat /tmp/test_20
20
[root@636350430fc3 /]# exit
exit

-----------------------------------------------------^
4. 引数に何も指定しないでビルドする
------------------------------------------------------
ビルドする。引数を指定しないとエラー発生する。
[root@node1 test]# docker build -t test-img:ver1 --no-cache=true .
Sending build context to Docker daemon 4.096 kB
-中略-
Step 3 : COPY test_$arg /tmp
lstat test_: no such file or directory ★

##4.8 ONBUILD
DockerfileのONBUILD

##4.9 Dockerfileの中からシェルスクリプトを実行する。

Dockerfileを作成する。
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
ADD test.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/test.sh
ENTRYPOINT ["/usr/local/bin/test.sh"]

シェルスクリプトを作成する。
[root@master1 test2]# vi test.sh
[root@master1 test2]# cat test.sh
#!/usr/bin/bash
date
df -HT

ファイルを確認する。
[root@master1 test2]# ls
Dockerfile  test.sh

イメージをビルドする。
[root@master1 test2]# docker build -t test-img:ver1 --no-cache=true .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM centos:centos7
 ---> 0584b3d2cf6d
Step 2 : ADD test.sh /usr/local/bin/
 ---> 47e0b863dc89
Removing intermediate container cb92e3c9f034
Step 3 : RUN chmod +x /usr/local/bin/test.sh
 ---> Running in 9bf731f15e9c
 ---> 7c9d1c388c8a
Removing intermediate container 9bf731f15e9c
Step 4 : ENTRYPOINT /usr/local/bin/test.sh
 ---> Running in b70e9cf496aa
 ---> 9d8185069d7f
Removing intermediate container b70e9cf496aa
Successfully built 9d8185069d7f

コンテナを起動する。
[root@master1 test2]# docker run --rm test-img:ver1
Sat Nov 26 12:06:16 UTC 2016
Filesystem                                                                                     Type   Size  Used Avail Use% Mounted on
/dev/mapper/docker-8:3-713942-b4002d9923c4ebdf11156b914942131e8f9b34ffe43b646f4ebe55914855d553 xfs     11G  252M   11G   3% /
tmpfs                                                                                          tmpfs  514M     0  514M   0% /dev
tmpfs                                                                                          tmpfs  514M     0  514M   0% /sys/fs/cgroup
/dev/sda3                                                                                      xfs     43G  5.4G   37G  13% /etc/hosts
shm                                                                                            tmpfs   68M     0   68M   0% /dev/shm
[root@master1 test2]#

##4.10 コンテナを動作させ続ける(tail -f /dev/null)

Dockerfileを作成する。
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM centos:centos7
CMD tail -f /dev/null

イメージをビルドする。
[root@master1 test2]# docker build -t test-img:ver1 --no-cache=true .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM centos:centos7
 ---> 0584b3d2cf6d
Step 2 : CMD tail -f /dev/null
 ---> Running in 51c3bd766516
 ---> 9ddc19b87832
Removing intermediate container 51c3bd766516
Successfully built 9ddc19b87832

コンテナを起動する。
[root@master1 test2]# docker run -d --name test-con test-img:ver1
ab0b4bd16be96e4df1fa01bd47df5e663c67a9a56d97f72d9038280d4d7d9e5b

コンテナの状態を確認する。動作して続けていることがわかる。
[root@master1 test2]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
ab0b4bd16be9        test-img:ver1       "/bin/sh -c 'tail -f "   2 minutes ago       Up 2 minutes                            test-con


#5 実用編
##5.1 WordPress(ブログソフトウェア)とMySQL(データベース)の連携

-------------------------------------------------------------
1. 構成
-------------------------------------------------------------
WordPressとMySQLは、以下の構成になっています。


                +--------------- Host(CentOS7.2) ------------------+
                |                                                  |
              TCP port            container             container  |
   web  <---> 10003 <----------> 80(wordpress) <------> (wp-mysql) |
 browser        |                                                  |
                |                                                  |
                +--------------------------------------------------+


-------------------------------------------------------------
2. 設定
-------------------------------------------------------------
コンテナ(MySQL)を起動する。
[root@master1 ~]# docker run -d --name wp-mysql -e MYSQL_ROOT_PASSWORD=hana_shin mysql
ac631804cc003747cfb16549b8738e5ea0d89d9c4ccc747f277397e36258ae33

コンテナ(wordpress)を起動する。linkオプションは、<連携したいコンテナ名:エイリアス名>のようにつける。
[root@master1 ~]# docker run -d --name wordpress --link wp-mysql:mysql -p 10003:80 wordpress
6c02355bd6b3d357a1d6627ebae4bd353598f096be529406ef5e161aa63e2b3f

コンテナの状態を確認する。
[root@master1 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
6c02355bd6b3        wordpress           "docker-entrypoint.sh"   6 seconds ago       Up 2 seconds        0.0.0.0:10003->80/tcp   wordpress
ac631804cc00        mysql               "docker-entrypoint.sh"   11 seconds ago      Up 9 seconds        3306/tcp                wp-mysql

wordpressが取得した環境変数を表示する。
[root@master1 ~]# docker exec -it wordpress env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=6c02355bd6b3
MYSQL_PORT=tcp://172.17.0.2:3306
MYSQL_PORT_3306_TCP=tcp://172.17.0.2:3306
MYSQL_PORT_3306_TCP_ADDR=172.17.0.2
MYSQL_PORT_3306_TCP_PORT=3306
MYSQL_PORT_3306_TCP_PROTO=tcp
-以下、略-

ブラウザで下記アドレスにアクセスする。
http://192.168.0.10:10003/

##5.2 CentOSとMySQLの連携(用途あるのか???)

コンテナ(MySQL)起動
[root@master1 test2]# docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=hana_shin mysql
7ddd8884ada441341361d45a74bdb252c1082e1cf3226141a26e6c1b992fe17c

コンテナ(CentOS)起動
[root@master1 test2]# docker run -it --name test-con --link mysql:db centos:centos7 bash

CentOSにmysqlパッケージをインストールする。
[root@8b616eca9919 /]# yum -y install mysql
Loaded plugins: fastestmirror, ovl
-以下、略-

接続するDBのIPアドレスを確認する。
[root@8b616eca9919 /]# env|grep DB_PORT_3306_TCP_ADDR
DB_PORT_3306_TCP_ADDR=172.17.0.2

CentOSからMySQLに接続する。
[root@8b616eca9919 /]# mysql -u root -p -h 172.17.0.2
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.16 MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]>

##5.3 Jenkins(開発支援ツール)を起動する。

###(1) Jenkinsを起動する。

Dockerfileを作成する。
[root@master1 test2]# vi Dockerfile
[root@master1 test2]# cat Dockerfile
FROM jenkins
COPY jenkins_plugins.txt /tmp/jenkins_plugins.txt
RUN /usr/local/bin/plugins.sh /tmp/jenkins_plugins.txt
USER root
RUN rm /tmp/jenkins_plugins.txt
RUN groupadd -g 142 docker
RUN addgroup -a jenkins docker
USER jenkins

プラグイン用ファイルを作成する。
[root@master1 test2]# vi jenkins_plugins.txt
[root@master1 test2]# cat jenkins_plugins.txt
swarm:1.22

作成したファイルを確認する。
[root@master1 test2]# ls
Dockerfile  jenkins_plugins.txt

イメージをビルドする。
[root@master1 test2]# docker build -t jenkins_server .

コンテナを起動する。
[root@master1 test2]# docker run --name jenkins_server -p 11111:8080 -p 50000:50000 -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/var/jenkins_home -d jenkins_server
64e6856dbe6ed15f575b0b916eae82c116c1bfa6300876a2ce607993120327d6

コンテナの状態を確認する。
[root@master1 test2]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                               NAMES
64e6856dbe6e        jenkins_server      "/bin/tini -- /usr/lo"   5 seconds ago       Up 3 seconds        0.0.0.0:50000->50000/tcp, 0.0.0.0:11111->8080/tcp   jenkins_server

ブラウザで下記URLにアクセスする。
http://192.168.0.10:11111/

セットアップするためのパスワード入力を求められるので、jenkinsにログインする。
[root@master1 var]# docker exec -it jenkins_server bash

jenkinsのセットアップ用パスワードを読みだす。
jenkins@64e6856dbe6e:~$ cat /var/jenkins_home/secrets/initialAdminPassword
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

パスワードを入力すると、jenkinsのセットアップが開始される。

###(2) jenkinsセットアップ完了後のコンテナの状態を保存(commit)する。

コンテナの状態を確認する。
[root@master1 test2]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                               NAMES
64e6856dbe6e        jenkins_server      "/bin/tini -- /usr/lo"   16 minutes ago      Up 16 minutes       0.0.0.0:50000->50000/tcp, 0.0.0.0:11111->8080/tcp   jenkins_server

コンテナを停止する。
[root@master1 test2]# docker stop jenkins_server
jenkins_server

コンテナイメージを保存(commit)する。保存するのは、セットアップ完了済イメージ。
[root@master1 test2]# docker commit jenkins_server jenkins_server:ver1
sha256:6d5dbe73cf0422e9ba14e2577454386b3ab0600f5b379c9ced52905144522de8

イメージを確認する。セットアップ完了後のイメージは jenkins_server:ver1
[root@master1 test2]# docker images |grep jenkins_server
jenkins_server                                        ver1                               6d5dbe73cf04        55 seconds ago      714.1 MB
jenkins_server                                        latest                             b8081e64f449        21 minutes ago      714.1 MB

jenkinsを起動する。セットアップ完了後のイメージから再起動できた。
[root@master1 test2]# docker run --name jenkins_server -p 11111:8080 -p 50000:50000 -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/var/jenkins_home -d jenkins_server:ver1

#6 コンテナの権限(Capabilities)

Secure Your Containers with this One Weird Trick
Hardening Docker Containers: Disable SUID Programs
CIS Docker 1.11.0 Benchmark
コンテナでcronを動かした時に出るPAMエラーの対処法
Docker networking considered harmful

##6.1 コンテナの権限を確認する方法

pscapコマンドをインストールする。pscapでプロセスの権限を確認します。
[root@master1 ~]# yum -y install libcap-ng-utils

コンテナを起動する。
[root@master1 ~]# docker run -it --name test-con centos:centos7 bash

コンテナからぬける(Ctrlキーを押下しながら、PキーとQキーを押下する)
[root@14cbbaf4c108 /]# [root@master1 ~]#

コンテナIDを求める。
[root@master1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@master1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

コンテナの権限(capabilities)を確認する。1行が長いので折り返しています。
[root@master1 ~]# pscap |grep $PID
ppid  pid   name   command   capabilities
1028  13295 root   bash      chown, dac_override, fowner, fsetid, kill, 
                             setgid, setuid, setpcap, net_bind_service, 
                             net_raw, sys_chroot, mknod, audit_write, setfcap

##6.2 全ての権限を与える。全ての権限を落とす

------------------------------------------
1. 全ての権限を与える(--cap-add=all)
------------------------------------------
コンテナを起動する。全ての権限を与える。
[root@node1 ~]# docker run -it --cap-add=all --name test-con centos:centos7 bash

コンテナからぬける(Ctrlキーを押下しながら、PキーとQキーを押下する)
[root@0f1503dc4f09 /]# [root@node1 ~]#

コンテナIDからコンテナのPIDを求める。
[root@node1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@node1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

権限を確認する。全ての権限が与えられていることがわかる。
[root@node1 ~]# pscap |grep $PID
ppid  pid   name        command           capabilities
1009  1367  root        bash            ★full


------------------------------------------
2. 全ての権限を落とす(--cap-drop=all)
------------------------------------------
コンテナを起動する。全ての権限を落とす。
[root@node1 ~]# docker run -it --cap-drop=all --name test-con centos:centos7 bash

コンテナからぬける(Ctrlキーを押下しながら、PキーとQキーを押下する)
[root@536f79628b07 /]# [root@node1 ~]#

コンテナIDからコンテナのPIDを求める。
[root@node1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@node1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

権限を確認する。権限が何も与えられていることがわかる
[root@node1 ~]# pscap |grep $PID
[root@node1 ~]#

------------------------------------------
3. 特定の権限だけ与える
------------------------------------------
コンテナを起動する。全ての権限を落としてから、必要な権限だけを与える。
[root@node1 ~]# docker run -it --cap-drop=all --cap-add=NET_ADMIN --name test-con centos:centos7 bash

コンテナからぬける(Ctrlキーを押下しながら、PキーとQキーを押下する)
[root@2768d178ef7d /]# [root@node1 ~]#
[root@node1 ~]#

コンテナIDからコンテナのPIDを求める。
[root@node1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@node1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

権限を確認する。NET_ADMINだけ与えられていることがわかる。
[root@node1 ~]# pscap |grep $PID
ppid  pid   name        command           capabilities
1009  1739  root        bash              net_admin

##6.3 NET_ADMINの使い方(その1:経路情報の追加/削除を制御する)

-----------------------------
1. NET_ADMINが有効の場合
-----------------------------
コンテナを起動する。NET_ADMINだけ有効にする。
[root@node1 ~]# docker run -it --cap-drop=all --cap-add=NET_ADMIN  --name test-con busybox sh

経路情報を確認する。
/ # ip route show
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0  src 172.17.0.2

経路情報を追加する。
/ # ip route add 8.8.8.8 via 172.17.0.1 dev eth0

経路情報を確認する。経路情報が追加されたことがわかる。
/ # ip route show
default via 172.17.0.1 dev eth0
8.8.8.8 via 172.17.0.1 dev eth0 ★
172.17.0.0/16 dev eth0  src 172.17.0.2

コンテナからぬける(Ctrlキーを押下しながら、PキーとQキーを押下する)
/ # [root@node1 ~]#

コンテナIDからコンテナのPIDを求める。
[root@node1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@node1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

権限を確認する。NET_ADMINが有効であることがわかる。
[root@node1 ~]# pscap |grep $PID
ppid  pid   name        command           capabilities
1009  2062  root        sh              ★net_admin

-----------------------------
2. NET_ADMINが無効の場合
-----------------------------
コンテナを起動する。全ての権限を落とす。
[root@node1 ~]# docker run -it --cap-drop=all --name test-con busybox sh

経路情報を確認する。
/ # ip route show
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0  src 172.17.0.2

経路情報を追加する。追加できない。
/ # ip route add 8.8.8.8 via 172.17.0.1 dev eth0
ip: RTNETLINK answers: Operation not permitted

コンテナからぬける(Ctrlキーを押下しながら、PキーとQキーを押下する)
/ # [root@node1 ~]#

コンテナIDからコンテナのPIDを求める。
[root@node1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@node1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

権限を確認する。権限が何も与えられていることがわかる
[root@node1 ~]# pscap |grep $PID
[root@node1 ~]#

##6.4 NET_ADMINの使い方(その2:ネットワークデバイスの作成可否を制御する)

-----------------------------
1. NET_ADMINが有効の場合
-----------------------------
コンテナを起動する。NET_ADMINだけ有効にする。
[root@node1 ~]# docker run -it --cap-drop=all --cap-add=NET_ADMIN --name test-con busybox sh

dummyタイプのデバイスを作成する。
/ # ip link add foo type dummy

デバイス(foo)が作成できた。
/ # ip link show foo
2: foo: <BROADCAST,NOARP> mtu 1500 qdisc noop
    link/ether 1a:f8:ed:6b:f0:91 brd ff:ff:ff:ff:ff:ff

デバイスを削除する。
/ # ip link del foo

デバイスが削除できたことがわかる。
/ # ip link show foo
ip: can't find device 'foo'

コンテナからぬける(Ctrlキーを押下しながら、PキーとQキーを押下する)
/ # [root@node1 ~]#

コンテナIDからコンテナのPIDを求める。
[root@node1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@node1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

権限を確認する。NET_ADMINが有効であることがわかる。
[root@node1 ~]# pscap |grep $PID
ppid  pid   name        command           capabilities
1009  3378  root        sh              ★net_admin

-----------------------------
2. NET_ADMINが無効の場合
-----------------------------
コンテナを起動する。全ての権限を無効にする。
[root@node1 ~]# docker run -it --cap-drop=all --name test-con busybox sh

デバイス(foo)を作成する。しかし権限がないため作成できない。
/ # ip link add foo type dummy
ip: RTNETLINK answers: Operation not permitted

コンテナからぬける(Ctrlキーを押下しながら、PキーとQキーを押下する)
/ # [root@node1 ~]#

コンテナIDからコンテナのPIDを求める。
[root@node1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@node1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

権限を確認する。権限が何も与えられていることがわかる
[root@node1 ~]# pscap |grep $PID
[root@node1 ~]#

##6.5 NET_BIND_SERVICEの使い方(特権ポートでのリッスンを制御する)

----------------------------------
1. NET_BIND_SERVICEが有効の場合
----------------------------------
コンテナを起動する。NET_BIND_SERVICEだけ有効にする。
[root@node1 ~]# docker run -it --cap-drop=all --cap-add=NET_BIND_SERVICE  --name test-con busybox sh

rotoユーザで実行する。
/ # id
uid=0(root) gid=0(root) groups=10(wheel)

一般ポート(80)でリッスンする。リッスンできた。Ctrl+Cで終了。
/ # nc -l -p 80
^C
一般ポート(1023)でリッスンする。リッスンできた。Ctrl+Cで終了。
/ # nc -l -p 1023
^C
特権ポート(1024以上)でリッスンする。リッスンできた。Ctrl+Cで終了。
/ # nc -l -p 1024
^C
/ #


別ターミナルを開く。リッスンしているポート番号が確認できる。
[root@node1 ~]# docker exec -it test-con sh
/ # netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 :::80★                 :::*                    LISTEN      20/nc

/ # netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 :::1023★               :::*                    LISTEN      22/nc

/ # netstat -antp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 :::1024★

コンテナIDからコンテナのPIDを求める。
[root@node1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@node1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

権限を確認する。NET_BIND_SERVICEが有効であることがわかる。
[root@node1 ~]# pscap |grep $PID
ppid  pid   name        command           capabilities
2308  2357  root        nc              ★net_bind_service

----------------------------------
2. NET_BIND_SERVICEが無効の場合
----------------------------------
コンテナを起動する。全ての権限を無効にする。
[root@node1 ~]# docker run -it --cap-drop=all --name test-con busybox sh

rotoユーザで実行する。
/ # id
uid=0(root) gid=0(root) groups=10(wheel)

特権ポート(1-1023)ではリッスンできない。
/ # nc -l -p 80
nc: bind: Permission denied

一般ポートではリッスンできる。
[root@node1 ~]# docker exec -it test-con sh
/ # nc -l -p 1024
^C

コンテナからぬける(Ctrlキーを押下しながら、PキーとQキーを押下する)
/ # [root@node1 ~]#
[root@node1 ~]#

コンテナIDからコンテナのPIDを求める。
[root@node1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@node1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

権限を確認する。権限が何も与えられていることがわかる
[root@node1 ~]# pscap |grep $PID
[root@node1 ~]#

##6.6 NET_RAWの使い方
ping,traceroute,arping,tcpdumpといったプログラムが使えなくなる。

-----------------------------
1. NET_RAWが有効の場合
-----------------------------
コンテナを起動する。NET_RAWだけ有効にする。
[root@node1 ~]# docker run -it --cap-drop=all --cap-add=NET_RAW busybox sh

経路情報を検索する。(ping,tracerouteの宛先を確認するため)
/ # ip route show
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0  src 172.17.0.2

pingを実行する。応答がある。
/ # ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1): 56 data bytes
64 bytes from 172.17.0.1: seq=0 ttl=64 time=0.194 ms
-以下、略-

tracerouteを実行する。応答がある。
/ # traceroute 172.17.0.1
traceroute to 172.17.0.1 (172.17.0.1), 30 hops max, 46 byte packets
 1  172.17.0.1 (172.17.0.1)  0.016 ms  0.070 ms  0.016 ms

arpingを実行する。ルータのMACアドレスを得ることができる。
/ # arping -I eth0 172.17.0.1
ARPING to 172.17.0.1 from 172.17.0.2 via eth0
Unicast reply from 172.17.0.1 [02:42:4c:40:95:b7] 0.031ms
-以下、略-


-----------------------------
2. NET_RAWが無効の場合
-----------------------------
コンテナを起動する。全ての権限を無効にする。
[root@node1 ~]# docker run -it --cap-drop=all busybox sh

経路情報を検索する。(ping,tracerouteの宛先を確認するため)
/ # ip route show
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0  src 172.17.0.2

pingを実行する。応答がない。
/ # ping 172.17.0.1
PING 172.17.0.1 (172.17.0.1): 56 data bytes
ping: permission denied (are you root?)

tracerouteを実行する。応答がない。
/ # traceroute 172.17.0.1
traceroute: socket: Operation not permitted

arpingを実行する。応答がない。
/ # arping -I eth0 172.17.0.1
arping: socket: Operation not permitted


busyboxにはyum,tcpdumpが入っていないので、centos7で確認。
[root@node1 ~]# docker run -it --rm --cap-drop=NET_RAW centos:centos7 bash
[root@f54069514adf /]# yum -y install tcpdump
[root@f54069514adf /]# tcpdump -i eth0 port 80
tcpdump: eth0: You don't have permission to capture on that device
(socket: Operation not permitted)

##6.7 MKNODの使い方

-----------------------------
1. MKNODが有効な場合
-----------------------------
コンテナを起動する。MKNODだけ有効にする。
[root@node1 ~]# docker run -it --cap-drop=all --cap-add=MKNOD --name test-con busybox sh

デバイスを作成する。
/ # mknod -m 660 /dev/hda b 56 0

デバイスを確認する。作成できた。
/ # ls -la /dev/hda
brw-rw----    1 root     root       56,   0 Dec 16 12:07 /dev/hda


コンテナからぬける(Ctrlキーを押下しながら、PキーとQキーを押下する)
/ # [root@node1 ~]#

コンテナIDからコンテナのPIDを求める。
[root@node1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@node1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

権限を確認する。MKNODが有効であることがわかる。
[root@node1 ~]# pscap |grep $PID
ppid  pid   name        command           capabilities
1009  3118  root        sh              ★mknod

-----------------------------
2. MKNODが無効な場合
-----------------------------
コンテナを起動する。全ての権限を無効にする。
[root@node1 ~]# docker run -it --cap-drop=all --name test-con busybox sh

デバイスを作成する。しかし、作成できない。
/ # mknod -m 660 /dev/hda b 56 0
mknod: /dev/hda: Operation not permitted

コンテナからぬける(Ctrlキーを押下しながら、PキーとQキーを押下する)
/ # [root@node1 ~]#
[root@node1 ~]#

コンテナIDからコンテナのPIDを求める。
[root@node1 ~]# CID=$(docker ps --no-trunc=true|grep -w "test-con"|awk '{print $1}')
[root@node1 ~]# PID=$(docker inspect --format {{.State.Pid}} $CID)

権限を確認する。MKNODが無効であることがわかる。
[root@node1 ~]# pscap |grep $PID
[root@node1 ~]#

##6.8 CHOWNの使い方

-----------------------------
1. CHOWNが有効の場合
-----------------------------
コンテナを起動する。CHOWNだけ有効にする。
[root@node1 ~]# docker run -it --cap-drop=all --cap-add=CHOWN busybox sh

ファイルを作成する。所有者、グループを確認する。
/ # touch /tmp/aa.txt
/ # ls -la /tmp/aa.txt
-rw-r--r--    1 root     root             0 Dec 18 12:01 /tmp/aa.txt

所有者、グループを変更する。
/ # id daemon
uid=1(daemon) gid=1(daemon) groups=1(daemon)
/ # chown daemon:daemon /tmp/aa.txt

所有者、グループを確認する。変更できた。
/ # ls -la /tmp/aa.txt
-rw-r--r--    1 daemon   daemon           0 Dec 18 12:01 /tmp/aa.txt


-----------------------------
2. CHOWNが無効の場合
-----------------------------
コンテナを起動する。全ての権限を無効にする。
[root@node1 ~]# docker run -it --cap-drop=all busybox sh

ファイルを作成する。所有者、グループを確認する。
/ # touch /tmp/aa.txt
/ # ls -la /tmp/aa.txt
-rw-r--r--    1 root     root             0 Dec 18 12:03 /tmp/aa.txt

所有者、グループを確認する。変更できない。
/ # chown daemon:daemon /tmp/aa.txt
chown: /tmp/aa.txt: Operation not permitted

##6.9 SETUIDの使い方
Added no-new-privileges Security Flag to Docker

使い方がよくわからない。想定通りに動作しない!!!

テスト用プログラム(実行ユーザIDを確認する)を作成する。
[root@node1 test]# vi uid_test.c
[root@node1 test]# cat uid_test.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(int argc, char *argv[])
{
        printf("Effective uid: %d\n", geteuid());
        return 0;
}

Dockerfileを作成する。
[root@node1 test]# vi Dockerfile
[root@node1 test]# cat Dockerfile
FROM centos:centos7
ADD uid_test /tmp/uid_test
RUN chmod u+s /tmp/uid_test
RUN useradd -u 2000 hana_shin
USER hana_shin
ENTRYPOINT /tmp/uid_test

[root@node1 test]# ls
Dockerfile  uid_test  uid_test.c

イメージをビルドする。
[root@node1 test]# docker build -t test-img:ver1 .
Sending build context to Docker daemon 12.29 kB
-以下、略-

#7. セキュリティ

##7.1 イメージの署名チェック機能(DOCKER_CONTENT_TRUST)を有効にする
イメージの署名チェック機能を有効にすると、イメージが改ざんされているかどうか確認できる。
本機能はDocker1.8で実装された。

--------------------------------------------------------
1. 署名チェック機能(DOCKER_CONTENT_TRUST)について確認する。
--------------------------------------------------------
イメージの署名チェック機能を有効にする。
[root@master1 ~]# export DOCKER_CONTENT_TRUST=1

イメージをダウンロードする。
[root@master1 ~]# docker pull busybox
Using default tag: latest
Pull (1 of 1): docker.io/busybox:latest@sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912
Trying to pull repository docker.io/library/busybox ...
sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912: Pulling from docker.io/library/busybox
56bec22e3559: Pull complete
Digest: sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912
Status: Downloaded newer image for docker.io/busybox@sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912
Tagging docker.io/busybox@sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912 as docker.io/busybox:latest

イメージがダウンロードできた。
[root@master1 ~]# docker images |grep busybox
docker.io/busybox                                     latest                             e02e811dd08f        7 weeks ago         1.093 MB
docker.io/busybox                                     <none>                             e02e811dd08f        7 weeks ago         1.093 MB


別のイメージをダウンロードする。イメージに署名がないため、ダウンロードが失敗する。
[root@master1 ~]# docker pull sdurrheimer/prom-busybox
Using default tag: latest
Error: remote trust data does not exist for docker.io/sdurrheimer/prom-busybox: notary.docker.io does not have trust data for docker.io/sdurrheimer/prom-busybox

                                  <none>                             e02e811dd08f        7 weeks ago         1.093 MB

署名チェック機能を無効にする。
[root@master1 ~]# export DOCKER_CONTENT_TRUST=0

もう一度、イメージをダウンロードする。署名チェック機能が無効なので、イメージに署名がなくてもダウンロードできた。
[root@master1 ~]# docker pull sdurrheimer/prom-busybox
Using default tag: latest
Trying to pull repository docker.io/sdurrheimer/prom-busybox ...
latest: Pulling from docker.io/sdurrheimer/prom-busybox
56bec22e3559: Already exists
2e3e1c51b98e: Pull complete
Digest: sha256:d2db77d1721fc54fab36939e94a329572c274ec4870d846771264991a0cd94d1
Status: Downloaded newer image for docker.io/sdurrheimer/prom-busybox:latest

イメージを確認する。公式のBusyboxに加え、prom-busyboxというイメージもダウンロードできた。
[root@master1 ~]# docker images |grep busybox
docker.io/sdurrheimer/prom-busybox                    latest                             172d95747d74        7 weeks ago         2.492 MB
docker.io/busybox                                     latest                             e02e811dd08f        7 weeks ago         1.093 MB
docker.io/busybox                                     <none>                             e02e811dd08f        7 weeks ago         1.093 MB
[root@master1 ~]#


--------------------------------------------------------------------------
2. 特定のイメージだけチェック機能を無効にしたい場合(--disable-content-trust)
--------------------------------------------------------------------------
イメージの署名チェック機能を有効にする。
[root@master1 ~]# export DOCKER_CONTENT_TRUST=1

イメージをダウンロードする。署名がないのでダウンロードできない。
[root@master1 ~]# docker pull sdurrheimer/prom-busybox
Using default tag: latest
Error: remote trust data does not exist for docker.io/sdurrheimer/prom-busybox: notary.docker.io does not have trust data for docker.io/sdurrheimer/prom-busybox

署名がなくてもダウンロードできるオプション(--disable-content-trust)をつけて、ダウンロードする。
[root@master1 ~]# docker pull --disable-content-trust sdurrheimer/prom-busybox
Using default tag: latest
Trying to pull repository docker.io/sdurrheimer/prom-busybox ...
latest: Pulling from docker.io/sdurrheimer/prom-busybox
56bec22e3559: Pull complete
2e3e1c51b98e: Pull complete
Digest: sha256:d2db77d1721fc54fab36939e94a329572c274ec4870d846771264991a0cd94d1
Status: Downloaded newer image for docker.io/sdurrheimer/prom-busybox:latest

##7.2 コンテナ間通信を禁止(--icc=false)にする方法

-------------------------------------------------
1. デフォルト(--icc=true)のときの挙動を調べる
-------------------------------------------------
コンテナを起動する。コンテナは5001番ポートで接続待ち状態にしておく。
[root@master1 ~]# docker run -d --name nc-test amouat/network-utils nc -l 5001
b8f13cffe0748431b05ed08491c3fa36b3173ba9b4e5a93abdcf35ae89e4cb7e

コンテナの状態を確認する。
[root@master1 ~]# docker ps
CONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS              PORTS               NAMES
b8f13cffe074        amouat/network-utils   "nc -l 5001"        8 seconds ago       Up 4 seconds                            nc-test

接続待ちコンテナにメッセージ(hello)を送ることができる。
[root@master1 ~]# docker run -e IP=$(docker inspect -f {{.NetworkSettings.IPAddress}} nc-test) amouat/network-utils sh -c 'echo -n "hello" | nc -w 2 -v $IP 5001'
Connection to 172.17.0.2 5001 port [tcp/*] succeeded!


-------------------------------------------------
2. コンテナ間通信を無効(--icc=false)にする
-------------------------------------------------
[root@master1 ~]# vi /etc/sysconfig/docker
[root@master1 ~]# cat /etc/sysconfig/docker|grep OPTIONS
OPTIONS='--iptables=true --icc=false'

設定を反映する。
[root@master1 ~]# systemctl restart docker

設定を確認する。--icc=falseが設定されていることがわかる。
[root@master1 ~]# ps -C docker-current -o cmd
CMD
/usr/bin/docker-current daemon --exec-opt native.cgroupdriver=systemd --iptables=true ★--icc=false --storage-opt dm.basesize=50G --insecure-registry 192.
[root@master1 ~]#

コンテナを起動する。コンテナは5001番ポートで接続待ち状態にしておく。
[root@master1 ~]# docker run -d --name nc-test amouat/network-utils nc -l 5001
11d2572c0efa9b43c8818fa01922035965653ffcc669de4df2fed1dcea186a07

コンテナの状態を確認する。
[root@master1 ~]# docker ps
CONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS              PORTS               NAMES
11d2572c0efa        amouat/network-utils   "nc -l 5001"        14 seconds ago      Up 11 seconds                           nc-test

接続待ちコンテナにメッセージ(hello)を送る。しかし、今度は送信できない。
[root@master1 ~]# docker run -e IP=$(docker inspect -f {{.NetworkSettings.IPAddress}} nc-test) amouat/network-utils sh -c 'echo -n "hello" | nc -w 2 -v $IP 5001'
nc: connect to 172.17.0.2 port 5001 (tcp) timed out: Operation now in progress

##7.3 Docker Bench for Securityを使う
Docker Bench for Securityをつかって、
コンテナのセキュリティチェックを行う。現時点では使い方だけ。

-------------------------------------------------------------
1. Docker Bench for Securityのイメージをビルドする。
-------------------------------------------------------------
Docker Bench for Securityをダウンロードする。
[root@master1 ~]# git clone https://github.com/docker/docker-bench-security.git
Cloning into 'docker-bench-security'...
remote: Counting objects: 810, done.
remote: Total 810 (delta 0), reused 0 (delta 0), pack-reused 810
Receiving objects: 100% (810/810), 395.98 KiB | 153.00 KiB/s, done.
Resolving deltas: 100% (546/546), done.

ビルドするディレクトリに移動する。
[root@master1 ~]# cd docker-bench-security/
[root@master1 docker-bench-security]# ls
CONTRIBUTING.md  LICENSE.md   README.md          distros                   docker-compose.yml  output_lib.sh
Dockerfile       MAINTAINERS  benchmark_log.png  docker-bench-security.sh  helper_lib.sh       tests

イメージをビルドする。
[root@master1 docker-bench-security]# docker build -t docker-bench-security .
Sending build context to Docker daemon 154.1 kB
Step 1 : FROM alpine:3.2
 ---> 7bed0150ea37
-以下、略-

イメージを確認する。
[root@master1 docker-bench-security]# docker images docker-bench-security
REPOSITORY              TAG            IMAGE ID           CREATED             SIZE
docker-bench-security   latest         d59bf3a4d941       24 seconds ago      41.21 MB


-------------------------------------------------------------
2. 試験対象のコンテナを起動する。
-------------------------------------------------------------
試験対象(Nginx)のコンテナを起動する。
[root@master1 docker-bench-security]# docker run -d --name nginx nginx
5ffaf5d636bf575b066b1e9995157c0600e5b8b645dc8b023c1239d564e5840e

コンテナの状態を確認する。
[root@master1 docker-bench-security]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
5ffaf5d636bf        nginx               "nginx -g 'daemon off"   6 seconds ago       Up 4 seconds        80/tcp, 443/tcp     nginx
[root@master1 docker-bench-security]#


-------------------------------------------------------------
3. コンテナのセキュリティチェックを行う。
-------------------------------------------------------------
Docker Bench for Securityを実行する。続けて、セキュリティチェックの実行結果が表示される。
Nginxのチェック結果には★印をつけています。
[root@master1 docker-bench-security]# docker run -it --net host --pid host --cap-add audit_control \
      -v /var/lib:/var/lib \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v /usr/lib/systemd:/usr/lib/systemd \
      -v /etc:/etc --label docker_bench_security \
      docker-bench-security
# ------------------------------------------------------------------------------
# Docker Bench for Security v1.1.0
#
# Docker, Inc. (c) 2015-
#
# Checks for dozens of common best-practices around deploying Docker containers in production.
# Inspired by the CIS Docker 1.11 Benchmark:
# https://benchmarks.cisecurity.org/downloads/show-single/index.cfm?file=docker16.110
# ------------------------------------------------------------------------------

Initializing Sun Dec  4 09:09:01 GMT 2016


[INFO] 1 - Host Configuration
[WARN] 1.1  - Create a separate partition for containers
[PASS] 1.2  - Use an updated Linux Kernel
[WARN] 1.4  - Remove all non-essential services from the host - Network
[WARN]      * Host listening on: 13 ports
[WARN] 1.5  - Keep Docker up to date
[WARN]       * Using 1.10.3, when 1.12.3 is current as of 2016-10-26
[INFO]       * Your operating system vendor may provide support and security maintenance for docker
[INFO] 1.6  - Only allow trusted users to control Docker daemon
[WARN] 1.7  - Failed to inspect: auditctl command not found.
[WARN] 1.8  - Failed to inspect: auditctl command not found.
[WARN] 1.9  - Failed to inspect: auditctl command not found.
[WARN] 1.10 - Failed to inspect: auditctl command not found.
[INFO] 1.11 - Audit Docker files and directories - docker.socket
[INFO]      * File not found
[INFO] 1.12 - Audit Docker files and directories - /etc/default/docker
[INFO]      * File not found
[INFO] 1.13 - Audit Docker files and directories - /etc/docker/daemon.json
[INFO]      * File not found
[INFO] 1.14 - Audit Docker files and directories - /usr/bin/docker-containerd
[INFO]      * File not found
[INFO] 1.15 - Audit Docker files and directories - /usr/bin/docker-runc
[INFO]      * File not found


[INFO] 2 - Docker Daemon Configuration
[WARN] 2.1  - Restrict network traffic between containers
[WARN] 2.2  - Set the logging level
[PASS] 2.3  - Allow Docker to make changes to iptables
[PASS] 2.4  - Do not use insecure registries
[PASS] 2.5  - Do not use the aufs storage driver
[INFO] 2.6  - Configure TLS authentication for Docker daemon
[INFO]      * Docker daemon not listening on TCP
[INFO] 2.7 - Set default ulimit as appropriate
[INFO]      * Default ulimit doesn't appear to be set
[WARN] 2.8  - Enable user namespace support
[PASS] 2.9  - Confirm default cgroup usage
[PASS] 2.10 - Do not change base device size until needed
[WARN] 2.11 - Use authorization plugin
[WARN] 2.12 - Configure centralized and remote logging
[WARN] 2.13 - Disable operations on legacy registry (v1)


[INFO] 3 - Docker Daemon Configuration Files
[PASS] 3.1  - Verify that docker.service file ownership is set to root:root
[PASS] 3.2  - Verify that docker.service file permissions are set to 644
[INFO] 3.3  - Verify that docker.socket file ownership is set to root:root
[INFO]      * File not found
[INFO] 3.4  - Verify that docker.socket file permissions are set to 644
[INFO]      * File not found
[PASS] 3.5  - Verify that /etc/docker directory ownership is set to root:root
[PASS] 3.6  - Verify that /etc/docker directory permissions are set to 755
[PASS] 3.7  - Verify that registry certificate file ownership is set to root:root
[PASS] 3.8  - Verify that registry certificate file permissions are set to 444
[INFO] 3.9  - Verify that TLS CA certificate file ownership is set to root:root
[INFO]      * No TLS CA certificate found
[INFO] 3.10 - Verify that TLS CA certificate file permissions are set to 444
[INFO]      * No TLS CA certificate found
[INFO] 3.11 - Verify that Docker server certificate file ownership is set to root:root
[INFO]      * No TLS Server certificate found
[INFO] 3.12 - Verify that Docker server certificate file permissions are set to 444
[INFO]      * No TLS Server certificate found
[INFO] 3.13 - Verify that Docker server key file ownership is set to root:root
[INFO]      * No TLS Key found
[INFO] 3.14 - Verify that Docker server key file permissions are set to 400
[INFO]      * No TLS Key found
[WARN] 3.15 - Verify that Docker socket file ownership is set to root:docker
[WARN]      * Wrong ownership for /var/run/docker.sock
[PASS] 3.16 - Verify that Docker socket file permissions are set to 660
[INFO] 3.17 - Verify that daemon.json file ownership is set to root:root
[INFO]      * File not found
[INFO] 3.18 - Verify that daemon.json file permissions are set to 644
[INFO]      * File not found
[INFO] 3.19 - Verify that /etc/default/docker file ownership is set to root:root
[INFO]      * File not found
[INFO] 3.20 - Verify that /etc/default/docker file permissions are set to 644
[INFO]      * File not found


[INFO] 4 - Container Images and Build Files
[WARN] 4.1  - Create a user for the container
[WARN]      * Running as root: nginx  ★
[WARN] 4.5  - Enable Content trust for Docker


[INFO] 5  - Container Runtime
[WARN] 5.1  - Verify AppArmor Profile, if applicable
[WARN]      * No AppArmorProfile Found: nginx  ★
[WARN] 5.2  - Verify SELinux security options, if applicable
[WARN]      * No SecurityOptions Found: nginx  ★
[PASS] 5.3  - Restrict Linux Kernel Capabilities within containers
[PASS] 5.4  - Do not use privileged containers
[PASS] 5.5  - Do not mount sensitive host system directories on containers
[PASS] 5.6  - Do not run ssh within containers
[PASS] 5.7  - Do not map privileged ports within containers
[PASS] 5.9 - Do not share the host's network namespace
[WARN] 5.10 - Limit memory usage for container
[WARN]      * Container running without memory restrictions: nginx ★
[WARN] 5.11 - Set container CPU priority appropriately
[WARN]      * Container running without CPU restrictions: nginx ★
[WARN] 5.12 - Mount container's root filesystem as read only
[WARN]      * Container running with root FS mounted R/W: nginx  ★
[PASS] 5.13 - Bind incoming container traffic to a specific host interface
[WARN] 5.14 - Set the 'on-failure' container restart policy to 5
[WARN]      * MaximumRetryCount is not set to 5: nginx     ★
[PASS] 5.15 - Do not share the host's process namespace
[PASS] 5.16 - Do not share the host's IPC namespace
[PASS] 5.17 - Do not directly expose host devices to containers
[INFO] 5.18 - Override default ulimit at runtime only if needed
[INFO]      * Container no default ulimit override: nginx   ★
[PASS] 5.19 - Do not set mount propagation mode to shared
[PASS] 5.20 - Do not share the host's UTS namespace
[PASS] 5.21 - Do not disable default seccomp profile
[PASS] 5.24 - Confirm cgroup usage
[WARN] 5.25 - Restrict container from acquiring additional privileges
[WARN]      * Privileges not restricted: nginx   ★


[INFO] 6  - Docker Security Operations
[INFO] 6.4 - Avoid image sprawl
[INFO]      * There are currently: 22 images
[WARN]      * Only 2 out of 22 are in use
[INFO] 6.5 - Avoid container sprawl
[INFO]      * There are currently a total of 2 containers, with 2 of them currently running
[root@master1 docker-bench-security]#

###7.3.1 "[WARN] * Running as root: <コンテナの名前>"に対処する
コンテナがrootユーザで動作しているために出力される警告です。
コンテナを一般ユーザで動かすことで警告は解消されます。

[root@node1 test]# vi Dockerfile
[root@node1 test]# cat Dockerfile
FROM centos:centos7
RUN useradd -u 2000 hana_shin
USER hana_shin
[root@node1 test]# docker build -t test-img:ver1 --no-cache=true .
Sending build context to Docker daemon  5.12 kB
-以下、略-

[root@node1 test]# docker run -it --name test-con test-img:ver1 bash
[hana_shin@54ba61db5ac7 /]$ id
uid=2000(hana_shin) gid=2000(hana_shin) groups=2000(hana_shin)

#8 dockerのデバッグオプション
##8.1 デバッグオプションの指定方法
定義ファイル(/etc/sysconfig/docker)の--log-levelにデバッグレベルを指定する。
デバッグレベルとしては以下のものがある。fatalが最も重要度が高く、debugが最も重要度が低い。

 1. fatal(優先度高)
 2. error
 3. warning
 4. info(デフォルト)
 5. debug(優先度低)

デフォルトはinfoレベルになっている。info以上のログを出力する。
debugを指定すると、全てのレベルのログを出力することになる。

デバッグレベルにdebugを指定した場合を以下に示す。
[root@master ~]# vi /etc/sysconfig/docker
OPTIONS='--log-level=debug'

##8.2 infoを指定した場合(「デフォルトのレベル)
infoを指定すると、info以上のレベルのものが表示されるようになる。

dockerを起動する。
[root@master ~]# systemctl start docker

別のターミナルをひらいて、syslogを確認する。warningとinfoレベルのログが出力されていることがわかる。
[root@master ~]# tail -f /var/log/messages|grep -E '(fatal|error|warning|info|debug)'
Mar 12 10:02:46 master dockerd-current: time="2017-03-12T10:02:46.494348443+09:00" level=info msg="libcontainerd: new containerd process, pid: 12877"
Mar 12 10:02:47 master dockerd-current: time="2017-03-12T10:02:47.734320975+09:00" level=warning msg="devmapper: Usage of loopback devices is strongly discouraged for production use. Please use `--storage-opt dm.thinpooldev` or use `man docker` to refer to dm.thinpooldev section."
Mar 12 10:02:47 master dockerd-current: time="2017-03-12T10:02:47.937309476+09:00" level=warning msg="devmapper: Base device already exists and has filesystem xfs on it. User specified filesystem  will be ignored."
Mar 12 10:02:48 master dockerd-current: time="2017-03-12T10:02:48.031061132+09:00" level=info msg="[graphdriver] using prior storage driver \"devicemapper\""
Mar 12 10:02:48 master dockerd-current: time="2017-03-12T10:02:48.054100692+09:00" level=info msg="Graph migration to content-addressability took 0.00 seconds"
Mar 12 10:02:48 master dockerd-current: time="2017-03-12T10:02:48.058632306+09:00" level=info msg="Loading containers: start."
Mar 12 10:02:49 master dockerd-current: time="2017-03-12T10:02:49.018324023+09:00" level=info msg="Loading containers: done."
Mar 12 10:02:49 master dockerd-current: time="2017-03-12T10:02:49.021027153+09:00" level=info msg="Daemon has completed initialization"
Mar 12 10:02:49 master dockerd-current: time="2017-03-12T10:02:49.021911520+09:00" level=info msg="Docker daemon" commit="047e51b/1.12.5" graphdriver=devicemapper version=1.12.5
Mar 12 10:02:49 master dockerd-current: time="2017-03-12T10:02:49.106995415+09:00" level=info msg="API listen on /var/run/docker.sock"

##8.3 warningを指定した場合
warningを指定すると、warning以上のレベルのものが表示されるようになる。

[root@master ~]# vi /etc/sysconfig/docker
OPTIONS='--log-level=warning'

dockerを起動する。
[root@master ~]# systemctl start docker

別のターミナルをひらいて、syslogを確認する。warningレベルのログだけが出力されていることがわかる。
infoレベルのログは出力されなくなったことがわかる。
Mar 12 10:15:09 master dockerd-current: time="2017-03-12T10:15:09.791169342+09:00" level=warning msg="devmapper: Usage of loopback devices is strongly discouraged for production use. Please use `--storage-opt dm.thinpooldev` or use `man docker` to refer to dm.thinpooldev section."
Mar 12 10:15:09 master dockerd-current: time="2017-03-12T10:15:09.962940297+09:00" level=warning msg="devmapper: Base device already exists and has filesystem xfs on it. User specified filesystem  will be ignored."

#9.各種イメージの起動

CentOS5.11
コンテナを起動する。
[root@master1 ~]# docker run -it --rm centos:centos5.11 bash
Unable to find image 'centos:centos5.11' locally
Trying to pull repository docker.io/library/centos ...
centos5.11: Pulling from docker.io/library/centos
2068b24f564b: Pull complete
Digest: sha256:c40041f5894293d0df8f5c6c2049b92a82c53f1718ecdd73cbf3c1826a08ba4a
Status: Downloaded newer image for docker.io/centos:centos5.11

版数を確認する。
[root@4d4c5a456ff3 /]# cat /etc/redhat-release
CentOS release 5.11 (Final)

[root@master1 ~]# docker images centos:centos5.11
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos    centos5.11          b424fba01172        4 months ago        284.1 MB
CentOS6.8
コンテナを起動する。
[root@master1 ~]# docker run -it --rm centos:centos6.8 bash
Unable to find image 'centos:centos6.8' locally
Trying to pull repository docker.io/library/centos ...
centos6.8: Pulling from docker.io/library/centos
67f15db7c18f: Pull complete
Digest: sha256:37ee2dcd9a3a430136b566efb4aa1111ed332bfdef8b0de51a25d26891689fd7
Status: Downloaded newer image for docker.io/centos:centos6.8

版数を確認する。
[root@805bd6c7ec2f /]# cat /etc/redhat-release
CentOS release 6.8 (Final)
[root@805bd6c7ec2f /]#

[root@master1 ~]# docker images centos:centos6.8
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos    centos6.8           0cd976dc0a98        4 months ago        194.5 MB
CentOS7.2
コンテナを起動する。
[root@master1 ~]# docker run -it centos:centos7.2.1511 bash

版数を確認する。
[root@7726e3a77531 /]# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
[root@7726e3a77531 /]#
[root@7726e3a77531 /]# exit
exit
[root@master1 ~]# docker images centos:centos7.2.1511
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos    centos7.2.1511      feac5e0dfdb2        4 months ago        194.6 MB
[root@master1 ~]#
CentOS7.3
コンテナを起動する。
[root@master1 ~]# docker run -it centos:centos7.3.1611 bash
Unable to find image 'centos:centos7.3.1611' locally
Trying to pull repository docker.io/library/centos ...
centos7.3.1611: Pulling from docker.io/library/centos
Digest: sha256:c577af3197aacedf79c5a204cd7f493c8e07ffbce7f88f7600bf19c688c38799
Status: Downloaded newer image for docker.io/centos:centos7.3.1611

版数を確認する。
[root@b66640a84593 /]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
[root@b66640a84593 /]# exit
exit
[root@master1 ~]# docker images centos:centos7.3.1611
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/centos    centos7.3.1611      67591570dd29        5 weeks ago         191.8 MB

#10. 参考資料
Dockerプライベートリポジトリ(Docker Registry)構築レシピ
Docker ドキュメント日本語化プロジェクト
さくらのナレッジ
Docker Content Trust 入門
Docker Content Trust Gets Hardware Signing
Alien (ソフトウェア)
Dockerfile ベストプラクティス

Docker実践入門
Docker実践ガイド
プログラマのためのDocker教科書 インフラの基礎知識&コードによる環境構築の自動化

Best practices for writing Dockerfiles
Create the smallest possible Docker container
[初心者向け] Dockerコンテナの内側
Docker/Aarukas入門ハンズオン資料~第1回さくらとコンテナの夕べ #さくらの夕べ 番外編

170
212
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
170
212