🐳

docker-compose で Go + PostgreSQL の環境構築をする

に公開
2

はじめに

docker-compose で Go + PostgreSQL の環境構築をしてみました。

なお、作成したものは以下のレポジトリで公開しています。
https://github.com/t-shimpo/go-postgres-docker

ディレクトリ構成

myapp
├── docker-compose.yml
├── Dockerfile
├── go.mod
├── go.sum
└── main.go

アプリの作成

検証のための簡単なアプリを作成します。

go mod init を実行します。

go.mod
module github.com/t-shimpo/go-postgres-docker

go 1.24.0

/にアクセスすると Hello, World! と表示されるプログラムを実装しました。

main.go
package main

import (
    "fmt"
    "log"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    http.HandleFunc("/", handler)
    fmt.Println("Server running on port 8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

go run main.goを実行し、localhost:8080にアクセスすると Hello World! と表示されます。

Goコンテナを作成

続いて、GoをDockerで動かせるようにします。
以下のDockerfiledocker-compose.ymlを追加しました。

Dockerfile
FROM golang:1.24

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .

CMD ["go", "run", "main.go"]

COPY go.mod go.sum ./について、後の実装でgo.sumが更新されるのでgo.sumも含めています。
ファイルがない場合エラーになるので、空ファイルでgo.sumを追加しておきます。

docker-compose.yml
services:
  app:
    build: .
    container_name: app
    ports:
      - "8080:8080"
    volumes:
      - .:/app

以下のコマンドを実行して、アプリが実行できるか確認します。

$ docker-compose up -d

localhost:8080にアクセスし Hello World! と表示されることを確認します。

PostgreSQLコンテナを作成

続いて、PostgreSQLをDockerで動かせるようにします。
docker-compose.ymlを更新しました。

docker-compose.yml
services:
  app:
    build: .
    container_name: app
    ports:
      - "8080:8080"
    volumes:
      - .:/app
    depends_on:
      - db
    environment:
      DATABASE_URL: postgres://user:password@db:5432/mydb?sslmode=disable

  db:
    image: postgres
    container_name: postgres
    restart: always
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: mydb
    ports:
      - "5432:5432"
    volumes:
      - postgres-data:/var/lib/postgresql/data

volumes:
  postgres-data:

今回は簡単に、DB接続用の情報をGoアプリでDATABASE_URLとして取得できるようにしています。

dockerを起動して、PostgreSQLのコンテナに入れるか確認します。

$ docker-compose up -d

以下のコマンドを実行して、PostgreSQLにログインできるか確認します。
postgresはコンテナ名です。

$ docker exec -it postgres psql -U user -d mydb

成功すればmydb=# のようなプロンプトが表示されます。

補足

depends_on

以下の設定でdbコンテナが起動してからappコンテナを起動するようにしています。

depends_on:
  - db

PostgreSQL の起動完了を保証するわけではないため、アプリ側でリトライ処理の実装や、healthcheckを追加しアプリがデータベースの準備完了を待つようにするのが望ましいです。

healthcheckの場合は以下のように設定できます。

docker-compose.yml
services:
  app:
    //
    depends_on:
+      db:
+        condition: service_healthy

  db:
    //
    volumes:
      - postgres-data:/var/lib/postgresql/data
+    healthcheck:
+      test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
+      interval: 10s
+      retries: 5
+      start_period: 30s
+      timeout: 10s 

depends_on: - dbでは、単にdbコンテナが起動するのを待つだけですが、service_healthy を使うことで、dbが正常に応答できる状態になってからappを起動することができます。

📌 参考URL: https://docs.docker.com/compose/how-tos/startup-order/#example

volumes

以下の設定はデータの永続に関する設定です。

volumes:
  postgres-data:

postgres-data というボリュームを作成し、PostgreSQL のデータ(/var/lib/postgresql/data)を永続化しています。
これにより、コンテナを削除してもデータが保持されます。

接続確認

GoアプリとpostgresDBの接続を確認します。
main.goを以下のように更新しました。

main.go
package main

import (
    "database/sql"
    "fmt"
    "log"
    "net/http"
    "os"

    _ "github.com/lib/pq"
)

func handler(w http.ResponseWriter, r *http.Request) {
    dbURL := os.Getenv("DATABASE_URL")
    if dbURL == "" {
        http.Error(w, "DATABASE_URL not set", http.StatusInternalServerError)
        return
    }

    db, err := sql.Open("postgres", dbURL)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    err = db.Ping()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    defer db.Close()

    w.WriteHeader(http.StatusOK)
    w.Write([]byte("Database connection successful"))
}

func main() {
    http.HandleFunc("/", handler)
    fmt.Println("Server running on port 8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

github.com/lib/pqはPostgreSQL用のドライバです。
PostgreSQLに接続するにはこちらが必要となります。
外部パッケージを追加したので、go mod tidyも実行しておきます。

dockerを起動して動作確認します。

$ docker-compose up -d

localhost:8080にアクセスし Database connection successful と表示されれば成功です。

参考資料

https://hub.docker.com/_/golang

https://hub.docker.com/_/postgres

https://docs.docker.jp/compose/toc.html

https://docs.docker.com/compose/how-tos/startup-order/#example

GitHubで編集を提案

Discussion