From 5424efd48a9b51e34fd56c84a03cf062791244e7 Mon Sep 17 00:00:00 2001
From: Table
Date: Sat, 29 Nov 2025 08:10:47 +0800
Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Docker=20=E6=A8=A1?=
=?UTF-8?q?=E5=BC=8F=E4=B8=8B=20SERVER=5FPORT=20=E6=9C=AA=E7=94=9F?=
=?UTF-8?q?=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 将 Makefile 中的 PORT 变量重命名为 SERVER_PORT,更清晰地表示应用端口
- 修复 docker-up-dev/stage/prod 命令中的 sed 命令:
* 将 $(PORT) 改为 $(SERVER_PORT)
* 修改 sed 命令从 s/[0-9]\+/... 改为 s|port:.*|port: $(SERVER_PORT)|
* 这样可以处理 config 文件中 port: 为空的情况
- 修复 dev/stage/prod 命令中的 sed 命令,统一使用新的格式
- 在 main.go 中增加端口为空检查:
* 在启动服务器前检查 cfg.Server.Port 是否为空
* 如果为空,输出明确的错误信息并退出,便于排查问题
问题原因:
- docker-up-dev 中使用的是 $(PORT) 而不是 $(SERVER_PORT)
- 当 port: 为空时,sed 的 s/[0-9]\+/... 无法匹配(需要数字才能匹配)
- 改为 s|port:.*|port: ...| 可以处理空值情况
---
Makefile | 70 ++++++++++++++++++++++++++---------------------------
src/main.go | 3 +++
2 files changed, 38 insertions(+), 35 deletions(-)
diff --git a/Makefile b/Makefile
index ffe66f0..22a5f04 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ DOCKER := docker
DOCKER_COMPOSE := $(DOCKER) compose
# 应用端口
-PORT := 1234
+SERVER_PORT := 1234
# 默认目标
.PHONY: help
@@ -30,8 +30,8 @@ help: ## 显示帮助信息
dev: ## 启动开发环境(本地模式,使用 localhost)
@echo "启动开发环境(本地模式)..."
@bash -c '\
- PORT=$(PORT); \
- echo "检查端口 $(PORT) 是否被占用..."; \
+ PORT=$(SERVER_PORT); \
+ echo "检查端口 $(SERVER_PORT) 是否被占用..."; \
PID=""; \
if command -v lsof >/dev/null 2>&1; then \
PID=$$(lsof -ti:$$PORT 2>/dev/null | head -1); \
@@ -98,15 +98,7 @@ dev: ## 启动开发环境(本地模式,使用 localhost)
echo "配置本地模式(使用 localhost)..."; \
cp config/dev.yaml config/dev.yaml.bak 2>/dev/null || true; \
sed -i.tmp "s|host: host.docker.internal|host: localhost|g" config/dev.yaml; \
- trap "mv config/dev.yaml.bak config/dev.yaml 2>/dev/null; rm -f config/dev.yaml.tmp 2>/dev/null" INT TERM EXIT; \
- $(GO) run src/main.go -env=dev; \
- EXIT_CODE=$$?; \
- mv config/dev.yaml.bak config/dev.yaml 2>/dev/null || true; \
- rm -f config/dev.yaml.tmp 2>/dev/null || true; \
- exit $$EXIT_CODE'
- @bash -c '\
- cp config/dev.yaml config/dev.yaml.bak 2>/dev/null || true; \
- sed -i.tmp "s|host: host.docker.internal|host: localhost|g" config/dev.yaml; \
+ sed -i.tmp "/^server:/,/^[a-z][^ ]*:/ { /^ port:/ s|port:.*|port: $(SERVER_PORT)|; }" config/dev.yaml; \
trap "mv config/dev.yaml.bak config/dev.yaml 2>/dev/null; rm -f config/dev.yaml.tmp 2>/dev/null" INT TERM EXIT; \
$(GO) run src/main.go -env=dev; \
EXIT_CODE=$$?; \
@@ -117,26 +109,27 @@ dev: ## 启动开发环境(本地模式,使用 localhost)
.PHONY: stage
stage: ## 启动预发布环境(本地模式,使用 localhost)
@echo "启动预发布环境(本地模式)..."
- @echo "检查端口 $(PORT) 是否被占用..."
+ @echo "检查端口 $(SERVER_PORT) 是否被占用..."
@PID=""; \
if command -v lsof >/dev/null 2>&1; then \
- PID=$$(lsof -ti:$(PORT) 2>/dev/null | head -1); \
+ PID=$$(lsof -ti:$(SERVER_PORT) 2>/dev/null | head -1); \
fi; \
if [ -z "$$PID" ] && command -v netstat >/dev/null 2>&1; then \
- PID=$$(netstat -tlnp 2>/dev/null | grep ":$(PORT) " | awk '{print $$7}' | grep -E '^[0-9]+' | cut -d/ -f1 | head -1); \
+ PID=$$(netstat -tlnp 2>/dev/null | grep ":$(SERVER_PORT) " | awk '{print $$7}' | grep -E '^[0-9]+' | cut -d/ -f1 | head -1); \
fi; \
if [ -z "$$PID" ] && command -v ss >/dev/null 2>&1; then \
- PID=$$(ss -tlnp 2>/dev/null | grep ":$(PORT) " | grep -oP 'pid=\K[0-9]+' | head -1); \
+ PID=$$(ss -tlnp 2>/dev/null | grep ":$(SERVER_PORT) " | grep -oP 'pid=\K[0-9]+' | head -1); \
fi; \
if [ -n "$$PID" ] && [ "$$PID" != "-" ] && [ "$$PID" != "0" ]; then \
- echo "⚠️ 警告: 端口 $(PORT) 已被进程 $$PID 占用"; \
- echo " 提示: 使用 'make kill-$(PORT)' 或 'make kill-port-force PORT=$(PORT)' 终止该进程"; \
+ echo "⚠️ 警告: 端口 $(SERVER_PORT) 已被进程 $$PID 占用"; \
+ echo " 提示: 使用 'make kill-$(SERVER_PORT)' 或 'make kill-port-force PORT=$(SERVER_PORT)' 终止该进程"; \
echo ""; \
fi; \
echo "配置本地模式(使用 localhost)..."
@bash -c '\
cp config/stage.yaml config/stage.yaml.bak 2>/dev/null || true; \
sed -i.tmp "s|host: host.docker.internal|host: localhost|g" config/stage.yaml; \
+ sed -i.tmp "/^server:/,/^[a-z][^ ]*:/ { /^ port:/ s|port:.*|port: $(SERVER_PORT)|; }" config/stage.yaml; \
trap "mv config/stage.yaml.bak config/stage.yaml 2>/dev/null; rm -f config/stage.yaml.tmp 2>/dev/null" INT TERM EXIT; \
$(GO) run src/main.go -env=stage; \
EXIT_CODE=$$?; \
@@ -147,26 +140,27 @@ stage: ## 启动预发布环境(本地模式,使用 localhost)
.PHONY: prod
prod: ## 启动生产环境(本地模式,使用 localhost)
@echo "启动生产环境(本地模式)..."
- @echo "检查端口 $(PORT) 是否被占用..."
+ @echo "检查端口 $(SERVER_PORT) 是否被占用..."
@PID=""; \
if command -v lsof >/dev/null 2>&1; then \
- PID=$$(lsof -ti:$(PORT) 2>/dev/null | head -1); \
+ PID=$$(lsof -ti:$(SERVER_PORT) 2>/dev/null | head -1); \
fi; \
if [ -z "$$PID" ] && command -v netstat >/dev/null 2>&1; then \
- PID=$$(netstat -tlnp 2>/dev/null | grep ":$(PORT) " | awk '{print $$7}' | grep -E '^[0-9]+' | cut -d/ -f1 | head -1); \
+ PID=$$(netstat -tlnp 2>/dev/null | grep ":$(SERVER_PORT) " | awk '{print $$7}' | grep -E '^[0-9]+' | cut -d/ -f1 | head -1); \
fi; \
if [ -z "$$PID" ] && command -v ss >/dev/null 2>&1; then \
- PID=$$(ss -tlnp 2>/dev/null | grep ":$(PORT) " | grep -oP 'pid=\K[0-9]+' | head -1); \
+ PID=$$(ss -tlnp 2>/dev/null | grep ":$(SERVER_PORT) " | grep -oP 'pid=\K[0-9]+' | head -1); \
fi; \
if [ -n "$$PID" ] && [ "$$PID" != "-" ] && [ "$$PID" != "0" ]; then \
- echo "⚠️ 警告: 端口 $(PORT) 已被进程 $$PID 占用"; \
- echo " 提示: 使用 'make kill-$(PORT)' 或 'make kill-port-force PORT=$(PORT)' 终止该进程"; \
+ echo "⚠️ 警告: 端口 $(SERVER_PORT) 已被进程 $$PID 占用"; \
+ echo " 提示: 使用 'make kill-$(SERVER_PORT)' 或 'make kill-port-force PORT=$(SERVER_PORT)' 终止该进程"; \
echo ""; \
fi; \
echo "配置本地模式(使用 localhost)..."
@bash -c '\
cp config/prod.yaml config/prod.yaml.bak 2>/dev/null || true; \
sed -i.tmp "s|host: host.docker.internal|host: localhost|g" config/prod.yaml; \
+ sed -i.tmp "/^server:/,/^[a-z][^ ]*:/ { /^ port:/ s|port:.*|port: $(SERVER_PORT)|; }" config/prod.yaml; \
trap "mv config/prod.yaml.bak config/prod.yaml 2>/dev/null; rm -f config/prod.yaml.tmp 2>/dev/null" INT TERM EXIT; \
$(GO) run src/main.go -env=prod; \
EXIT_CODE=$$?; \
@@ -276,7 +270,7 @@ docker-compose-dev: ## 生成开发环境Docker Compose文件
echo " context: .." >> $(DOCKER_DIR)/docker-compose.dev.yml; \
echo " dockerfile: Dockerfile" >> $(DOCKER_DIR)/docker-compose.dev.yml; \
echo " ports:" >> $(DOCKER_DIR)/docker-compose.dev.yml; \
- echo " - \"$(PORT):$(PORT)\"" >> $(DOCKER_DIR)/docker-compose.dev.yml; \
+ echo " - \"$(SERVER_PORT):$(SERVER_PORT)\"" >> $(DOCKER_DIR)/docker-compose.dev.yml; \
echo " environment:" >> $(DOCKER_DIR)/docker-compose.dev.yml; \
echo " - APP_ENV=dev" >> $(DOCKER_DIR)/docker-compose.dev.yml; \
echo " volumes:" >> $(DOCKER_DIR)/docker-compose.dev.yml; \
@@ -293,6 +287,7 @@ docker-up-dev: docker-compose-dev ## 启动开发环境Docker容器
@echo "配置 Docker 模式(使用 host.docker.internal)..."
@cp config/dev.yaml config/dev.yaml.bak 2>/dev/null || true; \
sed -i.tmp 's|host: localhost|host: host.docker.internal|g' config/dev.yaml; \
+ sed -i.tmp "/^server:/,/^[a-z][^ ]*:/ { /^ port:/ s|port:.*|port: $(SERVER_PORT)|; }" config/dev.yaml; \
HOST_IP=$$(hostname -I | awk '{print $$1}' 2>/dev/null || ip addr show | grep "inet " | grep -v "127.0.0.1" | head -1 | awk '{print $$2}' | cut -d/ -f1); \
if [ -z "$$HOST_IP" ]; then \
mv config/dev.yaml.bak config/dev.yaml 2>/dev/null || true; \
@@ -314,6 +309,7 @@ docker-up-stage: ## 启动预发布环境Docker容器
@echo "配置 Docker 模式(使用 host.docker.internal)..."
@cp config/stage.yaml config/stage.yaml.bak 2>/dev/null || true; \
sed -i.tmp 's|host: localhost|host: host.docker.internal|g' config/stage.yaml; \
+ sed -i.tmp "/^server:/,/^[a-z][^ ]*:/ { /^ port:/ s|port:.*|port: $(SERVER_PORT)|; }" config/stage.yaml; \
HOST_IP=$$(hostname -I | awk '{print $$1}' 2>/dev/null || ip addr show | grep "inet " | grep -v "127.0.0.1" | head -1 | awk '{print $$2}' | cut -d/ -f1); \
if [ -z "$$HOST_IP" ]; then \
mv config/stage.yaml.bak config/stage.yaml 2>/dev/null || true; \
@@ -324,6 +320,7 @@ docker-up-stage: ## 启动预发布环境Docker容器
echo "使用宿主机 IP: $$HOST_IP"; \
cd $(DOCKER_DIR) && \
sed -i.tmp2 "s|host.docker.internal:[0-9.]*|host.docker.internal:$$HOST_IP|g" docker-compose.stage.yml && \
+ sed -i.tmp2 "s|\"1234:1234\"|\"$(SERVER_PORT):$(SERVER_PORT)\"|g" docker-compose.stage.yml && \
$(DOCKER_COMPOSE) -f docker-compose.stage.yml up -d && \
rm -f docker-compose.stage.yml.tmp2; \
mv config/stage.yaml.bak config/stage.yaml 2>/dev/null || true; \
@@ -336,6 +333,7 @@ docker-up-prod: ## 启动生产环境Docker容器
@echo "配置 Docker 模式(使用 host.docker.internal)..."
@cp config/prod.yaml config/prod.yaml.bak 2>/dev/null || true; \
sed -i.tmp 's|host: localhost|host: host.docker.internal|g' config/prod.yaml; \
+ sed -i.tmp "/^server:/,/^[a-z][^ ]*:/ { /^ port:/ s|port:.*|port: $(SERVER_PORT)|; }" config/prod.yaml; \
HOST_IP=$$(hostname -I | awk '{print $$1}' 2>/dev/null || ip addr show | grep "inet " | grep -v "127.0.0.1" | head -1 | awk '{print $$2}' | cut -d/ -f1); \
if [ -z "$$HOST_IP" ]; then \
mv config/prod.yaml.bak config/prod.yaml 2>/dev/null || true; \
@@ -346,6 +344,8 @@ docker-up-prod: ## 启动生产环境Docker容器
echo "使用宿主机 IP: $$HOST_IP"; \
cd $(DOCKER_DIR) && \
sed -i.tmp2 "s|host.docker.internal:[0-9.]*|host.docker.internal:$$HOST_IP|g" docker-compose.prod.yml && \
+ sed -i.tmp2 "s|\"1234:1234\"|\"$(SERVER_PORT):$(SERVER_PORT)\"|g" docker-compose.prod.yml && \
+ sed -i.tmp2 "s|http://localhost:[0-9]*/health|http://localhost:$(SERVER_PORT)/health|g" docker-compose.prod.yml && \
$(DOCKER_COMPOSE) -f docker-compose.prod.yml up -d && \
rm -f docker-compose.prod.yml.tmp2; \
mv config/prod.yaml.bak config/prod.yaml 2>/dev/null || true; \
@@ -440,10 +440,10 @@ docker-ps: ## 查看所有Docker容器状态
# 端口管理
.PHONY: kill-port
-kill-port: ## 终止指定端口的进程 (用法: make kill-port PORT=$(PORT))
+kill-port: ## 终止指定端口的进程 (用法: make kill-port PORT=$(SERVER_PORT))
@if [ -z "$(PORT)" ]; then \
echo "❌ 错误: 请指定端口号"; \
- echo "用法: make kill-port PORT=$(PORT)"; \
+ echo "用法: make kill-port PORT=$(SERVER_PORT)"; \
exit 1; \
fi; \
echo "查找端口 $(PORT) 的进程..."; \
@@ -472,7 +472,7 @@ kill-port: ## 终止指定端口的进程 (用法: make kill-port PORT=$(PORT))
fi
.PHONY: kill-port-force
-kill-port-force: ## 强制终止指定端口的进程,无需确认 (用法: make kill-port-force PORT=$(PORT))
+kill-port-force: ## 强制终止指定端口的进程,无需确认 (用法: make kill-port-force PORT=$(SERVER_PORT))
@if [ -z "$(PORT)" ]; then \
echo "❌ 错误: 请指定端口号"; \
echo "用法: make kill-port-force PORT=$(PORT)"; \
@@ -498,21 +498,21 @@ kill-port-force: ## 强制终止指定端口的进程,无需确认 (用法: ma
echo "进程信息: $$PROCESS_INFO"; \
kill -9 $$PID 2>/dev/null && echo "✅ 已强制终止进程 $$PID" || echo "❌ 终止进程失败"
-.PHONY: kill-$(PORT)
-kill-$(PORT): ## 终止端口 $(PORT) 的进程(应用默认端口)
- @echo "终止端口 $(PORT) 的进程..."
+.PHONY: kill-$(SERVER_PORT)
+kill-$(SERVER_PORT): ## 终止端口 $(SERVER_PORT) 的进程(应用默认端口)
+ @echo "终止端口 $(SERVER_PORT) 的进程..."
@PID=""; \
if command -v lsof >/dev/null 2>&1; then \
- PID=$$(lsof -ti:$(PORT) 2>/dev/null | head -1); \
+ PID=$$(lsof -ti:$(SERVER_PORT) 2>/dev/null | head -1); \
fi; \
if [ -z "$$PID" ] && command -v netstat >/dev/null 2>&1; then \
- PID=$$(netstat -tlnp 2>/dev/null | grep ":$(PORT) " | awk '{print $$7}' | grep -E '^[0-9]+' | cut -d/ -f1 | head -1); \
+ PID=$$(netstat -tlnp 2>/dev/null | grep ":$(SERVER_PORT) " | awk '{print $$7}' | grep -E '^[0-9]+' | cut -d/ -f1 | head -1); \
fi; \
if [ -z "$$PID" ] && command -v ss >/dev/null 2>&1; then \
- PID=$$(ss -tlnp 2>/dev/null | grep ":$(PORT) " | grep -oP 'pid=\K[0-9]+' | head -1); \
+ PID=$$(ss -tlnp 2>/dev/null | grep ":$(SERVER_PORT) " | grep -oP 'pid=\K[0-9]+' | head -1); \
fi; \
if [ -z "$$PID" ] || [ "$$PID" = "-" ] || [ "$$PID" = "0" ]; then \
- echo "✅ 端口 $(PORT) 未被占用"; \
+ echo "✅ 端口 $(SERVER_PORT) 未被占用"; \
exit 0; \
fi; \
echo "找到进程 PID: $$PID"; \
diff --git a/src/main.go b/src/main.go
index 0a75b82..5ec37aa 100644
--- a/src/main.go
+++ b/src/main.go
@@ -79,6 +79,9 @@ func main() {
}
// 启动服务器
+ if cfg.Server.Port == "" {
+ log.Fatalf("❌ 错误: 服务器端口配置为空!请检查配置文件中的 server.port 设置")
+ }
log.Printf("服务器启动在端口 %s,环境: %s", cfg.Server.Port, env)
// 优雅关闭