Help us understand the problem. What is going on with this article?

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

やりたいこと

普通にイメージを作成するとどうしても大きくなってしまう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で作っていきたい人たちの参考になれば嬉しいです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away