Docker で作ったWebサーバ(app.py by Flask)を動かすテスト(続)

昨日の続き。

1. GCPで管理するtagをつけたDocker Image を用意する
2. Docker Image を Google Registryにpushする。(docker push)
3. Container を用意する (kubernetesを利用)
4. Google Registry にあるDocker Image を Deploy する
5. ブラウザで接続確認
6. 削除

![20200105-gcpfig.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/790adb9a-cd72-7e4f-1a77-6c7c06cad70e.png)

昨日作成したpython Flaskの簡易ＨＴＴＰサーバをDocker image をGCPで動かしました。昨日は docker run でローカルで動いたものが、GCPで割り当てられたノートで動作し、割り当てられたIPアドレスに外部からアクセスできます。

# 1. GCPをrepository にする Docker Image の作成

Docker でbuild しますが、GCPが管理するTAGをつけます。

```
> docker build --no-cache -t gcr.io/my-project-id/myapp-name .
```

```
> docker images
REPOSITORY                             TAG                 IMAGE ID            CREATED             SIZE
gcr.io/my-projetct-id/myapp-name  latest              0fbd3904998e        5 minutes ago       143MB
```

# 2. Docker Image を クラウドにpush する

最初、これを忘れていてはまりました。ローカルにある docker image をGoogle Cloud Registry にupload します。なお、勉強不足ですが

 - 認証が成立している必要があるそうですが、そこは下記のコマンドでは問題にならず。
 - tag 名で:v1 や :latest のように書くことが多いようですが、何も書かなくても今回は動作しました。

```
> gcloud auth configure-docker
> docker push gcr.io/my-project-id/myapp-name
```

なお現在のproject 名は以下で確認できます。

```
> gcloud config list
```

# 3. Container を用意する

## Kubernetes の環境を用意

### Kubernetes Engin APIを有効にする

コマンドラインで行う方法が分からなかったので、素直に console.cloud.google.com から設定を行いました。API の検索で Kubernetes と入れると出てきます。

### Container が集まった Cluster を用意する

Cluster でノード数を指定してContainer を用意します。Zone を指定する必要があるので、[こちら](https://cloud.google.com/compute/docs/regions-zones/?hl=ja#available)をみて、データセンターが東京にある`asia-northeast1`を選びました。少し時間がかかり警告も出ますが、Created ... と言われます。

```
> gcloud container clusters create myprog-cluster --num-nodes=2 zone=asia-northeast1
...
Creating cluster myapp-cluster in asia-northeast1-a... Cluster is being health-checked (master is healthy)...done.
Created [https://container.googleapis.com/v1/projects/my-project-id/zones/asia-northeast1-a/clusters/myprog-cluster].
```

あるいは

```
> gcloud container clusters get-credentials myprog-cluster --zone=asia-northeast1
```

Container が instance として存在することを確認します。

```
> gcloud compute instances list
NAME                                          ZONE               MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
gke-myprog-cluster-default-pool-aaa0000-9n0s  asia-northeast1-a  n1-standard-1               10.146.0.3   34.84.107.116  RUNNING
gke-myprog-cluster-default-pool-aaa0001-rv0r  asia-northeast1-a  n1-standard-1               10.146.0.2   34.84.184.13   RUNNING
```

# 4. Deploy する

### Docker image を pull する

用意したDocker Container にDocker Image をpull します。

```
kubectl create deployment myserver --image=gcr.io/my-project-id/myapp-name
```

動いていることを確認します。動いているinstanceを pod と呼ぶようです。（この解釈合っている？^^;)

```
> kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
myserver-000a0aa000-a0aa   1/1     Running   0          17m                             
```

最初 docker push していなかったのでGCP側にDocker image が無かったため、STATUSが`ImagePullBackOff`でした。image がないのでpull できず、再度pullしようとします、ということらしいです。

### 外部からアクセスするためのIPアドレスとポート

```
kubectl expose deployment myservice --type=LoadBalancer --port 80 --target-port 8000
```

以下でpod (docker instance)に外部から参照できるＩＰアドレス(EXTERNAL-IP)が割り振られているのを確かめます。しばらく（１分くらい？）<pending> となっているので、しばらく待ちましょう。

```
> kubectl get service
NAME         TYPE           CLUSTER-IP     EXTERNAL-IP    PORT(S)        AGE
myservice    LoadBalancer   10.xxx.xxx.xx  35.xxx.xxx.xxx 80:30624/TCP   66sm
```

# 5. 接続

昨日と同様に、ブラウザで　35.xxx.xxx.xxx にアクセスするか、以下で確認できます。

```
> curl http://35.xxx.xx.xx

StatusCode        : 200
StatusDescription : Ok
Content           : <html>
                    <head>
                    <meta http-equiv='refresh' content='1; url=http://35.xxx.xx.xx/&arubalp=b00000e2-0000-0a00-0a0a-00a0000000'>
                    </head>
                    </html>

RawContent        : HTTP/1.1 200 Ok
                    X-Frame-Options: SAMEORIGIN
                    X-XSS-Protection: 1; mode=block
                    X-UA-Compatible: IE=edge;IE=11;IE=10;IE=9
                    Connection: close
                    Content-Length: 139
                    Content-Type: text/html
                    Date: Sun, 05...
Forms             : {}
Headers           : {[X-Frame-Options, SAMEORIGIN], [X-XSS-Protection, 1; mode=block], [X-UA-Compatible, IE=edge;IE=11;IE=10;IE=9], [Connection, close]...}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 139
```

やったー！^^)/

# 6. 削除

Kubernetes service (pod, docker instanceのこと?)を削除し、Cluster も削除します。

```
> kubectl delete service myservice
> gcloud container clusters delete myprog-cluster --zone=asia-northeast1-a
```

# 備忘録

なんとか一通りはできた。。。次はDocker image にGCP SDK をインストールして、GCP の storage にアクセスしてファイルの保存とかできるようになりたいな。

### 参考

基本的に、GCP Tutorialの[コンテナ化されたウェブ アプリケーションのデプロイ](https://cloud.google.com/kubernetes-engine/docs/tutorials/hello-app?hl=ja)をアレンジしながら行いました。

## そのほか

なお、GCP のレポジトリにdocker push するときに、`gcloud docker -- push ... `とする方法もＷＥＢで見かけましたが、こちらはサポートされなくなるようです。

```
> gcloud docker --  push gcr.io/my-project-id/myprog
WARNING: `gcloud docker` will not be supported for Docker client versions above 18.03.

As an alternative, use `gcloud auth configure-docker` to configure `docker` to
use `gcloud` as a credential helper, then use `docker` as you would for non-GCR
registries, e.g. `docker pull gcr.io/project-id/my-image`. Add
`--verbosity=error` to silence this warning: `gcloud docker
--verbosity=error -- pull gcr.io/project-id/my-image`.

See: https://cloud.google.com/container-registry/docs/support/deprecation-notices#gcloud-docker
```