🦐
herokuにechoサーバデプロイを試した
概要
DB操作するGoによるサーバをなる早で作成したかったため、
herokuでechoサーバ(golang)をデプロイしてみた
herokuについて
アプリケーションのデプロイ、実行、管理を簡単に行えるPaaS。
従来の無料プランは2022年11月に終了
エコプラン($5/月)から利用可能
DBもherokuで作成出来るため、postgresをherokuで作成する
(最低金額~$0.007/hour, max $5/month
)
herokuを選んだ理由
その他無料でやるとするとlambda+APIGatewayが思いつくが、herokuがこういったPaaSでは有名なので、リソースもすぐ消すため、herokuにした
コード作成
go init api-post
ディレクトリ構成例
internal/
domain/
post.go
handler/
post_handler.go
infra/
db.go
router/
router.go
.env
docker-compose.yml
Dockerfile
go.mod
go.sum
heroku.yml
main.go
主要な記述のみ抜き出して載せる
main.go
herokuは環境変数PORTでPORT番号を指定するため、解放portは環境変数PORTを参照する。
package main
import (
"api-post/internal/router"
"database/sql"
"fmt"
"log"
"os"
_ "github.com/lib/pq"
)
func main() {
db, err := initializeDB()
if err != nil {
log.Fatal("Failed to initialize:", err)
}
defer db.Close()
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
e := router.NewEchoRouter(db)
log.Printf("Server starting on port: %s", port)
e.Logger.Fatal(e.Start(":" + port))
}
func initializeDB() (*sql.DB, error) {
dsn := os.Getenv("DATABASE_URL")
if dsn == "" {
dsn = fmt.Sprintf(
"postgres://%s:%s@%s:%s/%s?sslmode=require",
os.Getenv("DB_USER"),
os.Getenv("DB_PASSWORD"),
os.Getenv("DB_HOST"),
os.Getenv("DB_PORT"),
os.Getenv("DB_NAME"),
)
}
db, err := sql.Open("postgres", dsn)
if err != nil {
return nil, fmt.Errorf("failed to connect to database: %w", err)
}
if err := db.Ping(); err != nil {
return nil, fmt.Errorf("failed to ping database: %w", err)
}
return db, nil
}
heroku.yml
web: go run main.go
だと動かなかったため、以下のように記述した。
build:
docker:
web: Dockerfile
run:
web: /main
Dockerfile
FROM golang:1.22.2-alpine3.19 as builder
RUN apk update \
&& apk add --no-cache git curl
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod tidy
COPY . .
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-w -s" -o /main ./cmd/server
FROM alpine:3.12
COPY /main .
EXPOSE 8080
ENTRYPOINT ["/main web"]
.env
例(ローカル、heroku以外のDBに接続する時用)
PORT=8080
DB_HOST=xxxx
DB_USER=xxxx
DB_PORT=xxxx
DB_NAME=xxxx
DB_PASSWORD=xxxx
DB_SSLMODE=require
herokuでdeploy
#herokuをインストール(mac)
brew install heroku/brew/heroku
#herokuにログインする
heroku login
#プロジェクト作成, push
heroku create api-post
heroku git:remote -a api-post
git push heroku main
# データベース追加
heroku addons:create heroku-postgresql:essential-0
heroku pg:psql postgresql-[database-name] < init.sql
# 環境変数の設定
heroku config:set PORT=80
## herokuのdb以外に接続する場合
heroku config:set DB_USER=xxxx
heroku config:set DB_PASSWORD=xxxx
heroku config:set DB_HOST=xxxx
heroku config:set DB_PORT=xxxx
heroku config:set DB_NAME=xxxx
heroku config:set DB_SSLMODE=require
# ログの確認
heroku logs --tail
URLにアクセス->ルーティングの通りに値が返却される
はまったポイント
-
heroku.ymlのentrypointに
go run main.go
が使えない- 以下のようなエラーになった
2024-12-24T06:00:12.843863+00:00 app[web.1]: /bin/bash: line 1: go: command not found
- 結果Dockerfileでbuildするやり方に変更した
-
DBが繋がらない(heroku起因でない)
- 最初SupabaseのDBと繋げようとした際に、Direct connectionに向き先を向けていた。IPv6しか追加設定を入れない限り対応していないため、Session poolerに変更したら、接続出来るようになった
データの削除
#アプリ名確認
heroku apps
#アプリ削除
heroku apps:destroy --app <アプリ名> --confirm <アプリ名>
Discussion