GO + Gin + Postgres + Dockerの環境構築
初めに
初めての投稿になります。業務で、Gin(Goのフレームワーク) + Postgres + Docker の環境構築をしたので記事に残しておきます。
複数コンテナを動かすため、docker-composeを使用しました。参考にしてみてください。
参考にした記事
今回環境構築に成功したのは先人の記事のおかげです。ありがとうございます。
想定環境
- 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
ソースコードは下記ページになります。
本記事ではDocker上でGinアプリを動かす人のために書いたので、Ginアプリ内の詳細は省きます。
まずはそれぞれのファイルを書いていきます。
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:
# 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
CREATE DATABASE IF NOT EXISTS app;
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())
}
}
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
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
もし勘違いだったら申し訳ないのですが、envでは
と書いてあってdocker-composeでは
となっているため、"docker-compose up -d"でpostgresコンテナが起動しないと思います。
コメントありがとうございます。
docker-composeにあるdbとcontainer_name: ${DB_HOST}ですが、container_nameはコンテナ名を一意にするために利用するものだと考えていました。確認したところ自分の環境ではコンテナの立ち上げができました。
ただ、docker-composeの書き方がよくないと思うので、mainブランチを修正しています。必要であればご利用ください。
ご返信いただきありがとうございます。
こちらの環境で実行したところ、container_nameをそのままだと起動できず、変更すると起動できましたため勘違いしていたかもしれないです。
わざわざ対応ありがとうございます。
レポジトリ、ありがたく利用させていただきます。