Go言語でデータベースを使う処理を書いてHeroku上に公開してみる手順の覚書
はじめに
Go言語でWebアプリを作ってみたいと思い,作ったWebアプリを簡単に公開できる方法について調べていた.まずは無料でできる方法から始めたかったので,そこでHerokuを使ってみることにした.
また,アプリを作る上でデータベースに関わる処理も必要になってくるので,データベースが関わるコードをHerokuで動作させるために必要な設定の仕方についても試してみることにした.
今回試すのは,取りあえずデータベースに適当なテーブルを作成し,そのデータを読み取ってHTMLに表示するだけのGo言語で書いたサーバーサイドプログラムである.Heroku上でデータベース連携の処理を実行するのは,アドオンを追加したり等ローカルで試すのとは勝手が異なるので,少しつまづきそうになった.手順を覚書として書いておく.
次節に手順を書く.
フォルダ構成
[~/Code/Project/proj_y2022/proj0102/jikken3] % tree . . ├── dbdata │ └── setup.sql └── main.go 1 directory, 2 files
Heroku上で実行されるサーバサイドのプログラム
main.go
今回注目するのはhellodb関数であり,これはURLで/db
のパスにアクセスしたときの処理について書いてある.ここで行なっているのは,テーブルから全てのレコードを読み取り,カラム(name)を改行で連結した文字列として出力する.
package main import ( "io" "net/http" "os" "log" "database/sql" _ "github.com/lib/pq" "strings" ) var Db *sql.DB func hello(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Hello World!!") } type member struct { NUM string NAME string } func hellodb(w http.ResponseWriter, r *http.Request) { Db, err := sql.Open("postgres", os.Getenv("DATABASE_URL")) defer Db.Close() if err != nil { log.Fatalf("Error opening database: %q", err) } rows, err := Db.Query("SELECT * FROM members") defer rows.Close() if err != nil { io.WriteString(w, "Errorrr!") return } var out string var names []string for rows.Next() { var e member rows.Scan(&e.NUM, &e.NAME) names = append(names, e.NAME) } out = strings.Join(names, "\n") io.WriteString(w, out) } func main() { port := os.Getenv("PORT") http.HandleFunc("/", hello) http.HandleFunc("/db", hellodb) http.ListenAndServe(":"+port, nil) }
setup.sql
上記のGo言語のプログラム(main.go)からアクセスされることになる,今回のサンプルとしてのテーブルを定義する.テーブル(members)は名前(name)と番号(id)をレコードとして保存する構成であり,2つのカラム(id, name)を持つ.
[~/Code/Project/proj_y2022/proj0102/jikken3] % cat dbdata/setup.sql CREATE TABLE members ( id integer, name varchar(30) ); INSERT INTO members VALUES (1, 'John Smith'); INSERT INTO members VALUES (2, 'Richard Roe'); INSERT INTO members VALUES (3, 'Baby Doe');
Herokuにデプロイするまでの流れ
流れとしては以下である.詳細は次になる.
- (1) リポジトリを作る
- (2) Heroku上にアプリを作成する
- (3) Herou上のアプリにデータベースを追加する
- (4) 作成したコードをHeroku上のリポジトリにpushする
- (5) Heroku上のアプリのデータベースにテーブルを作成する
(1) リポジトリを作る
[~/Code/Project/proj_y2022/proj0102/jikken3] % git init
同じディレクトリ内で以下を実行する.go mod init
で作成されるgo.mod
ファイルはGoモジュールの依存関係を記述したファイルであり,これはHeroku上でのビルドにおいて使用される.
% go mod init github.com/<ユーザ名>/jikken3 % go mod tidy % go mod vendor
(2) Heroku上にアプリを作成する
heroku create
コマンドでアプリの名前を指定できる.(とりあえずjohnapp47
としておく)
[~/Code/Project/proj_y2022/proj0102/jikken3] % heroku create johnapp47
(3) Herou上のアプリにデータベースを追加する
今回のコードはpostgresqlを使うので,以下のようにしてHerokuアプリにアドオンを追加する.
% heroku addons:create heroku-postgresql:hobby-dev --app johnapp47
(4) 作成したコードをHeroku上のリポジトリにpushする
[~/Code/Project/proj_y2022/proj0102/jikken3] % git add -A . % git commit -m "test commit" % git push heroku master
(5) Heroku上のアプリのデータベースにテーブルを作成する
Herokuアプリ(今回はjohnapp47)の上に展開された,Go言語のサーバーサイドプログラムから利用するデータベースに対して,先に挙げたsetup.sql
のSQLを実行し,テーブルを作成する.
まず確認として,ファイル群は先ほどpushしたので,setup.sql
は以下のようにして認識されている.
[~/Code/Project/proj_y2022/proj0102/jikken3] % heroku run bash --app johnapp47 Running bash on ⬢ johnapp47... up, run.8167 (Free) ~ $ ls Procfile bin dbdata go.mod go.sum main.go vendor ~ $ ls dbdata setup.sql ~ $
それでは,テーブルを作成するためにsetup.sql
の中身のSQL文をデータベース上で実行する.
HerokuのPostgresサーバにのコンソールにアクセスするにはheroku pg:psql --app <アプリ名>
と実行すればよい.
[~/Code/Project/proj_y2022/proj0102/jikken3] % heroku pg:psql --app johnapp47 --> Connecting to postgresql-convex-34468 psql (14.1, server 13.5 (Ubuntu 13.5-2.pgdg20.04+1)) SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off) Type "help" for help. johnapp47::DATABASE=>
ファイル(setup.sql)を読み込んで実行するコマンドは\i <ファイル名>
johnapp47::DATABASE=> \i dbdata/setup.sql CREATE TABLE INSERT 0 1 INSERT 0 1 INSERT 0 1 johnapp47::DATABASE=> \dt List of relations Schema | Name | Type | Owner --------+---------+-------+---------------- public | members | table | jutsizbfgorver (1 row)
テーブルが作成されたのをselect文で確認.
johnapp47::DATABASE=> select * from members; id | name ----+------------- 1 | John Smith 2 | Richard Roe 3 | Baby Doe (3 rows) johnapp47::DATABASE=> \q
デプロイされたアプリにアクセスしてみる
https://johnapp47.herokuapp.com/db
にアクセスすると,以下のような表示を確認.
Go言語で書いたサーバプログラムがデータベースからレコードを読み込んでテーブル(members)から読んだ名前の一覧を表示できたことを確認できた.
おわりに
Heroku上でデータベースが連携するコードをデプロイする方法について理解できた.個人的にDockerを学び始めたこともあり,この後にDocker on Herokuなる存在を知ったので次はこっちも試してみようと思う.