About
Golang(Echo)でDockerfileを開発と本番で同じものを使いつつ、docker-composeを使う。
なおかつホットリロードもする。
前提
- Golang
- 1.12
- docker
- 18.09.2
- docker-compose
- 1.23.2
- realize
- 2.0.2
Docker環境を用意する
とりあえず最低限のEchoサーバーを動かすこと前提
main.go
main.go
を記述
package main
import (
"net/http"
"github.com/labstack/echo"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.Logger.Fatal(e.Start(":1323"))
}
modulesの初期設定
go.mod
を手に入れる
$ docker run -v `pwd`:/go/app -w /go/app golang:1.12-alpine go mod init app
go: creating new go.mod: module app
$ ls
go.mod main.go
ここで go.sum
が欲しい人はよしなに。
Dockerfile
DockerのMulti-Stage Buildを使ってレイヤーを2つ用意します。
1つ目のレイヤーはdocker-composeで使用するため、
2つ目のレイヤーは本番で使用するために使います。
FROM golang:1.12-alpine as build
WORKDIR /go/app
COPY . .
RUN apk add --no-cache git \
&& go build -o app
FROM alpine
WORKDIR /app
COPY --from=build /go/app/app .
RUN addgroup go \
&& adduser -D -G go go \
&& chown -R go:go /app/app
CMD ["./app"]
動作確認をしておきましょう。
$ docker build -t myapp .
$ docker run -p 1323:1323 -d --name myapp myapp
$ curl localhost:1323
Hello, World!
動いたのを確認できたらコンテナを落とします。
$ docker stop down myapp
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
$
docker-compose
docker-composeを動かすために docker-compose.yml
を記述します。
この時に指定する target: build
がポイントです。
Multi-Stage Buildのレイヤーを使用することができます。
version: '3.5'
services:
app:
build:
context: .
target: build
volumes:
- ./:/go/app
command: go run main.go
ports:
- 1323:1323
さて、動作確認です。
$ docker-compose up
Recreating echo_app_1 ... done
Attaching to echo_app_1
app_1 | go: finding github.com/labstack/gommon/color latest
app_1 | go: finding github.com/labstack/gommon/log latest
app_1 | go: finding golang.org/x/crypto/acme/autocert latest
app_1 | go: finding golang.org/x/crypto/acme latest
app_1 | go: finding golang.org/x/crypto latest
app_1 | go: finding github.com/valyala/fasttemplate latest
app_1 |
app_1 | ____ __
app_1 | / __/___/ / ___
app_1 | / _// __/ _ \/ _ \
app_1 | /___/\__/_//_/\___/ v3.3.10-dev
app_1 | High performance, minimalist Go web framework
app_1 | https://echo.labstack.com
app_1 | ____________________________________O/_______
app_1 | O\
app_1 | ? http server started on [::]:1323
別のターミナルを起動してcurlを打ってみましょう
$ curl localhost:1323
Hello, World!
動いてますね。
ホットリロードを導入する
oxequa/realize を使用して実現します
Dockerfileの編集
realizeのインストール
FROM golang:1.12-alpine as build
WORKDIR /go/app
COPY . .
RUN apk add --no-cache git \
- && go build -o app
+ && go build -o app \
+ && go get github.com/oxequa/realize
FROM alpine
WORKDIR /app
COPY --from=build /go/app/app .
RUN addgroup go \
&& adduser -D -G go go \
&& chown -R go:go /app/app
CMD ["./app"]
docker-composeの編集
realizeを使用して起動するようにする
version: '3.5'
services:
app:
build:
context: .
target: build
volumes:
- ./:/go/app
- command: go run main.go
+ command: realize start --run --no-config
ports:
- 1323:1323
動作確認
$ docker-compose up
Recreating echo_app_1 ... done
Attaching to echo_app_1
app_1 | len [0/0]0x0
app_1 | [10:25:29][APP] : Watching 1 file/s 1 folder/s
app_1 | [10:25:29][APP] : Install started
app_1 | [10:25:30][APP] : Install completed in 0.805 s
app_1 | [10:25:30][APP] : Running..
app_1 | [10:25:30][APP] : ____ __
app_1 | [10:25:30][APP] : / __/___/ / ___
app_1 | [10:25:30][APP] : / _// __/ _ \/ _ \
app_1 | [10:25:30][APP] : /___/\__/_//_/\___/ v3.3.10-dev
app_1 | [10:25:30][APP] : High performance, minimalist Go web framework
app_1 | [10:25:30][APP] : https://echo.labstack.com
app_1 | [10:25:30][APP] : ____________________________________O/_______
app_1 | [10:25:30][APP] : O\
app_1 | [10:25:30][APP] : ? http server started on [::]:1323
動いてますね。
curlをして動作確認してみましょう。
$ curl localhost:1323
Hello, World!
最後に main.go
を編集してホットリロードされるかの確認です
package main
import (
"net/http"
"github.com/labstack/echo"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
- return c.String(http.StatusOK, "Hello, World!")
+ return c.String(http.StatusOK, "Good Bye.")
})
e.Logger.Fatal(e.Start(":1323"))
}
$ curl localhost:1323
Good Bye.