今さら？docker on herokuでお手軽&格安なRDB構成のAPIサーバ(golang)を構築できないか試した話

Gakuです。

ここ最近WebはVue+Firestoreの構成で半年ほどやっていたのですが、どうしてもNoSQLのみのDB設計は慣れることができず、RDB使いたいな〜と思いはじめました。
RDBを使う構成だと、Serverlessな構成では基本的に組めないので、AWSやGCPで常時稼働系のサービスをレンタルすることになります。しかし、個人開発としては費用的に少しお高いです。

2、３日いろいろ考えた結果、herokuを利用すれば比較的安価に、スケール性のあるRDBを利用した構成を組むことができるのではないかと思い試したところ、結構良い感じなったので、その方法を備忘録として残したいと思います。
## 対象者
・Firebase[NoSQL]疲れた。。。RDBで組んでいきたい!という人
・VPS？めんどくせぇ。インフラのことはあんまり考えたくないし、スケール性はほしい！という人
・herokuはrailsの記事が多いけど、golangが好き！な人(今回はgolangで組んで行きます。)

## 準備
### 1.GitHubにリポジトリを作成します。
GitHubとherokuを連携すると、対象ブランチにコードをupするだけで自動的にheroku側でdeployしてくれるように今回は設定します。なので、最初にGitHubリポジトリを作成しlocalにクローンしておきましょう。
また、stagingとproduction環境を作成しdeployしますので、「stagingブランチ」と「productionブランチ(master)」を予め作っておきましょう。

### 2.heroku上にappを作成する
herokuのDashboardでpiplineを作成し、その中にappを作成します。(こうすることで、staging環境とproduction環境を一つにまとめることができます。)
![スクリーンショット 2019-01-18 13.16.13.png](https://qiita-image-store.s3.amazonaws.com/0/47132/f5f75d5e-4402-35d9-8df5-4df173c394e3.png)
【New→Create New piplineをクリック】
![スクリーンショット 2019-01-18 13.20.39.png](https://qiita-image-store.s3.amazonaws.com/0/47132/a54d73d5-e33d-fb91-846f-579de3fa63ec.png)
【Pipeline nameに名前、Connect to GitHubに先程作成したGitHubリポジトリを設定し、Create pipelineをクリックします。】
![スクリーンショット 2019-01-18 13.27.16.png](https://qiita-image-store.s3.amazonaws.com/0/47132/f83afac8-51b5-ba92-9511-64a31f65f9bf.png)

【Pipelineが作成されたらStagingとProductionの「Add app」をクリックして、それぞれにappを作成します。】
![スクリーンショット 2019-01-18 13.33.52.png](https://qiita-image-store.s3.amazonaws.com/0/47132/c3cf58ac-9757-5a44-7879-f747c0cb4cde.png)
【作成されたappの右上にある「<>」クリックし、Configure automatic deploys...を設定することで、githubの対象ブランチにupした瞬間、自動的にdeployすることが可能なので設定しておきます。】
[ここまでの注意点]
※1　Heroku CIをEnableにしてしまうと、Pipeline毎に毎月1000円(押した瞬間っぽい？)+利用に応じた課金がかかります。
CIを使わない場合は、間違ってEnableにしないよう注意しましょう。
※2 今回は触れませんがReview appsという機能も設定をミスったり、プルリク出して放置とかすると想定外な料金が発生しそうなので注意しましょう。(良い機能なので、チーム案件であれば用法用量守って使えば強力っぽい。

## 実装
localにcloneしたGithubリポジトリ上にmain.go、Dockerfileを記載します。

```
[main.go]
package main

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

func main() {
	port := os.Getenv("PORT")
	fmt.Printf("Starting server at Port %s", port)
	if port == "" {
		log.Fatal("$PORT must be set")
	}

	http.HandleFunc("/", handler)
	http.ListenAndServe(fmt.Sprintf(":%s", port), nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello worldだよぉお！(´・ω・`)b\n")
}
```

```
[Dockerfile]
FROM golang:latest as builder

ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64
WORKDIR /go/src/server
COPY . .
RUN go build main.go

# runtime image
FROM alpine
COPY --from=builder /go/src/server /app

CMD /app/main
```
localでdockerを起動します。

```
docker build -t app .
docker run -e "PORT=3000" -p 3000:3000 -t app
```
localhost:3000にアクセスして、「Hello worldだよぉお！(´・ω・`)b」が表示されればokです。

## deploy設定
今回はdocker conteinerでupしますので、以下コマンドでstackを変更しておきます。

```
heroku stack:set container -a <appname-stag>
heroku stack:set container -a <appname-prod>
```
heroku.ymlを作成し、build方法を記載します。

```
[heroku.yml]
build:
  docker:
    web: Dockerfile
```

ここまで設定できれば、deploy設定を行ったbranchへデータをpushしてみましょう。

```
git branch staging
git add .
git commit -m "init"
git push origin staging
```

これで自動的にherokuに作成したappにデプロイされればokです。
production環境も同様に、対象ブランチにpushすればデプロイされるはずです。

# おわりに
herokuを触るのは数年ぶりだったのですが、golangのポータブル性も相まってかなり楽に構築できるのではないかという印象を受けました。
本番稼働させるためには、Webサーバを常時稼働させるための$7が最低限必要です。(SSLや独自ドメインの設定も無料枠ではできません。)
しかし、VPSレンタルと変わらない料金にもかかわらず、スケール性がありインフラ考慮も極力行わないで良い環境を手に入れることができるのでかなりリーズナブルな気もしています。(試算結果なので、もっとかかるかもしれませんが。。。)

2018年はAWSのServerless構成、FirebaseのServerless構成と、サーバレスなNoSQLをひたすら考えていたのですが、もう疲れたので2019年は初心に戻って、RDBを軸にいろいろ考えていきたいと思います。
[個人的にこの風潮は今年来るんじゃないかな〜っと思ってます(年末にaws aurora serverlessも来ましたしね！)。Firebaseは人気ですが、NoSQLのみのRDB使わない縛りはあまりにも酷なので、疲れている人も多いハズ！herokuはgithubがprivateリポジトリが無制限無料になったので、低料金ですごく使いやすくなってます！]

今回はdeployまででしたが、また何かあったら記載します。

ぼくからは以上です。

## 参考文献
Goで書いたサーバーをHerokuにDocker Deployする
<https://qiita.com/croquette0212/items/2b85aa2c6b2933244f07>
HerokuでGoアプリケーションを動かしたい
<https://kwmt27.net/2017/03/23/how-to-deploy-go-application-on-heroku/>