Google Compute Engine(GCE)にGo(Echo)で作成したAPIをデプロイする

最近仕事でGCEにGoのEchoで作ったAPI資産をデプロイする必要がありました。

なんでわざわざVM？コンテナでよくない？というお話はあるのですが、色々な関係でテスト環境だけそうなってしまったので仕方がないです。

わざわざ記事に残す意味はあるかとも思いましたが、何となく今後も似たようなシチュエーションが出てきそうだったので、自分のために備忘録的な感じで残そうかと思います。

## インスタンスを立ち上げる

まずはデプロイするインスタンスを立ち上げるところです。

これは細かく書くほどでもないと思うので割愛します。

```
# SSH
gcloud compute ssh --project [プロジェクト名] --zone [ゾーン名] [インスタンス名]

# 初期化
sudo apt-get update && sudo apt-get install

# 時刻の変更
sudo timedatectl set-timezone Asia/Tokyo
date

```

## Goのインストール

まずはGoをサーバーにインストールします。

```
sudo apt install -y golang-go
```

次に簡単なgoのアプリケーションを作成して、ブラウザで見れるようにしましょう。testappディレクトリを作成し、その中にmain.goを作成します。

```
# 適当なディレクトリに移動
cd ~

# ディレクトリの作成
mkdir testapp
cd testapp

# go.mainの作成
touch go.main
```

そしてgo.mainを編集して下記のようにします。

```go:main.go
package main

import (
	"net/http"
	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
)

func main() {
	e := echo.New()

	// Middleware
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())

	// Route
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, Echo!")
	})

	// Start server
	e.Start(":8080")
}
```
この状態で一度動かしてみましょう

```
# Goモジュールの初期化
go mod init testapp
go mod tidy

# 起動
go run main.go
   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.12.0
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:8080

```
こんな感じでローカルサーバーが立ち上がれば一旦OKです。
この状態でローカルサーバーを立ち上げたまま、もう一つSSHクライアントを立ち上げSSHし、localhost:8080にリクエストを投げると、main.goの通りのレスポンスが帰ってくるはずです。

```
# 先ほど実行したローカルサーバーはそのままの状態で、別SSHクライアントで実行
curl http://localhost:8080
Hello, Echo!
```

## Apacheのインストールと設定

### Apacheのインストール

今回はApacheを使用することとします。

Goの場合標準ライブラリに組み込まれているHTTPサーバー機能を使えば別にApacheなどのウェブサーバーは不要なのですが、セキュリティ・HTTPS化・htmlファイルの設置等考えて今回はApacheを使用することとします。

```
sudo apt-get -y install apache2
```

とりあえずこれでApacheのデフォルトページが見れるはずです。

見れない場合はファイアーウォールで80番ポートを許可しているかの確認と、リクエストしているURLがhttpsになっていないか確認してみてください。
（GCPコンソールからアクセスすると勝手にhttps://から始まるURLに飛ばされて何も表示されないので注意してください）


### リバースプロキシモジュールの有効化

今回はApacheをリバースプロキシとして使用するので、そのための設定を行います。

```
# リバースプロキシモジュールの有効化
sudo a2enmod proxy
sudo a2enmod proxy_http
```

次に設定ファイルに以下の内容を追加します。

```
<VirtualHost *:80>
    ServerName example.com # ドメイン名 or IPアドレス

    ProxyPreserveHost On                      
    ProxyPass / http://localhost:8080/        
    ProxyPassReverse / http://localhost:8080/ 

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
```

そしてApacheの設定を適用するためにApacheを再起動すると、ServerNameに指定したリクエストは全てhttp://localhost:8080に流され、http://localhost:8080で起動しているGoアプリが動くようになります。

```
sudo systemctl restart apache2
```

![スクリーンショット 2024-07-18 14.12.16（3）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724713/9c36386b-a80c-f0a1-8f87-89093d53fdef.png)

ApacheにGoアプリケーションをデプロイすることができました！

## Goの実行ファイルを動かす＆プロセスの永続化

このままだとずっと`go run main.go`しないといけないので色々と困りますよね。

また一般的にはGoは実行ファイルをデプロイするので、最後に実行ファイルをデプロイするところと、プロセスを永続化する部分を設定していきたいと思います。

まずは実行ファイルを用意します。先ほど作成したサンプルGoアプリのディレクトリで下記コマンドでGoの実行ファイルを作成します。

```
cd ~/testapp
go build -o testapp
```

こうすると`testapp`というファイルを作成することができたと思います。
これが実行ファイルで、サーバーを立ち上げる時は`./testapp`で立ち上げることができます。

```
./testapp

   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.12.0
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:8080

```

### systemdの設定

Goの永続化にはLinuxで使用されるサービスマネージャのsystemdを使用します。

まずサービスファイルを作成します。サービスファイルの場所はお使いのOS等によると思いますが、私の場合`/etc/systemd/system`配下だったので、`/etc/systemd/system/go-app.service`として作成しました。

またこの時実行ファイルのパスを求められます。
一旦テストで実行ファイルを`/opt/testapp/out`として作成しました。

```
# 実行ファイルの作成
cd ~/testapp
go build -o out

# 実行ファイルの移動
mkdir /opt/testapp
mv out /opt/testapp/out
```

```:/etc/systemd/system/go-app.service
[Unit]
Description=My Go Application
After=network.target

[Service]
# 実行ファイルの絶対パス
ExecStart=/opt/testapp/out
WorkingDirectory=/opt/testapp
Restart=always
# Apacheユーザー
User=www-data
Group=www-data
Environment=PORT=8080

[Install]
WantedBy=multi-user.target
```

その後指定したユーザーにファイルの実行権限をつけた後、サービスのリロードと起動を行います。

```
# 権限
sudo chown www-data:www-data /opt/testapp/out
sudo chmod +x /opt/testapp/out

# サービスのリロードと起動
sudo systemctl daemon-reload
sudo systemctl start go-app

# ステータス確認
sudo systemctl status go-app
```

最後のコマンドでステータスがactiveとなっていれば完了です。これでgoのプロセスを永続化することができました！

### ちなみに

`sudo systemctl start go-app`でエラーが出た時、下記コマンドが役に立ったので記載しておきます。

```
# 変更のリロード
sudo systemctl daemon-reload

# サービスの開始
sudo systemctl start go-app

# サービスのステータス確認
sudo systemctl status go-app

# 起動ログの確認
sudo journalctl -u go-app
```


## 結構簡単だった

とても簡単にデプロイまで完了できました。実行ファイルを置きさえすれば動くのは本当に素晴らしいですね。

何か間違っている部分などあればどんどん指摘してモラレバと思います。ありがとうございました！