57
31

More than 5 years have passed since last update.

Go + docker で Mysqlを使う(multi-stage builds & docker-composeで)

Last updated at Posted at 2018-12-09

やりたいこと

普通にイメージを作成するとどうしても大きくなってしまうGoイメージですが、multi-stage buildsにすると
格段にサイズが小さくすることができます。
今回はdocker(docker-compose)で環境を準備し Go から MySQL にアクセスする方法について書いていきます。

基本的に、以前自分が勉強でtodolist用のAPIを作成するために作成したリポジトリからの出典になります。
https://github.com/t0w4/toDoListBackend

Dockerfile

FROM golang:1.11.2-alpine3.8 AS build

WORKDIR /
COPY . /go/src/github.com/t0w4/toDoListBackend
RUN apk update \
  && apk add --no-cache git \
  && go get github.com/go-sql-driver/mysql \
  && go get github.com/google/uuid \
  && go get github.com/gorilla/mux
RUN cd /go/src/github.com/t0w4/toDoListBackend && go build -o bin/todolist main.go

FROM alpine:3.8
COPY --from=build /go/src/github.com/t0w4/toDoListBackend/bin/todolist /usr/local/bin/
CMD ["todolist"]

goのdockerの公式サイトも見ましょう。
docker上では$GOPATHが /go になることも注意しましょう。

docker-compose.yml

version: '3'
services:
  db:
    image: mysql:5.7
    volumes:
      - mysql_data:/var/lib/mysql
      - ./sqls/init:/docker-entrypoint-initdb.d
    ports:
      - "3306:3306"
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: gerhuhaer
      MYSQL_DATABASE: todoList
      MYSQL_USER: t0w4
      MYSQL_PASSWORD: faweufhli

  todolist:
    build: .
    depends_on:
      - db
    ports:
      - "8080:8080"
    environment:
      MYSQL_DB_HOST: db
      MYSQL_DB: todoList
      MYSQL_PORT: 3306
      MYSQL_USER: t0w4
      MYSQL_PASSWORD: faweufhli
    restart: always

volumes:
  mysql_data:

注意!!!!!!!
今回特に外部公開もしていないのに勉強用だからいいですが、外部から見えるような場所でID, パスワードをほいほい公開しないようにしましょう。
各環境変数の要不要、意味については公式を読みましょう。下手解説より100倍いいです。

/docker-entrypoint-initdb.d にsqlを配置すると初期起動時に実行してくれるますので、DBやテーブルの作成、初期データの投入などの用途で使えます。
また永続化のためMySQLのデータはローカルにマウントさせています。

GoでのMySQLへのアクセス

GoでMySQLを扱う部分についてはRevelでGORMを使ったMySQL Associationの実装が参考になったので
そちらを見てください。。。。だと不親切なので、以下に自分がORMを使わないで書いた実装があるんで載せます。

package db

import (
    "database/sql"
    "fmt"
    "os"
    "strings"

    _ "github.com/go-sql-driver/mysql"
)

func Init() (*sql.DB, error) {
    connectionString := getConnectionString()
    db, err := sql.Open("mysql", connectionString)
    if err != nil {
        return nil, err
    }
    return db, nil
}

func getParamString(param string, defaultValue string) string {
    env := os.Getenv(param)
    if env != "" {
        return env
    }
    return defaultValue
}

func getConnectionString() string {
    host := getParamString("MYSQL_DB_HOST", "localhost")
    port := getParamString("MYSQL_PORT", "3306")
    user := getParamString("MYSQL_USER", "root")
    pass := getParamString("MYSQL_PASSWORD", "")
    dbname := getParamString("MYSQL_DB", "todoList")
    protocol := getParamString("MYSQL_PROTOCOL", "tcp")
    dbargs := getParamString("MYSQL_DBARGS", " ")

    if strings.Trim(dbargs, " ") != "" {
        dbargs = "?" + dbargs
    } else {
        dbargs = ""
    }
    return fmt.Sprintf("%s:%s@%s([%s]:%s)/%s%s",
        user, pass, protocol, host, port, dbname, dbargs)
}

差分は、initの部分と、参考記事が設定ファイルから取得していたところを環境変数から取得するようにしたところくらいです。
自分が開発していた時は、このgetConnectionStringが返すMySQLの接続情報がわからず時間を食ってしまいました。。。

終わりに

記事としてはとても短いので「えっ!これだけ?」と思われるかもしれないですが、意外と上記の内容がまとまった記事というのが見つからなかったので、今後Goをdockerで作っていきたい人たちの参考になれば嬉しいです。

57
31
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
57
31