Golang + Mysql + Dockerで環境構築したった
シュタインズゲートを最近初めて見て、ダルのような生き方をしたいと思いました。
前提知識
Golang
言わずと知れたGo言語の別称。Goだと海外では紛らわしいらしい。
Echo
Golang の webフレームワーク。簡単にルーティングなどができる。
Gorm
Go 版の Active Record。 Go のOR マッパー。
GOPATH
Go で開発をするにあたり必須の環境変数。必要なライブラリはGOPATHに全てインストールされる。
vi .bash_profile export GOPATH=/Users/sipporyusyon/Desktop/workspace/go
Docker
コンテナ型の仮想化ツール。OS までは仮想化しないので、Virtual Box とかより軽い。ちなみに Golang で書かれている。
ファイル構成
カレントディレクトリを /Users/sipporyusyon/Desktop/workspace/go とする。.
├── Dockerfile
├── docker-compose.yml
├── main.go
└── handler── create.go
各ファイル
docker-compose.yml
version: '3' services: app: build: . # docker-compose.yml はgo/ 直下に置いてるので . ディレクトリでビルドする container_name: go_app # 自由に決められる volumes: - ./:/go # dockerコンテナ上の変更をローカルのmacに保存 ports: - 1323:1323 # 開放するポート depends_on: # dbコンテナに接続する ビルドするのもdbコンテナが立ち上がってからになる - db db: image: mysql:latest # mysql のdockerイメージを取ってくる container_name: go_db # 自由に決められる volumes: - ./mysql_data:/var/lib/mysql # データ永続化のためのボリューム - ./sqls/init:/docker-entrypoint-initdb.d ports: - 3306:3306 # 開放するポート environment: MYSQL_ROOT_PASSWORD: docker_pwd # sqlのrootユーザーでログインする時のパスワード MYSQL_DATABASE: docker_db # sqlで初回起動時に作成されるデータベース名 MYSQL_USER: docker_user # sqlで初回起動時に作成されるユーザー名 MYSQL_PASSWORD: docker_user_pwd # sqlで初回起動時に作成されるユーザーのパスワード volumes: mysql_data: # ローカルのディレクトリにデータを保存
細かいことはこの記事を見てください。(別タブ開きます)
Dockerfile
FROM golang:1.11.2-alpine3.8 AS build # GolangのDockerイメージ取ってくる WORKDIR /go # Docker上の作業ディレクトリ設定 ADD . /go # ローカルのファイルをdocker にコピー RUN apk update && \ apk add --no-cache git && \ go get github.com/go-sql-driver/mysql && \ # go で sql 使うのに必要なライブラリ go get github.com/labstack/echo/middleware && \ # echo インストール go get github.com/jinzhu/gorm # gorm インストール CMD ["go", "run", "main.go"] # main.go ファイル実行 後述するがmain.goでサーバーを立てる
特に話すことはないですね。docker-compose.yml よりも先に Dockerfile の方が先に実行されるのは、考えれば当たり前ですが、最近知りました。
main.go
package main import ( "github.com/labstack/echo" "github.com/labstack/echo/middleware" "./handler" ) func main() { e := echo.New() // Middleware e.Use(middleware.Logger()) e.Use(middleware.Recover()) // Routes e.GET("/users", handler.ListUser) e.GET("/users/:id", handler.GetUser) e.POST("/users", handler.CreateUser) e.PUT("/users/:id", handler.UpdateUser) e.DELETE("/users/:id", handler.DeleteUser) // Start server e.Logger.Fatal(e.Start(":1323")) }
echo では echo インスタンスを作った後 e.start でサーバーを建てることができます。
ルーティングの中で handler パッケージの ListUser メソッドや CreateUser メソッドなど呼び出していますが、今回では CreateUser メソッドだけ触れます。
なお、echo 関連は基本この記事でコピペ勉強させていただきました。(別タブ開きます)
handler/create.go
package handler import ( "net/http" "github.com/labstack/echo" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" ) type User struct( Id int `gorm:"AUTO_INCREMENT"` Name string `gorm:"type:varchar(50);"` ) func gormConnect() *gorm.DB { db,err := gorm.Open("mysql", "docker_user:docker_user_pwd@tcp(docker.for.mac.localhost:3306)/docker_db") if err != nil { panic(err.Error()) } return db } func CreateUser(c echo.Context) (err error) { db := gormConnect() defer db.Close() u := &User{} if err := c.Bind(u); err != nil { return err } u.Name = "test" db.Table("User").Create(&u) return c.JSON(http.StatusCreated, u) }
まず、import 内で gorm, echo のライブラリを呼ぶ。今回 mysql に接続できればいいので, User の構造体は簡易なものにした。
gormConnect 関数内で mysql コンテナに接続。gormのOpen関数を使うことで接続する。docker から繋ぐのでは ホストの名前が localhost ではまずいらしく、一番ハマった。正しくは docker.for.mac.localhost。ポートは mysql コンテナのポート。
docker_user, docker_user_pwd, docker_db はdocker-compose.yml で定義した環境変数の値でおけ。
CreateUser 関数内で db インスタンスを受け取る。echo.Contect は echo でレスポンス返す時に使う変数...くらいにしか理解がありません。
u に User 型の変数を定義し、u.Name に値を代入。db.Table("User").Create(&u) で User テーブルがあれば、POSTリクエストがあった時、Userテーブル内に id が1、nameがtest のユーザーが作られるはずです。
確認
[sipporyusyon@MBP go] docker-compose up
コンテナを起動させる。
[sipporyusyon@MBP go] docker exec -it go_db bash
mysql コンテナ内に入る。
root@be9383fe56c8:/# mysql -u docker_user -h localhost -D docker_db -p # パスワードを聞かれるので入力(docker-compose.ymlで指定したdocker_user_pwd)
使用するユーザー名とデータベース名を指定して、mysql に接続。
mysql> CREATE TABLE User (Id int auto_increment, Name varchar(50));
Id と Name をカラムに持つ User テーブル作成。
コンテナを一度出て,
[sipporyusyon@MBP go] curl -v POST -H "Content-Type: application/json" "http://localhost:1323/users"
curl で CreateUser のある url へ POST リクエストを送る。
無事Userテーブルに testユーザーが作られたら成功。
あとがき
ここまで書くのに2時間かかって、現在夜の3時...何がやばいって平日の木曜なのがやばいですね。