You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker中Golang Gin后端代码变更自动重建方案求助

解决方案:Gin + Docker 代码变更自动重建

一、修复modd无法检测代码变更的问题

1. 修正modd.conf路径匹配

当前modd.conf的**/*.go匹配存在路径歧义,改为明确的相对路径匹配,确保监控容器内挂载目录下所有Go文件:

./**/*.go {
    prep: echo "Detected code change, rebuilding app..."
    prep: go build -o ./run .
    daemon +sigterm: ./run
}

./**/*.go会递归监控当前工作目录(/go/src/app)下所有子目录的.go文件,避免因路径匹配范围不足导致无法检测变更。

2. 放弃手动pkill操作

modd本身会管理后台进程的生命周期:当检测到代码变更时,它会自动向旧的./run进程发送SIGTERM信号,等待进程优雅退出后再启动新进程。手动执行pkill -f run会误杀容器内的PID1进程(即modd本身),直接导致容器退出,完全没必要。

3. 确认Gin优雅关闭的信号处理逻辑

确保你的Gin应用正确捕获并处理SIGTERM信号,否则modd发送的终止信号无法触发优雅关闭,甚至可能导致进程无法正常退出。示例代码如下:

package main

import (
    "context"
    "log"
    "net/http"
    "os"
    "os/signal"
    "syscall"
    "time"

    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    // 配置你的路由...
    r.GET("/", func(c *gin.Context) {
        c.String(http.StatusOK, "Hello World")
    })

    srv := &http.Server{
        Addr:    ":8080",
        Handler: r,
    }

    // 启动HTTP服务
    go func() {
        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            log.Fatalf("Failed to start server: %v", err)
        }
    }()

    // 监听中断信号
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    <-quit
    log.Println("Initiating graceful shutdown...")

    // 设置5秒超时,确保未完成的请求处理完毕
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    if err := srv.Shutdown(ctx); err != nil {
        log.Fatalf("Server forced to shutdown: %v", err)
    }
    log.Println("Server exited gracefully")
}

二、替代方案:使用Air实现Go应用热重载

如果modd仍有问题,推荐使用Air(专门为Go设计的热重载工具),配置更简洁,对信号处理的兼容性更好。

1. 调整Dockerfile

修改builder阶段安装Air,无需提前编译应用:

FROM golang:1.22.5-alpine3.20 AS builder

WORKDIR /go/src/app

ENV GO111MODULE=on

# 安装Air工具
RUN go install github.com/cosmtrek/air@latest

COPY go.mod .
COPY go.sum .

RUN go mod download

COPY . .

FROM alpine:3.20
RUN apk --no-cache add ca-certificates
WORKDIR /root/

# 复制Air二进制到运行镜像
COPY --from=builder /go/bin/air /usr/bin/air

EXPOSE 8080

2. 更新docker-compose配置

挂载代码卷并使用Air启动服务:

services:
  goapp:
    build:
      context: ./src
      target: builder
    image: goapp
    volumes:
      - ./src:/go/src/app
    command: air -c .air.toml
    ports:
      - "8080:8080"

3. 配置Air

在本地src目录下执行air init生成默认配置文件.air.toml,重点确认以下配置项:

[build]
  cmd = "go build -o ./tmp/main ."  # 编译命令
  bin = "./tmp/main"                # 编译后二进制路径
  send_interrupt = true             # 发送中断信号触发优雅关闭
  stop_on_error = true              # 编译错误时停止启动新进程

启动容器后,Air会自动监控代码变更,编译并重启应用,同时正确转发终止信号给Gin应用实现优雅关闭。

内容的提问来源于stack exchange,提问作者iLaurian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 05:42:12