Go + Docker + CoreOS + Vagrant で開発環境を構築


備忘録

ローカルで実行してもいいけれど、最終的にnginxをフロントに置く構成を想定していたのでVagrantで環境を構築。せっかくなので構成を出来る限り再現するためDocker経由の構成まで作った。

Vagrantの共有フォルダでローカルのsrcを含むパスをGOPATHとして参照するようにして、ソースコードの編集〜Docker再起動でビルドして実行が可能としている。

ホストOS：MacOS X El Capitan
Vagrant: CoreOS 976.0.0

## Dockerイメージを作成

開発時はビルドができるように[gb](https://getgb.io/)を入れる。

```docker
FROM golang:1.6.0

RUN go get github.com/constabulary/gb/...
RUN mv /go/bin/gb /usr/local/go/bin
RUN mv /go/bin/gb-vendor /usr/local/go/bin

EXPOSE 9090

COPY entrypoint.sh /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]
```

entrypoint.shはsrc/があればビルドしてからアプリ(bin/app)を実行。

```bash
#!/bin/bash
set -e

cd /go
if [ -e src ]; then
  gb build
fi
bin/app
```

Dockerイメージを作成してdocker pushする。

## cloud-configを作成

NginxとGoアプリを導入。-vオプションを指定してホストOSと接続する。Docker側では/goがGOPATHになっている。

```bash
#cloud-config

---
coreos:
  units:
  - name: docker-tcp.socket
    command: start
    enable: true
    content: |
      [Unit]
      Description=Docker Socket for the API

      [Socket]
      ListenStream=2375
      Service=docker.service
      BindIPv6Only=both

      [Install]
      WantedBy=sockets.target
  - name: nginx.service
    command: start
    enable: true
    content: |
      [Unit]
      Description=Nginx
      After=docker.service
      Requires=docker.service

      [Service]
      TimeoutStartSec=15m
      ExecStartPre=-/usr/bin/docker kill nginx
      ExecStartPre=-/usr/bin/docker rm nginx
      ExecStartPre=-/usr/bin/docker pull danday74/nginx-lua
      ExecStart=/bin/bash -c "\
        /usr/bin/docker run --name nginx \
        -p 80:80 \
        -v /nginx/conf:/nginx/conf:ro \
        -v /nginx/html:/nginx/html:ro \
        -v /nginx/log:/var/log/nginx \
        danday74/nginx-lua"
      ExecStop=/usr/bin/docker stop nginx

      [Install]
      WantedBy=multi-user.target
  - name: app.service
    command: start
    enable: true
    content: |
      [Unit]
      Description=App
      After=docker.service
      Requires=docker.service

      [Service]
      TimeoutStartSec=15m
      ExecStartPre=-/usr/bin/docker kill app
      ExecStartPre=-/usr/bin/docker rm app
      ExecStartPre=-/usr/bin/docker pull sample/app:1.0
      ExecStart=/bin/bash -c "\
        /usr/bin/docker run --name app \
        -p 9090:9090 \
        -v /go:/go \
        sample/app:1.0"
      ExecStop=/usr/bin/docker stop app

      [Install]
      WantedBy=multi-user.target
```

## Vagrantfileを作成

[coreos/coreos-vagrant](https://github.com/coreos/coreos-vagrant)を使用する

Dockerの-vオプションで指定したフォルダをVagrantの共有フォルダでローカル側と接続すると、ローカル環境をDockerボリュームに接続できる。以下ではapp/をGOPATHとしている。

```bash
ROOT_PATH = File.dirname(__FILE__)
LOG_PATH = File.join(ROOT_PATH, "log")
NGINX_CONF = File.join(ROOT_PATH, "config/nginx")
NGINX_ROOT = File.join(ROOT_PATH, "html")
GOPATH = File.join(ROOT_PATH, "app")

$shared_folders = {
  "#{LOG_PATH}" => "/nginx/log",
  "#{NGINX_CONF}" => "/nginx/conf",
  "#{NGINX_ROOT}" => "/nginx/html",
  "#{GOPATH}" => "/go"
}
```

## Vagrantを起動してログインする

```bash
$ vagrant up
$ vagrant ssh
```

### CoreOSのサービスが起動していることを確認する

```bash
$ systemctl | grep app
app.service                        loaded active running   App
```

### コードを変更して動作確認を行う

ローカル側でapp/srcのコードを変更して、CoreOSからサービスの再起動を行うとDocker内でビルドを実施する

```bash
$ sudo systemctl restart app
```