背景:IoT Platformの評価として、ThinsBardを使いたい。ThinsBoardを無料で使うには、自分でサーバを仕立てる必要あり。ちょっと試すだけならGCPの無料サービス枠があり、Cloud Runを使えばDockerコンテナも走らせられる
課題:Cloud Runを使ったことがないので、python+flaskの組み合わせでDockerイメージを作って Cloud Run上で走らせてみる
結論:python+flaskによるWebServer用コンテナは稼働できた
詳細:
(前提)
Regionはasia-northeast1を使います。また、Ubuntu環境にgcloud CLIがインストール済み、GCP上の評価用プロジェクトとして、aaa-demoを設定済み
CloudRunで実行するコンテナはGCPのArtifact Repository(以降GAR)に登録されているイメージが基本となる(他から取ってくるのも可能らしいが)
まず GAR上にリポジトリを作成する。
リポジトリ名は仮にmyrepoとする
gcloud artifacts repositories create myrepo --location=asia-northeast1 --repository-format=docker
ローカル環境でDockerビルドする。テストで使ったdockerfileとapp.py(flask用サンプルコード)は以下
file: dockerfile
FROM alpine RUN apk update; apk add python3; apk add py3-flask COPY . /app WORKDIR /app CMD ["/usr/bin/python3", "app.py"]
file:app.py
#!/usr/bin/python3 from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!" if __name__ == "__main__": app.run(host="0.0.0.0", debug=False, port=8080)
portは8080でないとどうも正常に起動されない。host="0.0.0.0"を指定することで自サーバ外からの接続を受け付け可にする
dockerでpushする前に認証関連を設定する
gcloud auth configure-docker asia-northeast1-docker.pkg.dev
docker imageをビルド、レポジトリにPUSHする
file: build.sh
#!/bin/sh REGION=asia-northeast1 PROJECT_ID=aaa-demo DOCKER_IMAGE=flask_image01 GAR_REPO=myrepo IMAGE=${REGION}-docker.pkg.dev/${PROJECT_ID}/${GAR_REPO}/${DOCKER_IMAGE} echo "docker build ./ -t ${IMAGE}" docker build ./ -t ${IMAGE} echo "docker push ${IMAGE}" docker push ${IMAGE}
レポジトリに登録されたimage を使ってコンテナを起動する
file: run.sh
#!/bin/sh PROJECT_ID=aaa-demo DOCKER_IMAGE=flask_image01 SERVICE_NAME=flask02try GAR_REPO=myrepo REGION=asia-northeast1 IMAGE=asia-northeast1-docker.pkg.dev/${PROJECT_ID}/${GAR_REPO}/${DOCKER_IMAGE} echo "gcloud run deploy ${SERVICE_NAME} --image ${IMAGE} --platform=managed --project=${PROJECT_ID} --region ${REGION}" gcloud run deploy ${SERVICE_NAME} --image ${IMAGE} --platform=managed --project=${PROJECT_ID} --region ${REGION}
GCPコンソールを参照するとコンテナが起動されている。
アクセス用URLも書かれているのでそれにアクセスする。
Hello Wold!と表示された。これにより、GCPのコンテナ上でPython+Flaskが動いていることが分かる
FireWallを設定しなくてもincoming:443はすでに許可されているのか??コンソールで再確認すると、 ingress incoming ANYが設定されているので、443 全通しと思われる。
現在稼働中のコンテナ(サービス)を確認
$ gcloud run services list SERVICE REGION URL LAST DEPLOYED BY LAST DEPLOYED AT ✔ flask02try asia-northeast1 https://flask02try-441441441877.asia-northeast1.run.app hoge@gmail.com 2024-10-27T05:10:54.367925Z
(gcloud run の run とは実行コマンドのrunではなく、サービス名(Cloud Run)のrunであった)
コンテナ情報を表示
$ gcloud run services describe flask02try --region asia-northeast1 ✔ Service flask02try in region asia-northeast1 URL: https://flask02try-441441441877.asia-northeast1.run.app Ingress: all Traffic: 100% LATEST (currently flask02try-00001-pgn) Last updated on 2024-10-27T05:10:54.367925Z by hoge@gmail.com: Revision flask02try-00001-pgn Container None Image: asia-northeast1-docker.pkg.dev/aaa-demo/myrepo/flask01 Port: 8080 Memory: 512Mi CPU: 1000m Startup Probe: TCP every 240s Port: 8080 Initial delay: 0s Timeout: 240s Failure threshold: 1 Type: Default Service account: 441441441877-compute@developer.gserviceaccount.com Concurrency: 80 Max Instances: 100 Timeout: 300s
動作確認を終えたのでコンテナ削除
$ gcloud run services delete flask02try --region asia-northeast1 Service [flask02try] will be deleted. Do you want to continue (Y/n)? y Deleting [flask02try]...done. Deleted service [flask02try].
■課題
・ FWの設定によるのか、全通し状態なので、適切な制限がかかるようにする
・ThinsBoardをコンテナ上で走らせる場合、サーバとDBが別のコンテナになる。コンテナ間通信をどうやったら実現できるのか調査必要(内部DNAにDBサーバを登録してFQDN経由でアクセスすることになるのではなかろうか)
→同一VM(?)上で複数のDockerコンテナが同居することになるので、localhost:
→永続化のために、Cloud SQLとか、Cloud Strageが提供されているようだ。これらは基本料金高そうだ。正しい手順の永続化はやめて、コンテナを落とす前にDB内データをダンプして、データをS3に転送するとか。。(素人根性の運用)
CloudStrageの月額費用
東京(asia-northeast1) $0.023 (GB 単位/月)
■関連資料
ThingsBoardのインストール手順
Installing ThingsBoard using Docker (Linux or Mac OS) | ThingsBoard Community Edition