【GCP & Go】新年なのでGoで作成したサーバーをCloudRunでデプロイしてみました。


## はじめに
私は、3次請のSESで金融系のプロジェクトに携わっています。
（はよ、脱出したい；；）
休日に勉強する過程で得た知識をアウトプットする目的で
本記事を投稿しようと思いました。

## 今回実行した内容
Goで作成した簡単なWebサーバーをGoogle Cloud Pratform上でデプロイする
Dockerの学習もしたいと考えているため、今回はGCPのCloudRunを用いてデプロイしました
## 手順

#### Googleにログインしてプロジェクトを作成する
![スクリーンショット 2025-01-11 14.38.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/855814/adeffee9-a788-7bb6-4baf-8e2fd887ffd8.png)
※プロジェクトIDはマスキング処理をしています。

完成したら、以下のような形で表示されます。
![スクリーンショット 2025-01-11 14.27.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/855814/3897cb84-3fca-1c13-0dbb-317b59e43167.png)
プロジェクトIDはデプロイする際に必要となるので控えておきましょう

#### SDKのインストール&セットアップ
以下のリンクから自分が使う環境のSDKをインストールして`gcloud`コマンドを使用できるようにします。

https://cloud.google.com/sdk/docs/install?hl=JA


以下のコマンドを実行して、プロジェクトをセットします。
```
$ gcloud config set project [コンソールに記載のプロジェクト名]
```
正常に終了したら、認証を行います。
以下のコマンドを実行したら、ブラウザが起動するので
認証を行います。
```
$ gcloud auth login
```

##### Goでサーバーを記述
今回はクラウド上でデプロイすることが目的なので
立ち上げるサーバーは簡単なものとします。
ターミナル上で`go run main.go`と実行し、ブラウザから`localhost:8080`にアクセスすると、Hello, World!と表示されます。
※ですので、ゴールはクラウドでデプロイした時のアドレスからアクセスしても同じように表示されることです

```main.go
package main

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

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, World!")
}

func main() {
	http.HandleFunc("/", handler)
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	fmt.Printf("サーバーを起動します。ポート%sで待ち受けています...\n", port)
	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatal(err)
	}
}

```

デプロイ用のDockerfileを記述します
色々な記事を参考にしてDockerfileを記述しましたが
go言語のverやgo buildの後ろの「http-server」をコピペしてしまったせいで
うまく動かなかったりしました。参考にする場合は注意してください。

```Dockerfile

FROM golang:1.22-alpine as builder

WORKDIR /app
COPY . .

RUN go mod init http-server
RUN go mod tidy


ENV GOOS=linux
ENV GOARCH=amd64
ENV CGO_ENABLED=0
RUN go build -o http-server .


FROM alpine:latest

WORKDIR /app
COPY --from=builder /app/http-server .


RUN chmod +x /app/http-server

EXPOSE 8080


ENV PORT=8080

CMD ["/app/http-server"]
```

 これで一通り実行に必要な準備は完了しました。



 #### イメージをビルド
Dockerfileを使用して、Dockerイメージを作成します。
Google Cloud Runにデプロイする場合は
タグに「gcr.io/[プロジェクト名]/[イメージ名]」と記述します

 ```
 docker build -t gcr.io/[プロジェクト名]/http-server .
 ```

 #### イメージをプッシュ
Dockerイメージをプッシュして、Google Cloud Runで実行できるようにします。
 
 ```
 docker push gcr.io/[プロジェクト名]/http-server
 ```
おそらく、初めてCloud Runを利用する場合は以下のエラーメッセージが出ると思います。
これはGCPがコンテナやパッケージなどを管理するためのレポジトリサービスとなります。エラーメッセージにあるリンクから「有効」にして、再度ビルドしましょう。
```
denied: Artifact Registry API has not been used in project 346078466758 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/artifactregistry.googleapis.com/overview?project=346078466758 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry. 
```

最後に以下のコマンドを実行します。
```
gcloud run deploy http-server \
  --image gcr.io/named-purpose-423702-p6/http-server \
  --platform managed \
  --region asia-northeast1 \
  --allow-unauthenticated
```

ブラウザでHello, World!が表示されていることを確認


## まとめ
文字に起こすと簡単だと思いましたが、苦労が多かったです。
- Dockerの知識
　└ Dockerfileの記述方法
　└ コンテナをビルドした際の大枠の理解
- クラウドの知識
　└ IAMポリシーなどの認証するための権限付与がいまいち理解できなかった、、


ただ、クラウド上にデプロイすることはできたので、次に作りたいものへ確実に前進はしています。
2025年はアウトプットを増やす一年にしたいと考えていますのでこれからも記事の投稿は続けていくぞー！！