Go + gorm + gin と mysqlと言うありきたりな組み合わせでDockerの環境作りましたー!
今更ですがDocker触り始めて軽さに感動😭
環境もがっつり作ったのは初めてかも。。
以下の記事参考させていただきました!
Dockerで立てたmysqlにgolangから接続する方法
[golang]gormを使ってローカル環境のMySQLとCRUD操作
他のDockerコンテナからコンテナ内のMySQLに接続する
ディレクトリ構成
こんな感じ
/
├ docker-compose
├ .dockerignore
├ docker/
│ └ api/
│   └ Dockerfile
│ └ db/
│   └ Dockerfile
│   └ conf.d
│     └ mysql.conf 
├ src
   └ api/
      └ main.go
      └ start_app.sh
Dockerfile
docker/api/Dockerfile
どこでも見るような感じになってますが CMD が結構ネックです!
FROM golang:latest
COPY src/api /go/src/api  ← GOROOTが/goになるので
WORKDIR /go/src/api/
RUN go get -u github.com/gin-gonic/gin \  ← gormとginとドライバー
  && go get github.com/jinzhu/gorm \
  && go get github.com/go-sql-driver/mysql
  && apt-get install -y mariadb-client
CMD ["sh", "./start_app.sh"]  ←ハマった。。
docker/db/Dockerfile
こちらもそこまで特筆することはありません!
FROM mysql:5.7
RUN touch /var/log/mysql/mysqld.log ← ログファイル作っときましょう
docker-compose
上で作った2つのコンテナを取り扱う為にdocker-composeを使います。
version: '3'
services:
  api:
    links:
      - mysql ← サービス名(下のmysql)は好きな物で大丈夫です。
    build: ← buildの中にこの2つ書くと一番上のディレクトリから色々弄れる感覚です。
      context: . 
      dockerfile: ./docker/api/Dockerfile
    ports:
      - "8080:8080"
    volumes:
      - ./src/api:/go/src/api
  mysql:
    build: ./docker/db
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_USER: root
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: sample
    hostname: mysql
    ports: 
      - "3306:3306"
    volumes:
      - ./docker/db/conf.d:/etc/mysql/conf.d
      - ./log/mysql:/var/log/mysql
conf.d/mysql.conf
これはmysqlの設定ファイルなんで参考までに!
(丸パクリさせてもらいましたw)
[mysqld]
character-set-server=utf8mb4       # mysqlサーバー側が使用する文字コード
explicit-defaults-for-timestamp=1   # テーブルにTimeStamp型のカラムをもつ場合、推奨
general-log=1                   # 実行したクエリの全ての履歴が記録される(defaultではOFFになっているらしい)
general-log-file=/var/log/mysql/mysqld.log # ログの出力先
[client]
default-character-set=utf8mb4               # mysqlのクライアント側が使用する文字コード
src/start_app.sh
ここすごいハマりました。。
結論から言うとmysqlサーバーが立ち上がる前にapiサーバーが立ち上がってしまうので立ち上がりを待つようにしています。(確実にもっと良い書き方あります。。)
# !/bin/bash
# MySQLサーバーが起動するまで待機する
until mysqladmin ping -h mysql -P 3306 --silent; do
  echo 'waiting for mysqld to be connectable...'
  sleep 2
done
echo "app is starting...!"
exec go run main.go
src/main.go
gormとginを使うとこまでなので多くは書いてません!
なんで他のパッケージに公開してるかは突っ込まないでくださいw
package main
import (
	"github.com/gin-gonic/gin"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)
func main() {
	DBMigrate(DBConnect())
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "成功",
		})
	})
	r.Run(":8080")
}
type User struct {
	gorm.Model
	NickName string `json:"nickName"`
}
func DBMigrate(db *gorm.DB) *gorm.DB {
	db.AutoMigrate(&User{})
	return db
}
func DBConnect() *gorm.DB {
	DBMS := "mysql"
	USER := "root"
	PASS := "password"
	PROTOCOL := "tcp(mysql:3306)"  ← ここのmysqlはサービス名です
	DBNAME := "sample"
	CONNECT := USER + ":" + PASS + "@" + PROTOCOL + "/" + DBNAME + "?parseTime=true"
	db, err := gorm.Open(DBMS, CONNECT)
	if err != nil {
		panic(err.Error())
	}
	return db
}
起動
docker-compose build
docker-compose up
起動が確認できたら
curl http://localhost:8080/ping
で成功が返ってこれば問題ないです!
docker-compose up -d
を使っても良いんですけどどこかミスってて落ちてるの気づけないので最初はupで行きましょう!
終わり
mysqlサーバーとAPIサーバーの立ち上がりの順番でめちゃハマりました。。。