Dockerで、DynamoDB Localを動かしてGo言語で操作する環境を構築する

## はじめに


![20180815165541.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2278/9fae9230-22b0-0ebb-c668-7afcf92766a4.png)

上記の環境を構築する方法をご紹介します。
以下のような方向けの記事となっております。

- Go言語でDynamoDBを操作する環境を手に入れたい
- Dockerで開発環境を構築する流れをざっくりと知りたい

DockerとDocker Composeが使える状態になっていることが前提となっております。

https://docs.docker.com/docker-for-mac/install/

ひとまず環境が欲しい場合は、以下の手順で手に入れることができます。

```bash
$ git clone git@github.com:memememomo/go-docker-dynamodb-sample.git
$ cd go-docker-dynamodb-sample
$ docker-compose build
$ docker-compose run go
```


## 作業用のディレクトリを作成

まずはディレクトリを作成します。

```bash
$ mkdir go-docker-dynamodb-sample
$ cd go-docker-dynamodb-sample
```

## Go言語用Dockerfile

Goプログラムを実行するためのコンテナを作成します。
使用するイメージは `golang:1.11.5-alpine`です。

```dockerfile:Dockerfile_go
FROM golang:1.11.5-alpine

# 必要なパッケージをインストール
RUN apk add --no-cache git bash make curl gcc libc-dev openssl && \
    go get -u github.com/golang/dep/cmd/dep && \
    go get -u golang.org/x/lint/golint && \
    go get -u github.com/kyoh86/richgo

# コンテナ内のディレクトリを作成
WORKDIR /go/src/go-docker-dynamodb-sample

# ホストPCのカレントディレクトリにあるファイルを、コンテナ内のディレクトリにコピー
COPY . /go/src/go-docker-dynamodb-sample

# Go言語で使う依存モジュールをインストール
RUN dep ensure
```

## DynamoDB Local用Dockerfile

DynamoDB Localのサーバを立ち上げるためのコンテナを作成します。
使用するイメージは `amazon/dynamodb-local` です。Amazonから公式に配布されているイメージです。

```dockerfile:Dockerfile_dynamodb
FROM amazon/dynamodb-local

# ポートをListenする設定。外部からDynamoDBにアクセスするため
EXPOSE 8000
```

Goを実行するコンテナからDynamoDB Localのコンテナにアクセスするために8000番ポートをListenする設定になっています。


## docker-compose.ymlの設定

Go と DynamoDB Local のそれぞれのコンテナを統合するように、Docker Compose の設定を行います。

```yaml:docker-compose.yml
version: '3'
services:
  go:
    command: ./scripts/run.sh
    build:
      context: ./
      dockerfile: ./Dockerfile_go
    volumes:
      - .:/go/src/go-docker-dynamodb-sample
    depends_on:
      - dynamodb
    environment:
      - DYNAMO_ENDPOINT=http://dynamodb:8000/
    networks:
      - network

  dynamodb:
    build:
      context: ./
      dockerfile: ./Dockerfile_dynamodb
    ports:
      - '8000:8000'
    networks:
      - network

networks:
  network:
    driver: bridge
```

## Goプログラムを用意

簡単なGoプログラムを用意します。
まず、依存パッケージの設定を行います。depを使うので、Gopkg.toml に記述していきます。

```go:Gopkg.toml
[prune]
    go-tests = true
    unused-packages = true

[[constraint]]
  name = "github.com/guregu/dynamo"
  version = "v1.1.1"
```

Goプログラムは以下のようにしています。

```go:sample.go
package main

import (
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/guregu/dynamo"
	"os"
)

type Sample struct {
	UserID string `dynamo:"UserID,hash"`
	Name string `dynamo:"Name"`
}

func main() {
	sess, err := session.NewSession(&aws.Config{
		Region: aws.String("ap-northeast-1"),
		Endpoint: aws.String(os.Getenv("DYNAMO_ENDPOINT")),
		Credentials: credentials.NewStaticCredentials("dummy", "dummy", "dummy"),
	})
	if err != nil {
		panic(err)
	}

	db := dynamo.New(sess)

	db.Table("Samples").DeleteTable().Run()

	err = db.CreateTable("Samples", Sample{}).Run()
	if err != nil {
		panic(err)
	}

	table := db.Table("Samples")
	err = table.Put(&Sample{UserID: "1", Name: "Test1"}).Run()
	if err != nil {
		panic(err)
	}

	var sample Sample
	err = table.Get("UserID", "1").One(&sample)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%+v\n", sample)
}
```

Goプログラムを実行するスクリプトを用意します。以下のようにファイルを作成します。

```bash
$ mkdir scripts
$ touch scripts/run.sh
$ chmod +x scripts/run.sh
```

ファイルの内容は以下のようになります。

```bash:scripts/run.sh
#!/bin/bash
dep ensure
go run sample.go
```

これで、プログラムを実行する準備が整いました。

## プログラムの実行

以下のように、docker-composeコマンド経由でプログラムを実行します。

```bash
$ docker-compose build
$ docker-compose run go
```

コンテナが起動して、その中でDynamoDB LocalとGoプログラムが実行されます。

以上で、環境を構築することができました。


## おわりに

手元のPCで、DynamoDB LocalとGo言語を使って検証できる環境をDockerを使用して構築しました。
実際の開発で挙動を確認したい場合が出てくるので、こういった環境を用意しておくと便利です。

Gopher
https://github.com/golang-samples/gopher-vector#gopher