🎃

GO + Gin + Postgres + Dockerの環境構築

2023/03/24に公開
3

初めに

初めての投稿になります。業務で、Gin(Goのフレームワーク) + Postgres + Docker の環境構築をしたので記事に残しておきます。

複数コンテナを動かすため、docker-composeを使用しました。参考にしてみてください。

参考にした記事

https://zenn.dev/ajapa/articles/65b9934db18396
https://www.w2solution.co.jp/corporate/tech/dockercomposeでgoのginとmysqlの環境を作ってみた-第1弾/

今回環境構築に成功したのは先人の記事のおかげです。ありがとうございます。

想定環境

  • M1 Macbook Air(2021)
  • Docker Desktop

ディレクトリ構成

├── app
│   ├── controller
│   │   ├── post_controller.go
│   │   └── router.go
│   ├── database
│   │   └── init
│   │   └── init_database.sql
│   ├── go.mod
│   ├── go.sum
│   ├── main.go
│   ├── model
│   │   ├── books_model.go
│   │   └── database.go
│   └── view
│   ├── create.html
│   ├── delete.html
│   ├── edit.html
│   ├── index.html
│   └── show.html
├── build
│   └── dockerfiles
│   ├── app
│   │   └── Dockerfile
│   └── db
│   └── Dockerfile
├── docker-compose.yml
└── makefile

ソースコードは下記ページになります。
https://github.com/yasu2122yasu/gin_postgres_app

本記事ではDocker上でGinアプリを動かす人のために書いたので、Ginアプリ内の詳細は省きます。

まずはそれぞれのファイルを書いていきます。

docker-compose.yml
version: '3.8'

services:
  # go_app
  app:
    container_name: ${APP_CONTAINER_NAME}
    build: 
      context: .
      dockerfile: ./build/dockerfiles/app/Dockerfile
    volumes: 
      - ./app:/usr/local/go/src/web/app
      - .env:/usr/local/go/src/web/app/.env
    tty: true 
    depends_on:
      - db
    ports:
      - ${APP_PORT}:8080

  # postgresql
  db:
    container_name: ${DB_HOST}
    build:
      context: .
      dockerfile: ./build/dockerfiles/db/Dockerfile
    environment:
      - POSTGRES_DB=${DB_DATABASE}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - db-store:/var/lib/postgresql/data
      - ./app/database/init:/docker-entrypoint-initdb.d 
    ports:
      - ${DB_PORT}:5432

volumes:
  db-store:
.env
# DBコンテナ名
DB_HOST=database

# init時のdatabase
DB_DATABASE=app

# DB情報
DB_USER=postgres
DB_PASSWORD=postgres
DB_PORT=5432

# app コンテナ
APP_CONTAINER_NAME=app
APP_PORT=8080
init_database.sql
CREATE DATABASE IF NOT EXISTS app;
database.go
package model

import (
	"fmt"
	"time"

	"gorm.io/driver/postgres"
	"gorm.io/gorm"
)

var Db *gorm.DB

func init() {
	dsn := "host=db port=5432 user=postgres password=postgres dbname=app sslmode=disable"
	dialector := postgres.Open(dsn)
	var err error
	if Db, err = gorm.Open(dialector); err != nil {
		connect(dialector, 100)
	}
	fmt.Println("db connected!!")
}

func connect(dialector gorm.Dialector, count uint) {
	var err error
	if Db, err = gorm.Open(dialector); err != nil {
		if count > 1 {
			time.Sleep(time.Second * 2)
			count--
			fmt.Printf("retry... count:%v\n", count)
			connect(dialector, count)
			return
		}
		panic(err.Error())
	}
}
app/Dockerfile
FROM golang:1.20-alpine3.16

COPY app /go/app/

RUN mkdir -p /usr/local/go/src/web/app

WORKDIR /usr/local/go/src/web/app/

RUN apk update \
&& apk add --no-cache git \
&& go get github.com/gin-gonic/gin \
&& go get github.com/jinzhu/gorm \
&& go get github.com/lib/pq \
&& go mod init app \
&& apk add git

EXPOSE 8080
db/Dockerfile
FROM postgres:15.1

RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
ENV LANG ja_JP.utf8

Docker上でGinを動かすまで

Docker Desktopが起動していることが前提です。

#image・containerの作成/起動をまとめて実行してくれます。
¥ docker-compose up -d

# appコンテナに入ります
¥ docker exec -it app sh

/usr/local/go/src/web/app # go run main.go
docker exec -it db sh

を実行してdbコンテナに入ることで、データベース操作も可能になります。

まとめ

もし本記事に問題点・修正点があれば教えてもらえると助かります。

よろしくお願い致します。

Discussion

hukuhuku

もし勘違いだったら申し訳ないのですが、envでは

.env
# DBコンテナ名
DB_HOST=database

と書いてあってdocker-composeでは

docker-compose.yml
services:
    # postgresql
  db:

となっているため、"docker-compose up -d"でpostgresコンテナが起動しないと思います。

yasuyasu

コメントありがとうございます。

docker-composeにあるdbとcontainer_name: ${DB_HOST}ですが、container_nameはコンテナ名を一意にするために利用するものだと考えていました。確認したところ自分の環境ではコンテナの立ち上げができました。

ただ、docker-composeの書き方がよくないと思うので、mainブランチを修正しています。必要であればご利用ください。

https://github.com/yasu2122yasu/gin_postgres_app

hukuhuku

ご返信いただきありがとうございます。

こちらの環境で実行したところ、container_nameをそのままだと起動できず、変更すると起動できましたため勘違いしていたかもしれないです。
わざわざ対応ありがとうございます。

レポジトリ、ありがたく利用させていただきます。