Go
nginx
Docker
docker-compose
hot-reload

Docker+golang+Nginxでリバースプロキシ・ホットリロードな開発環境を構築する


はじめに

こんにちは、3Dとかゲームがメインのyoship1639です。

Web知識皆無な人間だったのですが、最近Web系を触るようになり(強制)、その中でDocker+golang+NginxでWebサービスを作るという状況になったので、備忘録含めどうやったらDocker上でNginx+golangな環境を構築できるのかをご紹介したいと思います。

なるべく最小限の環境を構築したいので、Nginxは設定としてリバースプロキシ部分のみ、golangはrealizeによるホットリロード機能のみを記述します。

一応、私の環境はこんな感じです

・Win10 64bit Home

・VSCode 1.34.0

・Virtualbox 5.2.8 r121009

・Docker 18.03.0-ce


構築

今回作成するプロジェクト名はわかりやすく「docker_go_nginx」とします。

配置場所はgo/src/github.com/docker_go_nginxです。

フォルダ構成は以下の通りです。

docker_go_nginx

├─ app
│ ├─ main.go
│ └─ .realize.yml
├─ nginx
│ ├─ Dockerfile
│ └─ nginx.conf
├─ docker-compose.yml
└─ Dockerfile

それぞれについて見ていきます


docker-compose.yml

docker-composeファイルは以下のようになります。


docker-compose.yml

version: "3"

services:
golang:
tty: true
build: "."
volumes:
- ./app:/go/src/github.com/docker_go_nginx/app
ports:
- "3000"
command: bash -c "cd app && realize start --server"
nginx:
build: ./nginx
ports:
- "80:80"
depends_on:
- "golang"


golangコンテナのポートはNginxのプロキシを通すので80ではなく3000を指定しています。逆にNginxのコンテナに80を指定します。また、golangコンテナ起動時にホットリロードを開始させます(realize start --server)。これによってついでにmain.goが自動で走ります。

nginxはgolangのリバースプロキシになるのでdepends_on: - "golang"を指定します。


Dockerfile (golang用)


Dockerfile

FROM golang:latest

RUN go get -u github.com/oxequa/realize && \
go get -u github.com/gorilla/mux

WORKDIR /go/src/github.com/docker_go_nginx/


golangは最新のイメージを取得し、realizeパッケージをgo getします。

WORKDIR /go/src/github.com/docker_go_nginx/は後でコンテナのシェルに入ったときに一々cdするのが面倒なので予めワークディレクトリとして指定しておきます。


Dockerfile (nginx用)


Dockerfile

FROM nginx:latest

COPY ./nginx.conf /etc/nginx/nginx.conf

設定はホスト側のnginx.confを適用させたいので、コンテナ側の/etc/nginx/nginx.confにコピーします。


nginx.conf


nginx.conf

worker_processes auto;

events {
worker_connections 1024;
}

http {
server {
listen 80;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;

proxy_pass http://golang:3000;
}
}
}


非常に最小限なnginx.confです。80ポートをlistenしたらリバースプロキシとしてhttp://golang:3000にパスします。これで、Nginx経由でwebアプリ(golang)にアクセスします。

また、http://golang:3000golangはservicesに記述したサービス名と同じにしてください。そうしないとちゃんと動いてくれません。


main.go


main.go

package main

import (
"fmt"
"net/http"

"github.com/gorilla/mux"
)

func rootHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("Hello world!")
}

func main() {

r := mux.NewRouter()
r.HandleFunc("/", rootHandler)

http.Handle("/", r)
http.ListenAndServe(":3000", nil)
}


main.goに関しては特に何も言うことないですね。

3000ポートをlistenして、ルートにアクセスがあったらHello world!するだけです。


.realize.yaml


.realize.yaml

settings:

legacy:
force: true
interval: 0s
server:
status: true
open: false
port: 5002
host: localhost
schema:
- name: app
path: .
commands:
run:
status: true
watcher:
extensions:
- go
paths:
- /
ignored_paths:
- .git
- .realize
- vendor

realizeは自動生成されたものを少し修正して、コンテナの立ち上がりと同時に自動で実行させるようにしています。


実行

ファイル一式そろえたらdocker-compose upします

$ cd docker_go_nginx

$ docker-compose up
Starting dockergonginx_golang_1 ... done
Starting dockergonginx_nginx_1 ... done
Attaching to dockergonginx_golang_1, dockergonginx_nginx_1
golang_1 | [04:08:01][APP] : Watching 1 file/s 0 folder/s
golang_1 | [04:08:01][APP] : Install started
golang_1 | [04:08:01][REALIZE] : Started on localhost:5002
golang_1 | ⇨ http server started on 127.0.0.1:5002
golang_1 | [04:08:02][APP] : Install completed in 1.330 s
golang_1 | [04:08:02][APP] : Running..
golang_1 | [04:08:44][APP] : Hello world!

realizeのおかげで自動でmain.goが走るので、あとは192.168.99.100にブラウザでアクセスして真っ白い画面がでたら成功です。ついでにHello worldが出力されます。

これで、リバースプロキシ+ホットリロードな開発環境ができたので、あとは煮るなり焼くなりするだけです。


まとめ

Docker上でNginx+golangによるリバースプロキシ、ホットリロードな最小限の開発環境を構築しました。

ホットリロードを機能させておくと編集するたびにコンパイルしなおさなくてもいいのでgolangの開発がとてもスムーズになりおススメです。

Web初心者なので間違ってたらコメントください_(:3」∠)_