0
0

More than 1 year has passed since last update.

【Go】ログイン機能でウェブアプリを作ってみる(3)

Last updated at Posted at 2023-07-21

こんにちは。

Part 3は準備(MySQL & docker-compose.yml)についてです。

目標

  • MySQLを起動する
  • GoからMySQLに接続する

MySQLを起動する

MySQLの設定ファイルを準備します。

早速、MySQLを起動の前に、後々必要になるかもしれない設定などをしています。
そのために必要なディレクトリを作成します。

$ mkdir -p _tools/mysql/{init.d,conf.d}

今回で言うとMySQLに関するファイルを_toolsディレクトリ以下にまとめます。

_tools/mysql/conf.dにはMySQLの設定ファイルを置きます。

_tools/mysql/conf.d/my.cnf

[mysqld]
character-set-server=utf8mb4

[client]
default-character-set=utf8mb4

_tools/mysql/init.dには今回使うユーザーのテーブル作成用のファイルを作成します。

_tools/mysql/init.d/init.sql

CREATE TABLE `user` (
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `email` VARCHAR(255) NOT NULL UNIQUE,
  `password` VARCHAR(60) NOT NULL,
  `salt` VARCHAR(30) NOT NULL,
  `state` VARCHAR(8) NOT NULL,
  `activate_token` VARCHAR(8) NOT NULL,
  `updated_at` DATETIME(6) NOT NULL,
  `created_at` DATETIME(6) NOT NULL,
  PRIMARY KEY (`id`),
  INDEX email_idx (email)
) Engine=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=100001;

これで設定ファイルの準備は完了です。

MySQLを起動する

docker-compose.yml

version: "3.8"

services:
  api:
    container_name: login-example-api
    build:
      dockerfile: Dockerfile
      context: .
    volumes:
      - ".:/app"
    ports:
      - "8000:8000"
    environment:
      DB_USER: login-user
      DB_PASSWORD: login-pass
      DB_NAME: login-db
      DB_HOST: db
      DB_PORT: 3306
    depends_on:
      db:
        condition: service_healthy
  db:
    container_name: login-example-db
    image: mysql:8.0.33
    platform: linux/amd64
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: login-db
      MYSQL_USER: login-user
      MYSQL_PASSWORD: login-pass
    ports:
      - "33306:3306"
    volumes:
      - type: volume
        source: login-example-db
        target: /var/lib/mysql
      - type: bind
        source: ./_tools/mysql/conf.d
        target: /etc/mysql/conf.d
      - type: bind
        source: ./_tools/mysql/init.d
        target: /docker-entrypoint-initdb.d
    healthcheck:
      test: ["CMD", "mysqladmin", "ping"]
      interval: 5s
      timeout: 5s
      retries: 5
  mail:
    container_name: login-example-mail
    image: mailhog/mailhog
    platform: linux/x86_64
    ports:
      - "8025:8025"
      - "1025:1025"
volumes:
  login-example-db:

part2で作成したdocker-compose.ymlを修正いたしました。

サービスを起動します。

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

これで起動ができました。
これでMySQLの準備はOKです!

GoからMySQLに接続する

接続するために必要なパッケージをダウンロードしておきます。

$ go get github.com/go-sql-driver/mysql
$ go get github.com/jmoiron/sqlx

必要なパッケージが準備できたら接続用のコードを書いていきます。
db/db.go

package db

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

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

func NewDB() (*sqlx.DB, error) {
	// 環境変数からDBの情報を取得します
	dbUser := os.Getenv("DB_USER")         // login-user
	dbPassword := os.Getenv("DB_PASSWORD") // login-pass
	dbHost := os.Getenv("DB_HOST")         // db
	dbName := os.Getenv("DB_NAME")         // login-db
	dbPort := os.Getenv("DB_PORT")         // 3306
	src := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true",
		dbUser, dbPassword, dbHost, dbPort, dbName)

	db, err := sql.Open("mysql", src)
	if err != nil {
		return nil, fmt.Errorf("failed to Open DB: %w", err)
	}

	// mysqlに実際に接続できているかpingで確認します。
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel()
	if err := db.PingContext(ctx); err != nil {
		db.Close()
		return nil, fmt.Errorf("failed to Ping DB: %w", err)
	}

	xdb := sqlx.NewDb(db, "mysql")
	return xdb, nil
}

MySQLに接続するためのコードが書けました。

では、本当にこのコードで接続できるか確認いたします。

確認

MySQLに本当に接続できるか確認するためのmain.goを修正します。

main.go

package main

import (
	"fmt"
	"login-example/db"
)

func main() {
	db, err := db.NewDB()
	if err != nil {
		fmt.Println(err)
		return
	}
	defer db.Close()

	fmt.Println("MySQL接続OK")
}

logで確認

$ docker compose logs api -f

# 最後に「MySQL接続OK」と出れば接続できています!
login-example-api   |   __    _   ___  
login-example-api   |  / /\  | | | |_) 
login-example-api   | /_/--\ |_| |_| \_ , built with Go 
login-example-api   | 
login-example-api   | mkdir /app/tmp
login-example-api   | watching .
login-example-api   | watching _tools
login-example-api   | watching _tools/mysql
login-example-api   | watching _tools/mysql/conf.d
login-example-api   | watching _tools/mysql/init.d
login-example-api   | watching db
login-example-api   | !exclude tmp
login-example-api   | building...
login-example-api   | go: downloading github.com/go-sql-driver/mysql v1.7.1
login-example-api   | go: downloading github.com/jmoiron/sqlx v1.3.5
login-example-api   | running...
login-example-api   | MySQL接続OK

まとめ

ディレクトリ構成は次のようになりました。

.
├── Dockerfile
├── .air.toml
├── _tools
│   └── mysql
│       ├── conf.d
│       │   └── my.cnf
│       └── init.d
│           └── init.sql
├── db
│   └── db.go
├── docker-compose.yml
├── go.mod
├── go.sum
└── main.go

今日は以上です。
ありがとうございました。

今日作成したアプリをgithubに追加しました。
必要な場合はこちらのリンクをクリックしてください。

次のPart 4はdocker-compose.ymlの解説です。
よろしくお願いいたします。

0
0
0

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
0
0