コンテナ型仮想化技術 Study03 / Docker Compose

#はじめに
実際の運用を考えた場合、コンテナ単体で使うことはほとんど無いと思います。通常、役割ごとに複数のコンテナを稼働させて、複数のコンテナをまとめて管理することになると思います。
複数コンテナを効率よく管理するための技術がいくつか提供されており、例えば以下のようなものがあります。他にもいろいろあるけれど。

- **Docker Compose**: 1ホスト内で複数のコンテナを管理するための仕組み / Docker社が提供
- **Docker Swarm**: 複数のDockerホストをまとめて管理するための仕組み(オーケストレーションツール) / Docker社が提供
- **Kubernetes**: オーケストレーションツール / Google社が提供
- **OpenShift**: OSSであるKubernetesの拡張 / RedHat社が提供

SwarmとKubernetesはほぼ同列の位置づけだが、DockerがKubernetesとの統合を発表したため、Swarmは主流からはずれつつあるとのこと。実質オーケストレーションツールのデファクトスタンダードはKubernetesとなっている模様。
さらに、OSSであるKubernetesを拡張してエンタープライズ向けサブスクリプションサポートとして提供しているのがOpenShiftという位置づけ。

とりあえずオーケストレーションツールとしては、まずKubernetesのお勉強をすればよいと思われるが、Docker Composeは併用される可能性もあるようなので、Kubernetesにいくまえに、Docker Composeを見ておきます。
(Swarmは一旦置いておく)

##関連記事
[コンテナ型仮想化技術 Study01 / Docker基礎](https://qiita.com/tomotagwork/items/34b4505b90b71dcfa8ca)
[コンテナ型仮想化技術 Study02 / Docker レジストリ](https://qiita.com/tomotagwork/items/bb1df5232dec5ea7adb7)
[コンテナ型仮想化技術 Study03 / Docker Compose](https://qiita.com/tomotagwork/items/af802c3e25f594cb4a8a)
[コンテナ型仮想化技術 Study04 / Minikube & kubectl簡易操作](https://qiita.com/tomotagwork/items/79527a132d343ab8d534)
[コンテナ型仮想化技術 Study05 / Pod操作](https://qiita.com/tomotagwork/items/7b16bde0529c052a9540)
[コンテナ型仮想化技術 Study06 / ReplicaSet, Deployment, Service](https://qiita.com/tomotagwork/items/2eb36f84c7f396f51e56)
[コンテナ型仮想化技術 Study06' / Kubernetesネットワーク問題判別](https://qiita.com/tomotagwork/items/f1145f3f5656a5cd51c3)
[コンテナ型仮想化技術 Study07 / ストレージ](https://qiita.com/tomotagwork/items/eacf8629bd4889f80672)
[コンテナ型仮想化技術 Study08 / Statefulset, Ingress](https://qiita.com/tomotagwork/items/3a5589031854c702fcec)
[コンテナ型仮想化技術 Study09 / Helm](https://qiita.com/tomotagwork/items/f46a26e3437c716881dc)

#参考情報

[Docker Composeのインストール方法(CentOS7.3)](https://qiita.com/uhooi/items/fb14d99d3323bd2eee9d)
[GitHub: Docker Compose Release](https://github.com/docker/compose/releases)


#環境



[oneWEX導入メモ / RHEL7.6 オフライン編](https://qiita.com/tomotagwork/items/6ad047d0b72e199b7878)
※上で作ったRHEL環境を使うことにする

```xxx:DockerCE
[root@test11 ~]# docker version
Client: Docker Engine - Community
 Version:           19.03.1
 API version:       1.40
 Go version:        go1.12.5
 Git commit:        74b1e89
 Built:             Thu Jul 25 21:21:07 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.1
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.5
  Git commit:       74b1e89
  Built:            Thu Jul 25 21:19:36 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.6
  GitCommit:        894b81a4b802e4eb2a91d1ce216b8817763c29fb
 runc:
  Version:          1.0.0-rc8
  GitCommit:        425e105d5a03fabd737a126ad93d62a9eeede87f
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
```

# Docker Composeのインストール
参考: [GitHub: Docker Compose Release](https://github.com/docker/compose/releases)
最新の1.24.1をインストールする。

```
[root@test11 ~]# curl -L https://github.com/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   617    0   617    0     0   1148      0 --:--:-- --:--:-- --:--:--  1148
100 15.4M  100 15.4M    0     0  1493k      0  0:00:10  0:00:10 --:--:-- 1819k

[root@test11 ~]# chmod +x /usr/local/bin/docker-compose

[root@test11 ~]# docker-compose version
docker-compose version 1.24.1, build 4667896b
docker-py version: 3.7.3
CPython version: 3.6.8
OpenSSL version: OpenSSL 1.1.0j  20 Nov 2018
```

#docker-compose操作例

##単純ケース
一旦、1つのコンテナだけdocker-composeを使ってセットアップしてみる。

適当なディレクトリを作成して、そこにdocker-compose.ymlファイルを作成します。

```yml:docker-compose.yml
version: "3"
services:
 echo:
  image: example/echo:latest
  ports:
   - 9000:8080
```

上の指定は、```docker container run -d -p 9000:8080 example/echo:latest``` を実行するのと同等。

開始してみます。
同ディレクトリで以下のコマンドを実行。

```
[root@test11 /home/user01/docker_test/comp01]# docker-compose up -d
Creating network "comp01_default" with the default driver
Creating comp01_echo_1 ... done
```

コンテナが起動しました。

```
[root@test11 /home/user01/docker_test/comp01]# docker container ls
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                    NAMES
bc8cbd9f50dc        example/echo:latest   "go run /echo/main.go"   2 minutes ago       Up 2 minutes        0.0.0.0:9000->8080/tcp   comp01_echo_1
```

停止してみます。

```
[root@test11 /home/user01/docker_test/comp01]# docker-compose down
Stopping comp01_echo_1 ... done
Removing comp01_echo_1 ... done
Removing network comp01_default

[root@test11 /home/user01/docker_test/comp01]# docker container ls -a
CONTAINER ID        IMAGE                           COMMAND                  CREATED             STATUS                      PORTS               NAMES
dc74ac8cd41f        example/echo:latest             "go run /echo/main.go"   21 hours ago        Exited (2) 21 hours ago                         hungry_morse
f24ced154c60        hello-world                     "/hello"                 21 hours ago        Exited (0) 21 hours ago                         eager_johnson
21e14f86d53b        hello-world                     "/hello"                 21 hours ago        Exited (0) 21 hours ago                         relaxed_germain
c34b4b82478d        ibm-cics-tx-on-cloud:10.1.0.0   "/work/create_and_st…"   9 days ago          Exited (137) 22 hours ago                       lucid_einstein
```

docker-compose downコマンドは、コンテナの停止&削除まで実施されます(停止、削除それぞれ個別に実施する場合は、stop, rmというコマンドが使用できます)。

参考: [docker-compose コマンドまとめ](https://qiita.com/wasanx25/items/d47caf37b79e855af95f)

##複数コンテナ管理

JenkinsのMaster/Slaveそれぞれのコンテナを作成してみます。

###Jenkins-Masterコンテナ作成
一旦、Master用のコンテナ1つだけのymlを作成。

```yml:docker-compose.yml
version: "3"
services:
 master:
  container_name: master
  image: jenkinsci/jenkins:2.154-slim
  ports:
   - 8080:8080
  volumes:
   - ./jenkins_home:/var/jenkins_home
```

./jenkins_homeを作成して権限設定しておく。(とりあえずchmod 777)
構成情報等が保持されるディレクトリはホスト上の./jenkins_homeにマウントし、永続化しています。


実行

```
[root@test11 /home/user01/docker_test/comp02]# docker-compose up
Creating network "comp02_default" with the default driver
Pulling master (jenkinsci/jenkins:2.150.1-slim)...
2.150.1-slim: Pulling from jenkinsci/jenkins
a5a6f2f73cd8: Pull complete
38f6dd39b858: Pull complete
...
```

Slaveとの接続用にSSH接続用のキーペアを作成します。

```
[root@test11 /home/user01/docker_test/comp02]# docker container ls
CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS              PORTS                               NAMES
91f61d834815        jenkinsci/jenkins:2.150.1-slim   "/sbin/tini -- /usr/…"   16 minutes ago      Up 14 minutes       0.0.0.0:8080->8080/tcp, 50000/tcp   master

[root@test11 /home/user01/docker_test/comp02]# docker container exec -it master ssh-keygen -t rsa -C ""
Generating public/private rsa key pair.
Enter file in which to save the key (/var/jenkins_home/.ssh/id_rsa):
Created directory '/var/jenkins_home/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /var/jenkins_home/.ssh/id_rsa.
Your public key has been saved in /var/jenkins_home/.ssh/id_rsa.pub.
...
```

###Jenkins-Slaveコンテナ作成

docker-compose.ymlを編集してSlave用の設定を追加します。

```yml:docker-compose.yml
version: "3"
services:
 master:
  container_name: master
  image: jenkinsci/jenkins:2.154-slim
  ports:
   - 8080:8080
  volumes:
   - ./jenkins_home:/var/jenkins_home

 slave01:
  container_name: slave01
  image: jenkinsci/ssh-slave
  environment:
   - JENKINS_SLAVE_SSH_PUBKEY=ssh-rsa AAAAB...
```

slave01の定義を追加し、SSH接続用に、上で作成したSSHキーの公開鍵の内容を環境変数として設定します。
masterコンテナからslave01という名前でslave01コンテナを認識できるようになるはず。

参考: [Jenkins SSH slave Docker image](https://github.com/jenkinsci/docker-ssh-slave/blob/master/README.md)
参考: [いい加減docker-composeでlinksを使うのをやめてnetworkでコンテナ間名前解決をする](https://qiita.com/dyoshikawa/items/05d627b962da35f7d5b6)
参考: [Compose のネットワーク機能](http://docs.docker.jp/compose/networking.html)

実行

```
[root@test11 /home/user01/docker_test/comp02]# docker-compose up -d
Creating network "comp02_default" with the default driver
Pulling slave01 (jenkinsci/ssh-slave:)...
latest: Pulling from jenkinsci/ssh-slave
bc9ab73e5b14: Pull complete
193a6306c92a: Pull complete
e5c3f8c317dc: Pull complete
a587a86c9dcb: Pull complete
...

[root@test11 /home/user01/docker_test/comp02]# docker container ls
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS              PORTS                               NAMES
24413a54ccdf        jenkinsci/jenkins:2.154-slim   "/sbin/tini -- /usr/…"   2 minutes ago       Up 2 minutes        0.0.0.0:8080->8080/tcp, 50000/tcp   master
9dc6bf1b299c        jenkinsci/ssh-slave            "setup-sshd"             2 minutes ago       Up 2 minutes        22/tcp                              slave01
```

Master/Slave 2つのコンテナが起動されました。
MasterからSlave01をSSH経由で管理できるようになっているはず。
簡易的にMasterコンテナに入ってsshコマンドたたいてみると、slave01に対してSSH接続できました。

```
[root@test11 /home/user01/docker_test/comp02]# docker container exec -it master sh
$ ssh slave01
Linux 9dc6bf1b299c 3.10.0-957.el7.x86_64 #1 SMP Thu Oct 4 20:48:51 UTC 2018 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Thu Oct 24 05:35:39 2019 from 172.22.0.3
jenkins@9dc6bf1b299c:~$
```

slave01側からもmasterにpingが通ることが確認できました。

```
[root@test11 /home/user01/docker_test/comp02]# docker exec -it slave01 ping master
PING master (172.23.0.3) 56(84) bytes of data.
64 bytes from master.comp02_default (172.23.0.3): icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from master.comp02_default (172.23.0.3): icmp_seq=2 ttl=64 time=0.053 ms
64 bytes from master.comp02_default (172.23.0.3): icmp_seq=3 ttl=64 time=0.053 ms
```

これで、MasterノードのJenkins管理画面に接続して、Slaveのノードを登録したり構成したり、ってのができるようになるはず。

こんな感じで、複数のコンテナの単位をまとめて管理することができます。

---

---

---
#その他メモ
##Go言語のRHELへのインストール
ダウンロードして/usr/local以下に展開

```
[root@test11 /Inst_Image/golang]# wget https://dl.google.com/go/go1.13.3.linux-amd64.tar.gz
--2019-10-23 16:37:18--  https://dl.google.com/go/go1.13.3.linux-amd64.tar.gz
dl.google.com (dl.google.com) をDNSに問いあわせています... 172.217.25.206, 2404:6800:4004:81a::200e
dl.google.com (dl.google.com)|172.217.25.206|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 120055279 (114M) [application/octet-stream]
`go1.13.3.linux-amd64.tar.gz' に保存中

100%[======================================================================================================================================================================>] 120,055,279 12.1MB/s 時間 9.3s

2019-10-23 16:37:27 (12.4 MB/s) - `go1.13.3.linux-amd64.tar.gz' へ保存完了 [120055279/120055279]

[root@test11 /Inst_Image/golang]# ls
go1.13.3.linux-amd64.tar.gz

[root@test11 /Inst_Image/golang]# tar -C /usr/local -xzf go1.13.3.linux-amd64.tar.gz
[root@test11 /Inst_Image/golang]# ls -la /usr/local/go/
合計 204
drwxr-xr-x. 10 root root   272 10月 18 07:02 .
drwxr-xr-x. 13 root root   141 10月 23 16:39 ..
-rw-r--r--.  1 root root 55389 10月 18 07:02 AUTHORS
-rw-r--r--.  1 root root  1339 10月 18 07:02 CONTRIBUTING.md
-rw-r--r--.  1 root root 84339 10月 18 07:02 CONTRIBUTORS
-rw-r--r--.  1 root root  1479 10月 18 07:02 LICENSE
-rw-r--r--.  1 root root  1303 10月 18 07:02 PATENTS
-rw-r--r--.  1 root root  1607 10月 18 07:02 README.md
-rw-r--r--.  1 root root   397 10月 18 07:02 SECURITY.md
-rw-r--r--.  1 root root     8 10月 18 07:02 VERSION
drwxr-xr-x.  2 root root  4096 10月 18 07:02 api
drwxr-xr-x.  2 root root    29 10月 18 07:04 bin
drwxr-xr-x.  8 root root  4096 10月 18 07:02 doc
-rw-r--r--.  1 root root  5686 10月 18 07:02 favicon.ico
drwxr-xr-x.  3 root root    18 10月 18 07:02 lib
drwxr-xr-x. 13 root root   193 10月 18 07:02 misc
drwxr-xr-x.  6 root root    76 10月 18 07:04 pkg
-rw-r--r--.  1 root root    26 10月 18 07:02 robots.txt
drwxr-xr-x. 47 root root  4096 10月 18 07:02 src
drwxr-xr-x. 23 root root 12288 10月 18 07:02 test
[root@test11 /Inst_Image/golang]# ls -la /usr/local/go/bin
合計 18188
drwxr-xr-x.  2 root root       29 10月 18 07:04 .
drwxr-xr-x. 10 root root      272 10月 18 07:02 ..
-rwxr-xr-x.  1 root root 15071246 10月 18 07:04 go
-rwxr-xr-x.  1 root root  3548071 10月 18 07:04 gofmt
```

/usr/local/go/binをパスに通す (~/.bash_profile.sh)

```
[root@test11 ~]# go version
go version go1.13.3 linux/amd64
```