Docker (& Kubernetes)

「15Stepで習得 Dockerから入るKubernetes コンテナ開発からK8s本番運用まで」を学習用に購入したので、学習内容の備忘録。

>MIT License
Copyright (c) 2019 Maho Takara
https://github.com/takara9/codes_for_lessons/blob/master/LICENSE

# VirtualBox 6.0.14 install
Windows 10 にインストール

# Vagrant (2.2.6) install
https://www.vagrantup.com/downloads.html からインストール

# 仮想環境構築

```powershell
> git clone https://github.com/takara9/vagrant-minikube
> cd vagrant-minikube
> vagrant up

Bringing machine 'minikube' up with 'virtualbox' provider...
==> minikube: Box 'ubuntu/xenial64' could not be found. Attempting to find and install...
    minikube: Box Provider: virtualbox

 ~ ~ ~

Bringing machine 'minikube' up with 'virtualbox' provider...
==> minikube: Box 'ubuntu/xenial64' could not be found. Attempting to find and install...
    minikube: Box Provider: virtualbox

> vagrant halt  # 停止する場合
> vagrant destroy  # 削除する場合
> vagrant ssh  # 仮想マシンに入る
```

# Minikube start/stop

```bash:vagrant_ssh
$ sudo minikube start --vm-driver=none
$ sudo minikube stop  # minikube停止
$ sudo minikube delete  # minikube削除
$ kubectl get pod --all-namespaces
NAMESPACE     NAME                               READY   STATUS    RESTARTS   AGE
kube-system   coredns-5644d7b6d9-nnlsm           1/1     Running   0          111s
kube-system   coredns-5644d7b6d9-z9bjv           1/1     Running   0          9m12s
kube-system   etcd-minikube                      1/1     Running   0          8m24s
kube-system   kube-addon-manager-minikube        1/1     Running   0          8m42s
kube-system   kube-apiserver-minikube            1/1     Running   0          8m2s
kube-system   kube-controller-manager-minikube   1/1     Running   0          8m23s
kube-system   kube-proxy-rblpt                   1/1     Running   0          9m12s
kube-system   kube-scheduler-minikube            1/1     Running   0          8m27s
kube-system   storage-provisioner                1/1     Running   0          8m41s
```

# DashboardとGrafanaへのアクセス
```bash:vagrant_ssh
$ sudo minikube addons enable metrics-server
$ sudo minikube dashboard --url

# プロキシ起動
$ kubectl proxy --address="0.0.0.0" -p 8001 --accept-hosts='^*$' -n kube-system

# VirtualBox 6.Xでやってみた時、下記はenable failed: property name "heapster" not foundのエラーで通りませんでした。5.Xの時はなぜか実行できた。
$ sudo minikube addons enable heapster

```

ブラウザからDashboardへアクセス:
http://172.16.10.10:8001/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/

Vagrant 仮想マシンのIPアドレス：172.16.10.10
![1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428410/c0029dbc-fdae-7374-bd02-b126a7a1d64e.jpeg)

```bash:vagrant_ssh
$ kubectl get svc --all-namespaces
NAMESPACE              NAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
default                kubernetes                  ClusterIP   10.96.0.1       <none>        443/TCP                  69m
kube-system            heapster                    ClusterIP   10.105.223.93   <none>        80/TCP                   65m
kube-system            kube-dns                    ClusterIP   10.96.0.10      <none>        53/UDP,53/TCP,9153/TCP   69m
kube-system            metrics-server              ClusterIP   10.101.33.98    <none>        443/TCP                  65m
kube-system            monitoring-grafana          NodePort    10.96.232.116   <none>        80:30002/TCP             65m
kube-system            monitoring-influxdb         ClusterIP   10.102.60.44    <none>        8083/TCP,8086/TCP        65m
kubernetes-dashboard   dashboard-metrics-scraper   ClusterIP   10.107.49.65    <none>        8000/TCP                 64m
kubernetes-dashboard   kubernetes-dashboard        ClusterIP   10.99.221.155   <none>        80/TCP                   64m

$ sudo minikube ip
10.0.2.15

$ curl http://10.0.2.15:30002
<!DOCTYPE html>
<html lang="en">
# 略
```

Local PC からは http://172.16.10.10:30002 でGrafanaのGUIへアクセス確認だけ。
（heapster addできない場合はgrafanaもaddされない）

<img width="617" alt="1.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428410/f4f660c9-1d72-60ff-b078-8a42982f4af9.jpeg">

# Hello world
[Hello Minikube 参考](https://kubernetes.io/ja/docs/tutorials/hello-minikube/)

```bash:vagrant_ssh
# Deploymentの作成
$ kubectl create deployment hello-node --image=gcr.io/hello-minikube-zero-install/hello-node
$ kubectl get pods  # 作成に10mくらいかかった
NAME                          READY   STATUS    RESTARTS   AGE
hello-node-7676b5fb8d-c5f6d   1/1     Running   0          21m

$ kubectl get events
LAST SEEN   TYPE     REASON                    OBJECT                             MESSAGE
<unknown>   Normal   Scheduled                 pod/hello-node-7676b5fb8d-c5f6d    Successfully assigned default/hello-node-7676b5fb8d-c5f6d to minikube
10m         Normal   Pulling                   pod/hello-node-7676b5fb8d-c5f6d    Pulling image "gcr.io/hello-minikube-zero-install/hello-node"
78s         Normal   Pulled                    pod/hello-node-7676b5fb8d-c5f6d    Successfully pulled image "gcr.io/hello-minikube-zero-install/hello-node"
78s         Normal   Created                   pod/hello-node-7676b5fb8d-c5f6d    Created container hello-node
77s         Normal   Started                   pod/hello-node-7676b5fb8d-c5f6d    Started container hello-node
10m         Normal   SuccessfulCreate          replicaset/hello-node-7676b5fb8d   Created pod: hello-node-7676b5fb8d-c5f6d
10m         Normal   ScalingReplicaSet         deployment/hello-node              Scaled up replica set hello-node-7676b5fb8d to 1
47m         Normal   NodeHasSufficientMemory   node/minikube                      Node minikube status is now: NodeHasSufficientMemory
47m         Normal   NodeHasNoDiskPressure     node/minikube                      Node minikube status is now: NodeHasNoDiskPressure
47m         Normal   NodeHasSufficientPID      node/minikube                      Node minikube status is now: NodeHasSufficientPID
47m         Normal   RegisteredNode            node/minikube                      Node minikube event: Registered Node minikube in Controller
47m         Normal   Starting                  node/minikube                      Starting kube-proxy.
45m         Normal   NodeNotReady              node/minikube                      Node minikube status is now: NodeNotReady
40m         Normal   Starting                  node/minikube                      Starting kubelet.
40m         Normal   NodeHasSufficientMemory   node/minikube                      Node minikube status is now: NodeHasSufficientMemory
40m         Normal   NodeHasNoDiskPressure     node/minikube                      Node minikube status is now: NodeHasNoDiskPressure
40m         Normal   NodeHasSufficientPID      node/minikube                      Node minikube status is now: NodeHasSufficientPID
40m         Normal   NodeNotReady              node/minikube                      Node minikube status is now: NodeNotReady
40m         Normal   NodeAllocatableEnforced   node/minikube                      Updated Node Allocatable limit across pods
40m         Normal   NodeReady                 node/minikube                      Node minikube status is now: NodeRe


$ kubectl get deployments
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
hello-node   1/1     1            1           24m

# service作成
$ kubectl expose deployment hello-node --type=LoadBalancer --port=8080
service/hello-node exposed

$ kubectl get services
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
hello-node   LoadBalancer   10.96.235.223   <pending>     8080:32289/TCP   2s
kubernetes   ClusterIP      10.96.0.1       <none>        443/TCP          54m

$ minikube service hello-node
$ kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
hello-node-7676b5fb8d-c5f6d   1/1     Running   0          21m
```

http://172.16.10.10:32289/ へアクセスするとHello World!が表示された。
<img width="57" alt="1.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428410/f2da8058-a93d-e201-86c4-dd00e3bbe4bc.jpeg">

## クリーンアップ

```bash:vagrant_ssh
$ kubectl delete service hello-node
service "hello-node" deleted
$ kubectl delete deployment hello-node
deployment.apps "hello-node" deleted  # podもすぐ後に消えた。
```

# Docker

```bash:vagrant_ssh
# Image pull
$ docker pull centos:7
7: Pulling from library/centos
ab5ef0e58194: Pull complete
Digest: sha256:4a701376d03f6b39b8c2a8f4a8e499441b0d567f9ab9d58e4991de4472fb813c
Status: Downloaded newer image for centos:7

# Image表示
$ docker images
REPOSITORY                                      TAG                 IMAGE ID            CREATED             SIZE
centos                                          7                   5e35e350aded        3 weeks ago         203MB

# Docker実行
# docker run -it --name <CONTAINER_NAME> <REPOSITORY>:<TAG>

# この時別ターミナルから`docker ps` で動いているContainerを表示させられる。
$ docker run -it --name test1 centos:7 bash
CentOS Linux release 7.7.1908 (Core)
[root@5834070bf9fc /]# exit
exit

# container表示例
$ docker ps -a
CONTAINER ID        IMAGE                                     COMMAND                  CREATED             STATUS                        PORTS               NAMES
5834070bf9fc        centos:7                                  "bash"                   2 minutes ago       Exited (127) 33 seconds ago                       test1
6f57295c4054        hello-world                               "/hello"                 10 minutes ago      Exited (0) 10 minutes ago                         clever_bose

# 実行中のコンテナにシェルを実行する
$ docker exec -it <CONTAINER_NAME> bash

# log表示
$ docker logs 5834070bf9fc
[root@5834070bf9fc /]# cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)

# Dockerの停止/強制終了
$ docker stop <CONTAINER_ID>
$ docker kill <CONTAINER_ID>

# Dockerの再スタート
# -i オプションで標準出力/エラーをコンソールへ出力する。
$ docker start -i <CONTAINER_ID>|<CONTAINER_NAME>

# Docker commit
# DockerのImageをRepositoryへ保存する。
$ docker commit <CONTAINER_ID> | <NAMES> <REPOSITORY>:<TAG>

$ docker images
REPOSITORY                                      TAG                 IMAGE ID            CREATED             SIZE
centos                                          7-git               5d7a0ddd4d1f        4 minutes ago       408MB

# Remote repository へ push
$ docker login
$ docker push <REMOTE_REPOSITORY>:<TAG>

# コンテナ削除
$ docker rm <CONTAINER_ID>

# イメージ削除
$ docker rmi <IMAGE_ID>

```

```bash
# Container の IP、ステータスなどをJSON形式で表示する。
$ docker inspect <CONTAINER_ID>

# JSONからIP情報を取得して出力
$ docker inspect --format='{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' bafc23a2a3db
172.17.0.7
```

# Network
docker run の時、
 --networkでネットワークを指定しないとコンテナは bridge に自動で接続される。
`-p`：コンテナのポートをコンテナホストのIPアドレス上で公開できる。
`-d`：バックグラウンドで実行
`-e`：環境変数の指定

バックグラウンドで実行：コンテナはターミナルから切り離された状態になるので、標準出力、標準エラー出力はターミナルに出力されなくなる。ログに書かれるのみとなる。

```bash
# バックグラウンドで動いているコンテナをターミナルにつなぐ。
# --sig-proxy=false: Ctrl+C入力でもコンテナ自体は停止しない
$ docker attach --sig-proxy=false <CONTAINER_NAME>
```

```bash
# Network 作成
# $ docker network create <NETWORK_NAME>
$ docker network create my-network

# Webserver起動
$ docker run -d --name webserver1 --network my-network nginx:latest

# Port公開
$ docker run -d --name webserver1 -p 8080:80 nginx:latest
```


```bash
$ docker network create apl-net

# MySqlサーバコンテナ 起動
docker run -d --name mysql --network apl-net -e MYSQL_ROOT_PASSWORD=qwerty mysql:5.7

# AP サーバコンテナの起動
$ docker run -d --name php --network apl-net -p 8080:80 -e MYSQL_USER=root -e MYSQL_PASSWORD=qwerty php-apl:0.1
```

`http://172.16.10.10:8080/`へアクセス
<img width="342" alt="1.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428410/fc61941f-c9f6-6132-b7b0-7a84fa608faa.jpeg">


# Build
## 永続ボリューム

* ホストのフォルダパスは絶対パスで指定する。
* 同一ゾーンのサーバからしかマウントできない。

```bash
$ mkdir <FOLDER_NAME_IN_HOST>
$ docker build --tag <REPOSITORY>:<TAG> -f <DOCKER_FILE_NAME> .
$ docker run -it --name <CONTAINER_NAME> -v `pwd`/<FOLDER_NAME_IN_HOST>:/<PATH_IN_CONTAINER> <REPOSITORY>:<TAG>
```