構成

Go アプリ

アプリ名/コンテナ名

 

app/app

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

PostgreSQL

コンテナ名

 

postgres

 

ユーザ名/パスワード

 

app_user/password

 

データベース名/テーブル名

 

app_db/TEST_USER

 

テストデータ

 

コンテナ起動時にテーブル作成とデータ挿入を行う

ファイル配置

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

│
├─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 のバージョン
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

FROM golang:1.9

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

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

postgres

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ファイル

テーブル作成

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

テストデータ挿入

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

Go

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

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 に修正して解決

https://qiita.com/yu-croco/items/0c0d5083298f7db9e1bb ↩

https://qiita.com/hirosemi/items/199a3c753130c12d52f1 ↩

https://book.impress.co.jp/books/1115101145 ↩

http://docs.docker.jp/compose/startup-order.html ↩

https://stackoverflow.com/questions/44210502/docker-compose-cannot-find-package-golang ↩

https://qiita.com/unvavo/items/7b3d1ef9403f6b4b8456 ↩

广告
将在 10 秒后关闭
bannerAds