LoginSignup
31
23

More than 1 year has passed since last update.

Dokcer ComposeでGoとPostgreSQLの開発環境構築

Last updated at Posted at 2018-12-15

構成

Go アプリ

アプリ名/コンテナ名
app/app
機能
IDを指定してテーブルを検索・結果表示
フォルダ共有
コンテナ中の go ファイルをホストOS から編集できるようにしたいので、
ホストOS の go ファイルがあるフォルダを golang コンテナにマウント

PostgreSQL

コンテナ名
postgres
ユーザ名/パスワード
app_user/password
データベース名/テーブル名
app_db/TEST_USER
テストデータ
コンテナ起動時にテーブル作成とデータ挿入を行う

ファイル配置

$GOPATH/src/app 中に、docker と go ソースコードを次のような形で配置

$GOPATH/src/app
│
├─docker-compose.yml
├─docker
│  ├─golang
│  │   └─Dockerfile
│  └─postgres
│      ├─Dockerfile
│      └─init
│          ├─1_create_table.sql
│          └─2_insert_testdata.sql
└─go
    └─main.go

Docker 設定

Docker Compose

「今日から始めるDocker【docker-composeを使ってGo & Mysqlをよしなに起動しよう編】」1 を参考にしました。

docker-compose.yml
# docker-compose のバージョン
version: '3'

# 各コンテナの情報
services:

  # postgres サービス
  postgres:
    # コンテナの名前
    container_name: postgres
    # Dockerfile のディレクトリパス
    build:
      context: .
      dockerfile: ./docker/postgres/Dockerfile
    # postgres 設定
    environment:
      - POSTGRES_USER=app_user
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=app_db

  # golang アプリケーション
  app:
    container_name: app
    # postgres をビルドした後に app をビルド
    depends_on:
      - postgres
    # Dockerfile を指定
    build:
      context: .
      dockerfile: ./docker/golang/Dockerfile
    # GOPATHを指定
    environment:
      - GOPATH=/go
    # フォルダ共有(ホストOS:コンテナ)
    volumes:
      - ./go:/go/src/app/go/
    # docker-compose run 実行時に実行されるコマンド
    command: go run main.go

Dockerfile

app

Dockerfile
FROM golang:1.9

# コンテナ作業ディレクトリの変更
WORKDIR /go/src/denki/go
# ホストOSの ./go の中身を作業ディレクトリに追加
ADD ./go .

# パッケージのインストール
RUN go get github.com/lib/pq

postgres

Dockerfile
FROM postgres:latest
RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8
ENV LANG ja_JP.UTF-

# 初期化用 sql ファイルを、コンテナ内の所定のディレクトリにコピー
COPY ./docker/postgres/init/*.sql /docker-entrypoint-initdb.d/

/docker-entrypoint-initdb.d/ 内に sql ファイルを配置すると、それらを自動で実行してくれるらしい2

その他ファイル

SQLファイル

テーブル作成

1_create_table.sql
CREATE TABLE TEST_USER (
    user_id BIGINT PRIMARY KEY,
    user_password VARCHAR(20) NOT NULL
);

テストデータ挿入

2_insert_testdata.sql
DELETE FROM TEST_USER;
INSERT INTO TEST_USER VALUES(1, 'password1');
INSERT INTO TEST_USER VALUES(2, 'password2');

Go

書籍「Goプログラミング実践入門」3を参考にしました

main.go
package main

import (
    "database/sql"
    "fmt"
    "log"

    // postgres ドライバ
    _ "github.com/lib/pq"
)

// TestUser : テーブルデータ
type TestUser struct {
    UserID   int
    Password string
}

// メイン関数
func main() {

    // Db: データベースに接続するためのハンドラ
    var Db *sql.DB
    // Dbの初期化
    Db, err := sql.Open("postgres", "host=postgres user=app_user password=password dbname=app_db sslmode=disable")
    if err != nil {
        log.Fatal(err)
    }

    // SQL文の構築
    sql := "SELECT user_id, user_password FROM TEST_USER WHERE user_id=$1;"

    // preparedstatement の生成
    pstatement, err := Db.Prepare(sql)
    if err != nil {
        log.Fatal(err)
    }

    // 検索パラメータ(ユーザID)
    queryID := 1
    // 検索結果格納用の TestUser
    var testUser TestUser

    // queryID を埋め込み SQL の実行、検索結果1件の取得
    err = pstatement.QueryRow(queryID).Scan(&testUser.UserID, &testUser.Password)
    if err != nil {
        log.Fatal(err)
    }

    // 検索結果の表示
    fmt.Println(testUser.UserID, testUser.Password)
}

Docker Compose の実行

シェルで以下のコマンドを実行

$ docker-compose build  # イメージの作成
$ docker-compose up     # コンテナの作成、起動

コンテナの起動順序を指定していないため、postgres より前に app コンテナが先に起動する場合がある。
そうなると DB にテーブルが存在しないので、以下のエラーが吐かれる

app     | 2018/12/15 13:50:02 dial tcp 172.29.0.2:5432: getsockopt: connection refused

一回 Ctrl+C でコンテナを停止させ、もう一度 docker-compose up でコンテナを実行すると、app の実行結果( app | 1 password1 )が表示される

※起動順序を指定したいときは、docker-compose の entrypoint とスクリプトによって、DBコンテナが起動するまでアプリ起動を待機させる方法がある 4

コンテナの停止・破棄

docker-compose down

イメージの破棄

docker image rm app_app app_postgres

詰まったところ

go get に失敗する

イメージのビルドの際、go get において

cannot find package "パッケージ名" ... (from $GOROOT) ... (from $GOPATH)

のエラーが出てビルドに失敗することがある。原因として、

  • パッケージ自体が存在しないか、パスが間違っている
  • golang イメージに git がインストールされていない5

があるらしいので、URIを確認するなり、イメージのバージョンを golang:1.9 に変更する等する

postgres コンテナに接続できない

main.go の DB 接続設定で

var Db *sql.DB
// Dbの初期化
Db, err := sql.Open("postgres", "host=localhost user=...

のように host=localhost とすると

app  | ... dial tcp 127.0.0.1:5432: connect: connection refused

データベース接続エラーが吐かれる。host の値は、接続先のコンテナ名にする必要がある6 ので、host=postgres に修正して解決

31
23
1

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
31
23