golangサーバーのホットリロードをgo-task/taskで実現する

本記事は以下を参考にしています。

qiita.com


開発環境

# ホスト
> docker --version
Docker version 20.10.8, build 3967b7d

> docker-compose --version
docker-compose version 1.29.2, build 5becea4c

> task --version
Task version: v3.10.0 (h1:vOAyD9Etsz9ibedBGf1Mu0DpD6V0T1u3VG6Nwh89lDY=)

前提条件

ディレクトリ構成

> tree
.
├── Dockerfile
├── Taskfile.yml
├── docker-compose.yml
└── main.go

コード

FROM golang:1.17-alpine
WORKDIR /go/src

COPY ./ ./
RUN apk add --no-cache gcc musl-dev
version: '3'
tasks:
  build:
    cmds:
      - docker-compose up --build -d
  aaaa:
    cmds:
      - cmd: docker exec -it app kill -TERM `cat dev.pid`
        ignore_error: true
      - docker exec -it app go run main.go
    sources:
      - ./main.go
version: '3.8'
services:
    app:
        build:
            context: .
            dockerfile: Dockerfile
        tty: true
        container_name: app
        volumes:
            - .:/go/src
        ports:
            - 8080:8080
package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
)

func main() {
    f, err := os.Create("dev.pid")
    if err != nil {
        log.Println(err)
    }
    defer f.Close()

    f.Write([]byte(fmt.Sprintf("%d", os.Getpid())))

    http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
        defer r.Body.Close()
        fmt.Fprint(rw, "Hello, world!!")
    })
    http.ListenAndServe(":8080", nil)
}

実行

> task aaaa -w

main.goに修正がある度に aaaa を実行する。

モヤモヤ

f:id:tokizuoh:20220220172841p:plain

docker exec -it app kill -TERM `cat dev.pid`

上記コマンドでエラーが出ているが、ホットリロード自体は問題なくできている。

> docker exec -it app sh

# `A`
/go/src # go run main.go

# 上記とは別のターミナル
> docker exec -it app sh

/go/src # echo $?
0

# `A` がkillされる
/go/src # kill -TERM `cat dev.pid`

/go/src # echo $?
0

コンテナに潜って直接該当コマンド押下してもエラーは見受けられなかった。

参考