Help us understand the problem. What is going on with this article?

Golang(Echo) x docker-composeでホットリロード用いた開発

More than 1 year has passed since last update.

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 を記述

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つ目のレイヤーは本番で使用するために使います。

Dockerfile
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のレイヤーを使用することができます。

docker-compose.yml
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のインストール

Dockerfile
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を使用して起動するようにする

docker-compose.yml
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 を編集してホットリロードされるかの確認です

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.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away