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
相关产品推荐
相关产品推荐

