go・gin・gormとdockerで作ったAPIをHerokuで動かす

f:id:utr066:20190614163626p:plain

個人的にAPIを作ったけど、やっぱり作ったらどこかにデプロイしたい。

当初は、 GKE + CloudSQLの構成でやろうと思ったけど、結構料金かかるみたいだから断念。Kubernetes試してみたかったんだけどな。そもそも、CloudSQLが割と料金かかる。

RDBは無料で使えるようなものはほとんどないっぽい・・悲しい・・・

ということで、APIはHerokuに置いてしまうことにした。開発環境はDockerで作ったから、HerokuでもDocker運用する。

herokuでもdocker使える

どうせならDockerで本番環境もやりたくて、調べたらHerokuでもDocker使えるらしい。

Deploying with Docker | Heroku Dev Center

そして、Goにも対応しているということだからこれでいける。コマンド的には以下の2つでデプロイできるらしい。

$ heroku container:push web
// Dockerfileをbuildしてコンテナにプッシュする。
$ heroku container:release web
// プッシュされたimageをリリースする。

これでherokuでもDockerfileを元に作られたimageを使うことができる。

herokuリポジトリをgitに登録

まずは、herokuのリポジトリをgitで登録する。これやんないと、herokuにpushするときにエラー起きる。

$ heroku git:remote -a go-portfolio-api -r heroku
$ git remote -v

remoteにherokuのリポジトリが登録されていればok。

APIをherokuに対応させる

まあコマンド打ってherokuにデプロイすれば、割と簡単に使えるのかなー・・・とか思っていたけど甘かった。herokuとはいえ、やっぱり環境構築はしんどい。

DBをpostgreSQLにする

開発はMysqlでやっていた(CloudSQL使う想定だった・・・)んだけど、Postgresに変更した。HerokuでもAddonを追加すれば、Mysql使えるんだけど、何してもバージョンが5.5.62から上がらないという・・・これだと開発で使っていたSQL対応できないじゃん・・せめて・5.7まで対応しておくれ・・・

開発環境のMysqlを5.5.62まで下げるという手段もあったけど、普通に嫌だしPostgreSQL使うことにした。それに伴ってgooseで作ったSQLも変更した(MysqlとPostgresだと型が違ったりするからね・・トリガーなんかも追加したよ・・・)

postgres用のアドオンを入れる

heroku側ではpostgres用のアドオンを入れる。

$ heroku addons:create heroku-postgresql:hobby-dev

追加したらそのDB情報を見ることができるはず。

$ heroku config 

ちょっとわかりにくいけど、ここで表示されるDATABASE_URLの構成はこんな感じ⬇️ postgres://ユーザー名:パスワード@ホスト名:ポート/データベース名

この情報を使えば、heroku上のDB(postgreSQL)に接続できるはず。

GoのコードをPostgresに対応する

mysql用のものをimportして使っていたけど、postgresのものをimportして使うようにした。

_ "github.com/jinzhu/gorm/dialects/postgres"

構造体ちょっと変えたり、あとgorm使っていたんだけど、Openの引数も変えたわ。

connection := host=db port=5432 user=aaaaa password=aaaaa dbname=aaaaa sslmode=disable
db, err := gorm.Open("postgres", connection)

mysqlの時とはちょっと書き方が違うから、herokuで使うDB情報を元に書き換える。 Connecting to database | GORM - The fantastic ORM library for Golang, aims to be developer friendly.

herokuのDBに対応する

上で書いた情報使えば、ローカルからherokuのDBを見に行くのはできるんだけど、herokuにあげたアプリケーションからherokuのDBを見にいこうとするとエラーになる。これ普通に詰まって結構調べたわ・・・

で、ちょっと変えたのがgorm.Openの部分。

url := os.Getenv("DATABASE_URL")
connection, err := pq.ParseURL(url)
if err != nil {
    panic(err.Error())
}
connection += " sslmode=require"

db, err := gorm.Open("postgres", connection)

herokuから動かす場合にはこれで対応できた。os.Getenv("DATABASE_URL")heroku configで出てくるDATABASE_URL

Dockerfile改造する

gin使ってdockerfileにこんな風に書いていたんだけど、このポート番号指定はherokuではダメらしい。

CMD dep ensure -vendor-only && gin -p 9800

herokuでは、勝手にポート番号が割り当てられるようで、それを適用するためには以下のようにする必要がある。

CMD dep ensure -vendor-only && gin -p $PORT

$PORTでherokuで割り当てられるポート番号を指定できるらしいね。

デプロイする

デプロイはこれ。

$ heroku container:push web
// Dockerfileをbuildしてコンテナにプッシュする。
$ heroku container:release web
// プッシュされたimageをリリースする。

heroku container:push webでDockerfileをbuildして、pushしてくれる。で、それをリリースするにはheroku container:release web。これでheroku openすれば、herokuでアプリケーションの確認ができるはず。

heroku.yml記述する

なんかheroku.ymlないとファイルないから作れって言われるね。だからbuildするためのheroku.ymlを書いてPush。

build:
  docker:
    web: Dockerfile

まあ、これでいった。