Docker で始める golang 入門

Docker で始める golang 入門

Docker 環境

動作確認済のバージョン:

  • Version 2.0.0.0-mac81 (29211)

こちら http://studio-andy.hatenablog.com/entry/go-todo-crud がすごいわかりやすくて良いので、これに沿うような Docker 環境を整えてみる。

まずは何はともあれDockerfile

FROM golang:1.10.2

WORKDIR /go/src/go-todo/

RUN go get -u github.com/golang/dep/cmd/dep \
              bitbucket.org/liamstask/goose/cmd/goose

depはパッケージマネージャで、gooseマイグレーションツール。

WORKDIR/go/src以下でないとパスが通らなくなる。

次にdocker-compose.ymlを下記の内容で作成:

version: "3"
services:
    db:
        image: mysql:8
        volumes:
            - ./docker-runtime/mysql:/var/lib/mysql
        environment:
            MYSQL_ROOT_PASSWORD: password
            MYSQL_DATABASE: sampledb
            MYSQL_USER: sampleuser
            MYSQL_PASSWORD: password

    app:
        build: .
        volumes:
            - .:/go/src/go-todo/
        ports:
            - "8080:8080"
        tty: true
        stdin_open: true
        links:
            - db

ビルドしてバックグラウンド実行し、初期ロックファイルGopkg.lockを作成する:

$ docker-compose up -d --build
$ docker-compose exec app dep init

volumesしてあるので、ファイルがホストとも共有される。

Hello World

基本となるコントローラーファイルsrc/controller/index.goを作成:

package controller

import (
    "net/http"

    "github.com/gin-gonic/gin"
)

func IndexGET(c *gin.Context) {
    c.String(http.StatusOK, "Hello World")
}

上記のコントローラーをルートに割り振る。

main.go:

package main

import (
    "go-todo/src/controller"

    "github.com/gin-gonic/gin"
)

func main() {
    router := gin.Default()

    router.GET("/", controller.IndexGET)
    router.Run(":8080")
}

docker-compose.ymlappcommandを追加:

    app:
        command: go run main.go
        build: .
        volumes:
            - .:/go/src/go-todo/
        ports:
            - "8080:8080"
        tty: true
        stdin_open: true
        links:
            - db

これでdocker-compose up -dするとサーバーが立ち上がるので、http://localhost:8080 にアクセスできる :tada:

DBの用意

mysql のコンテナに入ってデータベースを作成:

docker-compose exec db mysql -uroot -ppassword
Enter password:

mysql> CREATE DATABASE sampledb;

データベース接続のための設定ファイル。ホスト名はdocker-compose.ymlで記述したdbになることに注意。

db/dbconf.yml:

development:
    driver: mymysql
    open: tcp:db:3306*sampledb/root/password

接続の確認:

$ docker-compose exec app goose status
goose: status for environment 'development'
    Applied At                  Migration
    =======================================

次のコマンドで、マイグレーションファイル(db/migrations/timestamp_createTask.sql)が作成されるので、SQL を追記。

$ docker-compose exec app goose create createTask sql
-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied
CREATE TABLE IF NOT EXISTS task (
    id INT UNSIGNED NOT NULL,
    created_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
    updated_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
    title VARCHAR(255) NOT NULL,
    PRIMARY KEY(id)
);


-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back
DROP TABLE task;

マイグレーションを実行:

$ docker-compose exec app bash goose up

モデルの接続

$ docker-compose exec app bash
/go/src/go-todo # go get -u golang.org/x/tools/cmd/goimports
/go/src/go-todo # go get -u github.com/xo/xo

xo ドライバ://ユーザー:パスワード@ホスト/データベースコマンドで各 model ファイルを作成:

/go/src/go-todo # mkdir -p models
/go/src/go-todo # xo mysql://root:password@db/sampledb -o models

models/model.goファイルを作成し、接続情報を記述する:

package models

import (
    "database/sql"
    "log"

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

// DBConnect returns *sql.DB
func DBConnect() (db *sql.DB) {
    dbconf := "root:password@tcp(db:3306)/sampledb"
    db, err := sql.Open("mysql", dbconf)
    if err != nil {
        log.Fatal(err)
    }
    return db
}

あとは同じなので省略!