🐋
【Go, Docker】docker composeでGoとMySQLをLocalで動かす
はじめに
- DockerfileでGoのimageを作成し、そのDockerfileと、MySQLのimageを使い、GoのコードでDBを使ってみます。
- ORMはXormを使います。
環境
- go 1.17
- macOS 12.0.1
- M1チップ
- github.com/go-sql-driver/mysql v1.6.0
- xorm.io/xorm v1.2.5
ゴール
-
docker-compose up -d
で起動 -
docker-compose exec app go run main.go
でmain.goを呼ぶ。 - Xormにデータが追加され、取得出来たものが取得されたら成功です。
ソースコード
Dockerfile
FROM golang:1.17.0-alpine3.14
ENV ROOT=/go/src/app
WORKDIR ${ROOT}
RUN apk update && apk add git
COPY ./main.go ${ROOT}
COPY go.mod ${ROOT}
RUN go mod tidy
docker-compose.yml
version: "3"
services:
app:
build: .
depends_on:
- db
volumes:
- ./:/go/src/app
tty: true
db:
image: mysql:5.7
environment:
- MYSQL_DATABASE=test_db
- MYSQL_ROOT_PASSWORD=password
command: >
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--innodb_file_per_table
--innodb_file_format=BARRACUDA
--innodb_large_prefix=1
ports:
- 3306:3306
main.go
package main
import (
"fmt"
"log"
_ "github.com/go-sql-driver/mysql"
"xorm.io/xorm"
)
type User struct {
ID int64 `xorm:"id pk autoincr"`
Name string `xorm:"name"`
Age int `xorm:"age"`
}
// createTable テーブルを作成する
func createTable(engine xorm.Engine) {
err := engine.CreateTables(User{})
if err != nil {
log.Fatalf("テーブルの生成に失敗しました。: %v", err)
}
fmt.Println("テーブル作成が成功しました。")
}
// insert テーブルにレコードを追加する
func insert(engine xorm.Engine) {
user := User{
Name: "tanaka",
Age: 20,
}
_, err := engine.Table("user").Insert(user)
if err != nil {
log.Fatal(err)
}
fmt.Println("レコードの追加が完了しました。")
}
// get 単体取得(1レコードを取得)
func get(engine xorm.Engine) {
user := User{}
// idフィールドは Autoincrement なので Insert済みなのであれば id = 1 のユーザが取得できるはず
result, err := engine.ID(1).Get(&user)
if err != nil {
log.Fatal(err)
}
if !result {
log.Fatal("ユーザーが見つかりませんでした。")
}
fmt.Printf("取得したレコード :%+v\n", user)
}
func main() {
//engineを作成します。
engine, err := xorm.NewEngine("mysql", "root:password@tcp(db:3306)/test_db?charset=utf8mb4&parseTime=true")
if err != nil {
log.Fatal(err)
}
//テーブルを作成する
createTable(*engine)
//テーブルに追加する
insert(*engine)
//テーブルから取得する
get(*engine)
fmt.Println("うまく動きました。")
}
解説
Dockerfile
下記にコメントで書いた通りです。
go mod install
ではなく、go mod tidy
を使ってます。
go mod tidy
使うと必要なものはinstallしてくれて、要らないものは削除してくれます。
ENVは使わなくても良いんですが、何回もPATH指定するの面倒くさいので、環境変数にしました。
//goのベースイメージで1.17を使います。
FROM golang:1.17.0-alpine3.14
// ROOTという名前で、`/go/src/app`を定義します。
ENV ROOT=/go/src/app
// WORKDIRを/go/src/appにします。
WORKDIR ${ROOT}
// gitをインストールします。
RUN apk update && apk add git
// main.goを/go/src/appにコピーします。
COPY ./main.go ${ROOT}
// go.modを/go/src/appにコピーします。
COPY go.mod ${ROOT}
//go mod tidyを実行します。
RUN go mod tidy
docker-compose.yml
- version
- docker-composeのversionです。
- services
- docker-compose.ymlで扱うコンテナです。
- 今回は
app
とdb
という名前のコンテナを使います。 -
app
とdb
という名前は適当です。
- app
- build: .
- カレントディレクトリのDockerfileをビルドします。
- 上で作成した、Goのイメージを使っているDockerfileがビルドされます。
- depends_on:
- これは
○○
の後で実行するというものです。 - 今回は
db
のコンテナの実行後にapp
のコンテナを起動させます。
- これは
- volumes:
- データを永続化する場所を指定します。
- 今回は
/go/src/app
を指定します。
- tty: true
- trueにしておく事でコンテナを継続させる事ができます。
- build: .
- db
- image: mysql:5.7
- これはMySQLオフィシャルのDockerイメージです。
- このようにDockerfileに書かなくても、docker-composeにこのように書くだけでオフィシャルのMySQL使えます。
- 今回はMySQL5.7を使用します。
- environment:
- 環境変数です。
- MYSQL_DATABASE=test_db
- データベース名です。
test_db
という名前にしてます。
- データベース名です。
- MYSQL_ROOT_PASSWORD=password
- ROOTパスワードです。
password
というパスワードにしてます。
- ROOTパスワードです。
- command: >
- オプションです。
- 下記2つは正直よく分かってませんが、文字キャラクターをutf8mb4にする為のものです。
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
- ports:
- ポートを指定します。
- MySQLなので3306を利用します。
- image: mysql:5.7
version: "3"
services:
app:
build: .
depends_on:
- db
volumes:
- ./:/go/src/app
tty: true
db:
image: mysql:5.7
environment:
- MYSQL_DATABASE=test_db
- MYSQL_ROOT_PASSWORD=password
command: >
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
ports:
- 3306:3306
main.go
//engineを作成します。
engine, err := xorm.NewEngine("mysql", "root:password@tcp(db:3306)/test_db?charset=utf8mb4&parseTime=true")
if err != nil {
log.Fatal(err)
}
ここでengineの作成をしてます。
db:3306
のdb
の部分はコンテナの名前です。
/test_db?
のtest_db
はデータベースの名前です。
さいごに
上記のコードで、コマンドを実行すれば動くはずです。
これであなたも、DockerでGoとMySQLが使えるハズ!!
Discussion