- 投稿日:2020-10-06T21:12:03+09:00
【Go + Gin】Docker環境を構築してみた
はじめに
GoとGinを使用する際のDokcerを用いた開発環境を構築しました。docker-composeを使用しています。
使用するDBはmysqlで、ORマッパーはGormの使用を想定しています。TL;DR
下記のディレクトリ構成にしています。
Dockerfile、docker-compose.ymlにしています。ディレクトリ構成
├── docker │ ├── docker.mysql.env │ └── go │ └── Dockerfile ├── docker-compose.yml └── src └── appdocker/go/Dockerfile
FROM golang:1.10.3-alpine3.8 COPY src/app /go/src/app/ WORKDIR /go/src/app/ RUN apk update \ && apk add --no-cache git \ && go get github.com/gin-gonic/gin \ && go get github.com/jinzhu/gorm \ && go get github.com/go-sql-driver/mysql EXPOSE 8080docker/docker.mysql.env
MYSQL_ROOT_PASSWORD=root MYSQL_DATABASE=go-gin-app MYSQL_USER=root MYSQL_PASSWORD=passworddocker-compose.yml
services: app: container_name: app build: context: . dockerfile: ./docker/go/Dockerfile ports: - 3000:3000 links: - database tty: true volumes: - ./src/app:/go/src/app database: restart: always image: mysql:5.7 ports: - 3308:3306 volumes: - mysql-datavolume:/var/lib/mysql env_file: - docker/docker.mysql.env volumes: mysql-datavolume: driver: local解説
Dockerfile
今回はGoのDockerfileのみを作成し、mysqlはベースイメージを使用するようにdocker-compose.ymlで指定します。
FROM golang:1.10.3-alpine3.8 COPY src/app /go/src/app/ WORKDIR /go/src/app/ RUN apk update \ && apk add --no-cache git \ && go get github.com/gin-gonic/gin \ && go get github.com/jinzhu/gorm \ && go get github.com/go-sql-driver/mysql EXPOSE 8080
src/app直下のファイルをボリュームに指定しています。また、aliphineのベースイメージを指定しているので、apkでGin、Gorm関連のパッケージをインストールしています。
docker-compose.yml
services: app: container_name: app build: context: . dockerfile: ./docker/go/Dockerfile ports: - 3000:3000 links: - database tty: true volumes: - ./src/app:/go/src/app database: restart: always image: mysql:5.7 ports: - 3307:3306 volumes: - mysql-datavolume:/var/lib/mysql env_file: - docker/docker.mysql.env volumes: mysql-datavolume: driver: localmysqlのenvファイルを別で作成したので、
env_fileで指定します。
ポート 3306はローカルのmysqlでよく使用するので、3307を指定しています。動作確認
src/app直下にmain.goを作成し、おなじみのhello worldを出力するようにコードを記述します。package main import "fmt" func main() { fmt.Println("Hello, world") }そして、下記コマンドでhello worldを出力させます。
docker-compose exec app go run main.gohello worldが出力されたでしょうか。
終わりに
意外と簡単にGo+Ginの環境構築を行うことができました。
やはりDockerを使用すると環境構築が楽になりますね、!
- 投稿日:2020-10-06T09:44:19+09:00
【Go】DBへのRead/Writeでエンドポイントを分けたい
はじめに
レプリケーションに対応するため、DBのエンドポイントをRead/Writeで分けることにしました。
Go/Gorm2でどのように対応するか検討しました。利用環境
- Go: 1.15.2
- Gorm2: v1.20.1
- Echo: v4.1.17
結論から
Endpoint別に複数のConnectionを持ったTypeに、Gormの各Methodをラップした。
こうすることで、connectionを利用する側はendpointを意識せずにDBへの操作を可能にしています。db/connect.gopackage db import ( "os" "gorm.io/driver/mysql" "gorm.io/gorm" ) type SqlHandler struct { ReadConn *gorm.DB WriteConn *gorm.DB } func Connect() *SqlHandler { readConn, err := gorm.Open(GetDBConfig("read")) if err != nil { panic(err.Error()) } writeConn, err := gorm.Open(GetDBConfig("write")) if err != nil { panic(err.Error()) } sqlHandler := SqlHandler{ ReadConn: readConn, WriteConn: writeConn, } return &sqlHandler } func GetDBConfig(endpoint string) (gorm.Dialector, *gorm.Config) { USER := "myUser" PASS := "hoge1234" PROTOCOL := "tcp(" + endpoint + ":5050)" DBNAME := "myDB" OPTION := "charset=utf8&parseTime=True&loc=Local" mysqlConfig := mysql.Config{ DSN: USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?" + OPTION, } config := &gorm.Config{} return mysql.New(mysqlConfig), config } func (handler *SqlHandler) Find(out interface{}, where ...interface{}) *gorm.DB { return handler.ReadConn.Find(out, where...) } func (handler *SqlHandler) Exec(sql string, values ...interface{}) *gorm.DB { return handler.WriteConn.Exec(sql, values...) } func (handler *SqlHandler) First(out interface{}, where ...interface{}) *gorm.DB { return handler.ReadConn.Find(out, where...) } func (handler *SqlHandler) Raw(sql string, values ...interface{}) *gorm.DB { return handler.WriteConn.Raw(sql, values...) } func (handler *SqlHandler) Create(value interface{}) *gorm.DB { return handler.WriteConn.Create(value) } func (handler *SqlHandler) Save(value interface{}) *gorm.DB { return handler.WriteConn.Save(value) } func (handler *SqlHandler) Delete(value interface{}) *gorm.DB { return handler.WriteConn.Delete(value) } func (handler *SqlHandler) Where(query interface{}, args ...interface{}) *gorm.DB { return handler.WriteConn.Where(query, args...) }レプリケーション
is 何
気になる所
func Execやfunc Rawなど、queryそのものが発行できる部分については、read/write双方の可能性があり、どちらに振り分けるか悩むところです。
今回はwriteに振り分けました。なるべく利用者はendpointを意識せずに使えるようにしたい...おわりに
CQRSを利用することを決めており、そもそもSQLベタ書きが増えそうな気がしています。
Gormを使う意味が少し薄れますが、やはりORMとしてのTypeへのマッピングを考えると欲しいところ。
マッピング部分だけ自作したりすると良いのかなと思います!!参考