『ホットリロード x Go言語 x MySQL』なHTTPサーバのDocker環境構築手順

インフラ

データベース接続をするGo言語製HTTPサーバのDocker環境構築について紹介します。
『コンテナ上のHTTPサーバとデータベースの疎通確認をする』をゴールとします。

Goは1.16.3、データベースはMySQL 8.0.21を利用します。

ホットリーロド可能なHTTPサーバのDocker環境を構築

GO言語で実装されたHTTPサーバをDocker化します。
構築手順の詳細は【Go言語】ホットリロード可能なHTTPサーバのDocker環境構築手順で解説をしているので、あわせてご覧になってください。

ホットリロードはAirで行います。Airの詳細についてはGo言語のホットリロードツール『Air』でコードの修正を即時反映させるをご覧になってください。

main.go

package main

import (
    "log"
    "net/http"
)

func rootHander(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(200)
    w.Header().Set("Content-Type", "text/html; charset=utf8")
    w.Write([]byte("こんにちは"))
}

func main() {
    http.HandleFunc("/", rootHander)
    log.Fatal(http.ListenAndServe(":3000", nil))
}

Dockerfile

FROM golang:1.16.3-buster

# コンテナの作業ディレクトリにローカルのファイルをコピー
WORKDIR /app
COPY . /app

# 必要なパッケージをインストール
RUN go mod tidy

# Airをインストール
RUN go install github.com/cosmtrek/air@v1.27.3

# airコマンドでGoファイルを起動
CMD ["air"]

docker-compose.yml

version: '3'
services:
  app:
    build: .
    ports:
      - '3030:3000' # ローカルの3030番ポートでコンテナの3000番ポートに接続
    volumes:
      - .:/app # ローカルとコンテナのディレクトリをバインドマウント(同期)
      - go_path:/go # パッケージやバイナリファイルのインストール先($GOPATH)を永続化
    command: ["./start.sh"]
volumes:
  go_path:

start.sh

#!/bin/bash -eu
go mod tidy
air

動作確認

コンテナ上のHTTPサーバにリクエストが届くことを確認します。
curl localhost:3030でレスポンスが返ってくればOKです。

### 作業ディレクトリの作成と移動
$ mkdir go-docker-example && cd $_

### go.modの作成
$ go mod init `basename $PWD`

### ファイルの確認
$ ls
Dockerfile  docker-compose.yml  go.mod  main.go start.sh

### バックグラウンドで起動
$ docker-compose up -d

### 接続の確認
$ curl localhost:3030

こんにちは

データベース接続設定を追加

Go言語でデータベース(MySQL)に接続する方法で紹介した手順をもとにmain.goの修正と、データベース接続に関するパッケージの作成をします。

main.go

package main

import (
    "go-docker-example/database"
    "log"
    "net/http"
)

func rootHander(w http.ResponseWriter, r *http.Request) {
    db := database.Connect()
    defer db.Close()

    err := db.Ping()

    if err != nil {
        w.Write([]byte("データベース接続失敗"))
        return
    } else {
        w.WriteHeader(200)
        w.Header().Set("Content-Type", "text/html; charset=utf8")
        w.Write([]byte("データベース接続成功"))
    }
}

func main() {
    http.HandleFunc("/", rootHander)
    log.Fatal(http.ListenAndServe(":3000", nil))
}

database/connect.go

package database

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

    "github.com/joho/godotenv"

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

func Connect() *sql.DB {
    err := godotenv.Load()
    if err != nil {
        fmt.Println(err.Error())
    }

    user := os.Getenv("DB_USER")
    password := os.Getenv("DB_PASSWORD")
    host := os.Getenv("DB_HOST")
    port := os.Getenv("DB_PORT")
    database_name := os.Getenv("DB_DATABASE_NAME")

    dbconf := user + ":" + password + "@tcp(" + host + ":" + port + ")/" + database_name + "?charset=utf8mb4"
    db, err := sql.Open("mysql", dbconf)
    if err != nil {
        fmt.Println(err.Error())
    }
    return db
}

.env

DB_USER=webuser
DB_PASSWORD=webpass
DB_HOST=db
DB_PORT=3306
DB_DATABASE_NAME=go_mysql8_development

次にdocker-compose.ymlの修正をします。
データベースコンテナを新しく追加し、HTTPサーバとデータベースがDocker上で疎通できるようにします。

docker-compose.yml

version: '3'
services:
  app:
    build: .
    ports:
      - '3030:3000'
    volumes:
      - .:/app
      - go_path:/go
  db:
    image: mysql:8.0.21
    ports:
      - '3306:3306'
    command: --default-authentication-plugin=mysql_native_password
    environment:
      MYSQL_USER: 'webuser'
      MYSQL_PASSWORD: 'webpass'
      MYSQL_ROOT_PASSWORD: 'pass'
      MYSQL_DATABASE: 'go_mysql8_development'
volumes:
  go_path:

動作確認

コンテナを起動し、HTTPサーバとデータベースの疎通確認を行います。
『データベース接続成功』のレスポンスが返ってくればOKです。

### 作業ディレクトリへ移動
$ cd /path/to/go-docker-example

### ファイルの確認
$ tree -L 1

├── Dockerfile
├── database
│   └── connect.go
├── docker-compose.yml
├── go.mod
├── go.sum
├── main.go
└── start.sh

### バックグラウンドで実行
$ docker-copmose up -d

### 接続の確認
$ curl localhost:3030
データベース接続成功

さいごに

Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!