Help us understand the problem. What is going on with this article?

Google Cloud Runのポートについて考える

当記事について

2019/11/15にGAになったGCPのコンテナサーバレス実行環境であるGoogle Cloud Runのポートについて理解を深める記事です。
公式ドキュメントのクイックスタートのからポートに関する部分を読み解きつつ解説します。

参考にしたサイト

コンテナ内部で使用するポート

初めに、コンテナ内部で使用しているポートを理会するためにクイックスタートのアプリケーションを見ていきましょう。

/helloworld.go
package main

import (
        "fmt"
        "log"
        "net/http"
        "os"
)

func handler(w http.ResponseWriter, r *http.Request) {
        log.Print("Hello world received a request.")
        target := os.Getenv("TARGET")
        if target == "" {
                target = "World"
        }
        fmt.Fprintf(w, "Hello %s!\n", target)
}

func main() {
        log.Print("Hello world sample started.")

        http.HandleFunc("/", handler)

        port := os.Getenv("PORT")
        if port == "" {
                port = "8080"
        }

        log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}

handler関数

handler関数では、環境変数"TARGET"から値を取得して、Helloの後ろにくっつけて引数のResponseWriterに出力しているのが解ります。環境変数"TARGET"がなければ"World"が入ります。

main関数

main関数では以下の二つのことを行っているのが解ります。
1. ルートでリクエストを待ち受けて、リクエストが来た場合に上のhandler関数を呼び出すようにしています。
2. 環境変数"PORT"から値を取得して取得した値のポート番号でリクエストを受け付けます。環境変数"PORT"がなければ"8080"が入ります。

コンテナ内部で動くアプリケーションは環境変数"PORT"の値で動いているのが解ります。

環境変数"PORT"の中身

Google Cloud Runの内部の環境変数"PORT"がどのようになっているのか、クックスタートにあるサンプルソースのmain関数を以下のようにしてビルド&デプロイしてみます。

/helloworld.go
func main() {
        log.Print("Hello world sample started.")

        http.HandleFunc("/", handler)

        port := os.Getenv("PORT")
        if port == "" {
                port = "8080"
        } else {
            log.Printf("PORT is %s", port)
        }

        log.Printf("Hello world sample is listening on port %s.", port)

        log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
}
$ gcloud builds submit --tag gcr.io/[PROJECT_ID]/helloworld
(省略)
$ gcloud  run deploy --image gcr.io/[PROJECT_ID]/helloworld
(省略)
Service [helloworld] revision [helloworld-XXXXXX-vof] has been deployed and is serving 100 percent of traffic at https://helloworld-XXXXXXXXX-an.a.run.app

デプロイ後、Loggingでログを確認すると次の画像のようになっていました。
Logging

Google Cloud Run上で動くコンテナの環境変数"PORT"は8080であることが解ります。

外部から接続されるポート

外部から接続されるポートを調べるために、実際にcURLを使いアクセスしてみます。

$ curl https://helloworld-XXXXXXXXX-an.a.run.app
Hello World!
$ curl https://helloworld-XXXXXXXXX-an.a.run.app:443
Hello World!
$ curl https://helloworld-XXXXXXXXX-an.a.run.app:80
curl: (35) error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol
$ curl https://helloworld-XXXXXXXXX-an.a.run.app:8080
^C
$ curl https://helloworld-XXXXXXXXX-an.a.run.app:8081
^C

ポート番号443を使用しているのが解ります。8080や8081のように関係のないポートは応答がありませんでした。

外部のポートと内部のポートの紐づけ

外部の443ポートとコンテナ内部の8080ポートが環境変数"PORT"経由で紐づけられているのが解ります。
図示するとこのようになります。

ポートの紐づけ

デプロイ時のコマンドにポートを紐づけるオプションは無いので、Dockerコマンドでいう"-p 443:8080"のようなパラメータはデプロイ時に自動で行ってくれていることになります。

待ち受けポート実装の仕方

デプロイ時に自動で紐づけられるということは、コンテナ内部で待ち受けるポートはGoogle Cloud Runの制約として決められているということになりますね。Cloud Runの制約を読んでみると、コンテナ内部で待ち受けるポートは環境変数"PORT"に収められていると書いてあります。
Google Cloud Runで動かすアプリケーションは環境変数"PORT"を取得してその番号のポートで待ち受けるようにしましょう。

また、既に構築済みのコンテナをGoogle Cloud Runにデプロイする場合は待ち受けポートが何になっているかをきちんと確認するようにしましょう。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした