add
This commit is contained in:
26
deploy/api/api_update_account/.dockerignore
Normal file
26
deploy/api/api_update_account/.dockerignore
Normal file
@@ -0,0 +1,26 @@
|
||||
# 排除Go编译产物
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
app # 排除本地已构建的二进制文件
|
||||
|
||||
# 排除依赖目录
|
||||
vendor/
|
||||
go/pkg/
|
||||
db
|
||||
scripts
|
||||
shared_data
|
||||
|
||||
# 排除版本控制和日志文件
|
||||
.git/
|
||||
.gitignore
|
||||
logs/
|
||||
*.log
|
||||
*.md
|
||||
*.sql
|
||||
|
||||
# 排除IDE配置文件
|
||||
.idea/
|
||||
.vscode/
|
7
deploy/api/api_update_account/README.md
Normal file
7
deploy/api/api_update_account/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
sudo docker rm -f user_update_account_api && sudo docker run -itd --name user_update_account_api -v ./:/app -p 20003:80 golang:1.25.0-alpine3.22
|
||||
|
||||
----
|
||||
|
||||
# 格式:docker build -t 镜像名:标签 .
|
||||
sudo docker rmi -f user-update-account-api:1.0.0
|
||||
sudo docker build -t user-update-account-api:1.0.0 .
|
69
deploy/api/api_update_account/depend.py
Normal file
69
deploy/api/api_update_account/depend.py
Normal file
@@ -0,0 +1,69 @@
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
def run_command(command, check=True, shell=True):
|
||||
"""执行shell命令并返回结果,包含错误处理"""
|
||||
try:
|
||||
print(f"执行命令: {command}")
|
||||
result = subprocess.run(
|
||||
command,
|
||||
shell=shell,
|
||||
check=check,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True
|
||||
)
|
||||
print(f"命令输出: {result.stdout}")
|
||||
return result
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"命令执行失败: {e.stderr}")
|
||||
raise
|
||||
|
||||
def main():
|
||||
container_name = "user_update_account_api"
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__)) # 获取当前脚本所在目录
|
||||
|
||||
try:
|
||||
# 1. 删除已存在的容器
|
||||
print("===== 步骤1: 删除已存在的容器 =====")
|
||||
run_command(f"sudo docker rm -f {container_name}", check=False)
|
||||
|
||||
# 2. 启动新容器
|
||||
print("\n===== 步骤2: 启动新容器 =====")
|
||||
run_command(
|
||||
f"sudo docker run -itd --name {container_name} "
|
||||
f"-v {script_dir}:/app -p 20003:80 golang:1.25.0-alpine3.22"
|
||||
)
|
||||
|
||||
# 3-5. 进入容器、进入app目录并执行go mod tidy(使用sh而非bash)
|
||||
print("\n===== 步骤3-5: 容器内操作 =====")
|
||||
exec_commands = (
|
||||
"cd /app && " # 进入app目录
|
||||
"echo '当前目录内容:' && ls -la && " # 新增目录检查
|
||||
"go version && " # 检查Go版本
|
||||
"go mod init user_update_account && " # 执行依赖整理
|
||||
"go mod tidy && " # 执行依赖整理
|
||||
"exit" # 退出容器
|
||||
)
|
||||
|
||||
# 使用sh代替bash执行命令
|
||||
run_command(
|
||||
f"sudo docker exec -it {container_name} sh -c '{exec_commands}'"
|
||||
)
|
||||
|
||||
# 7. 删除容器
|
||||
print("\n===== 步骤7: 删除容器 =====")
|
||||
run_command(f"sudo docker rm -f {container_name}")
|
||||
|
||||
# 8. 删除虚悬镜像
|
||||
print("\n===== 步骤8: 清理虚悬镜像 =====")
|
||||
run_command("sudo docker images -f 'dangling=true' -q | xargs -r sudo docker rmi")
|
||||
|
||||
print("\n===== 所有操作完成 =====")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n操作失败: {str(e)}")
|
||||
exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@@ -0,0 +1,16 @@
|
||||
services:
|
||||
user_update_account:
|
||||
image: user-update-account-api:1.0.0
|
||||
container_name: api_user_update_account
|
||||
restart: always
|
||||
depends_on:
|
||||
- postgres # 依赖数据库服务
|
||||
networks:
|
||||
- user-network
|
||||
environment:
|
||||
DB_HOST: postgres
|
||||
DB_PORT: ${DB_PORT} # 引用.env变量
|
||||
DB_USER: ${DB_USER} # 引用.env变量
|
||||
DB_PASSWORD: ${DB_PASSWORD} # 引用.env变量
|
||||
DB_NAME: ${DB_NAME}
|
||||
TZ: ${TZ} # 引用.env变量
|
38
deploy/api/api_update_account/dockerfile
Normal file
38
deploy/api/api_update_account/dockerfile
Normal file
@@ -0,0 +1,38 @@
|
||||
# ==================== 第一阶段:构建Go程序(构建阶段)====================
|
||||
# 使用官方Go镜像作为构建基础,选择与项目匹配的Go版本(示例用1.25.0,可根据实际调整)
|
||||
FROM golang:1.25.0-alpine3.22 AS builder
|
||||
|
||||
# 设置工作目录(容器内的目录,规范文件位置)
|
||||
WORKDIR /app
|
||||
|
||||
# 复制go.mod和go.sum(先复制依赖文件,利用Docker缓存机制,避免每次代码变动都重新下载依赖)
|
||||
COPY go.mod go.sum ./
|
||||
|
||||
# 下载项目依赖(仅当go.mod/go.sum变动时才会重新执行)
|
||||
RUN go mod download
|
||||
|
||||
# 复制整个项目代码到工作目录
|
||||
COPY . .
|
||||
|
||||
# 构建Go程序:
|
||||
# - CGO_ENABLED=0:禁用CGO,生成静态链接的二进制文件(避免依赖系统库,保证镜像兼容性)
|
||||
# - -o app:指定输出二进制文件名为app
|
||||
# - ./main.go:指定入口文件
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -o app ./main.go
|
||||
|
||||
|
||||
# ==================== 第二阶段:运行程序(运行阶段)====================
|
||||
# 使用轻量级的alpine镜像(仅5MB左右,大幅减小最终镜像体积)
|
||||
FROM alpine:3.19
|
||||
|
||||
# 设置工作目录
|
||||
WORKDIR /app
|
||||
|
||||
# 从构建阶段复制编译好的二进制文件到当前镜像(仅复制最终产物,减小体积)
|
||||
COPY --from=builder /app/app ./
|
||||
|
||||
# 暴露程序运行端口(与代码中一致)
|
||||
EXPOSE 8080
|
||||
|
||||
# 容器启动时执行的命令:运行二进制文件
|
||||
CMD ["./app"]
|
42
deploy/api/api_update_account/go.mod
Normal file
42
deploy/api/api_update_account/go.mod
Normal file
@@ -0,0 +1,42 @@
|
||||
module user_update_account
|
||||
|
||||
go 1.25.0
|
||||
|
||||
require (
|
||||
github.com/gin-gonic/gin v1.11.0
|
||||
github.com/lib/pq v1.10.9
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/bytedance/sonic v1.14.0 // indirect
|
||||
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/quic-go/quic-go v0.54.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.3.0 // indirect
|
||||
go.uber.org/mock v0.5.0 // indirect
|
||||
golang.org/x/arch v0.20.0 // indirect
|
||||
golang.org/x/crypto v0.40.0 // indirect
|
||||
golang.org/x/mod v0.25.0 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/tools v0.34.0 // indirect
|
||||
google.golang.org/protobuf v1.36.9 // indirect
|
||||
)
|
90
deploy/api/api_update_account/go.sum
Normal file
90
deploy/api/api_update_account/go.sum
Normal file
@@ -0,0 +1,90 @@
|
||||
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
|
||||
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
|
||||
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
||||
github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||
github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
|
||||
github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
|
||||
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg=
|
||||
github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
||||
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||
golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
|
||||
golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
204
deploy/api/api_update_account/main.go
Normal file
204
deploy/api/api_update_account/main.go
Normal file
@@ -0,0 +1,204 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
// UpdateAccountRequest 更新账号请求参数
|
||||
type UpdateAccountRequest struct {
|
||||
UserID string `json:"user_id" binding:"required"`
|
||||
Account string `json:"account" binding:"required"`
|
||||
}
|
||||
|
||||
// UpdateAccountResponse 更新账号响应结构
|
||||
type UpdateAccountResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Data struct {
|
||||
UserID string `json:"user_id,omitempty"`
|
||||
Account string `json:"account,omitempty"`
|
||||
} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
var db *sql.DB
|
||||
|
||||
func main() {
|
||||
// 记录程序启动时间
|
||||
startTime := time.Now()
|
||||
fmt.Printf("[%s] 程序开始启动\n", startTime.Format(time.RFC3339))
|
||||
|
||||
// 初始化Gin引擎
|
||||
r := gin.Default()
|
||||
fmt.Println("[INFO] Gin引擎初始化完成")
|
||||
|
||||
// 从环境变量获取数据库配置
|
||||
fmt.Println("[INFO] 开始读取数据库配置")
|
||||
dbHost := os.Getenv("DB_HOST")
|
||||
dbPort := os.Getenv("DB_PORT")
|
||||
dbUser := os.Getenv("DB_USER")
|
||||
dbPassword := os.Getenv("DB_PASSWORD")
|
||||
dbName := os.Getenv("DB_NAME")
|
||||
|
||||
fmt.Printf("[INFO] 数据库配置: host=%s, port=%s, user=%s, dbname=%s\n",
|
||||
dbHost, dbPort, dbUser, dbName)
|
||||
|
||||
// 构建数据库连接字符串
|
||||
connStr := fmt.Sprintf(
|
||||
"host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
|
||||
dbHost, dbPort, dbUser, dbPassword, dbName,
|
||||
)
|
||||
fmt.Println("[INFO] 数据库连接字符串构建完成")
|
||||
|
||||
var err error
|
||||
db, err = sql.Open("postgres", connStr)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("[ERROR] 无法连接数据库: %v", err))
|
||||
}
|
||||
defer func() {
|
||||
// 关闭数据库连接时记录日志
|
||||
if err := db.Close(); err != nil {
|
||||
fmt.Printf("[ERROR] 关闭数据库连接失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Println("[INFO] 数据库连接已关闭")
|
||||
}
|
||||
}()
|
||||
|
||||
// 验证数据库连接
|
||||
fmt.Println("[INFO] 开始验证数据库连接")
|
||||
if err := db.Ping(); err != nil {
|
||||
panic(fmt.Sprintf("[ERROR] 数据库连接失败: %v", err))
|
||||
}
|
||||
fmt.Println("[INFO] 数据库连接验证成功")
|
||||
|
||||
// 注册更新账号接口
|
||||
r.POST("/user/update/account", updateAccountHandler)
|
||||
fmt.Println("[INFO] 已注册接口: POST /user/update/account")
|
||||
|
||||
// 启动服务,监听80端口
|
||||
startMsg := "服务启动在80端口"
|
||||
fmt.Printf("[%s] %s\n", time.Now().Format(time.RFC3339), startMsg)
|
||||
fmt.Printf("[INFO] 启动耗时: %v\n", time.Since(startTime))
|
||||
|
||||
if err := r.Run(":80"); err != nil {
|
||||
fmt.Printf("[ERROR] 服务启动失败: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
// updateAccountHandler 处理账号更新逻辑
|
||||
func updateAccountHandler(c *gin.Context) {
|
||||
// 记录请求开始时间和请求ID
|
||||
startTime := time.Now()
|
||||
reqID := c.Request.Header.Get("X-Request-ID")
|
||||
if reqID == "" {
|
||||
reqID = fmt.Sprintf("req-%d", time.Now().UnixNano())
|
||||
}
|
||||
fmt.Printf("[%s] [REQUEST] %s - 收到请求: %s %s, RequestID: %s\n",
|
||||
startTime.Format(time.RFC3339),
|
||||
c.ClientIP(),
|
||||
c.Request.Method,
|
||||
c.Request.URL.Path,
|
||||
reqID,
|
||||
)
|
||||
|
||||
var req UpdateAccountRequest
|
||||
// 绑定并验证请求参数
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
errMsg := fmt.Sprintf("请求参数错误: %v", err)
|
||||
fmt.Printf("[%s] [ERROR] %s, RequestID: %s, 错误详情: %v\n",
|
||||
time.Now().Format(time.RFC3339),
|
||||
errMsg,
|
||||
reqID,
|
||||
err,
|
||||
)
|
||||
c.JSON(http.StatusBadRequest, UpdateAccountResponse{
|
||||
Success: false,
|
||||
Message: errMsg,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 打印接收到的请求参数
|
||||
fmt.Printf("[%s] [INFO] 接收到更新请求, RequestID: %s, UserID: %s, 新账号: %s\n",
|
||||
time.Now().Format(time.RFC3339),
|
||||
reqID,
|
||||
req.UserID,
|
||||
req.Account,
|
||||
)
|
||||
|
||||
// 更新账号信息
|
||||
updateQuery := `
|
||||
UPDATE user_account
|
||||
SET account = $1
|
||||
WHERE user_id = $2
|
||||
RETURNING id, user_id, account
|
||||
`
|
||||
fmt.Printf("[%s] [INFO] 执行SQL: %q, 参数: [%s, %s], RequestID: %s\n",
|
||||
time.Now().Format(time.RFC3339),
|
||||
updateQuery,
|
||||
req.Account,
|
||||
req.UserID,
|
||||
reqID,
|
||||
)
|
||||
|
||||
var (
|
||||
id string
|
||||
userID string
|
||||
account string
|
||||
)
|
||||
err := db.QueryRow(updateQuery, req.Account, req.UserID).Scan(&id, &userID, &account)
|
||||
switch {
|
||||
case err == sql.ErrNoRows:
|
||||
errMsg := "未找到该用户的账号信息"
|
||||
fmt.Printf("[%s] [WARN] %s, UserID: %s, RequestID: %s\n",
|
||||
time.Now().Format(time.RFC3339),
|
||||
errMsg,
|
||||
req.UserID,
|
||||
reqID,
|
||||
)
|
||||
c.JSON(http.StatusOK, UpdateAccountResponse{
|
||||
Success: false,
|
||||
Message: errMsg,
|
||||
})
|
||||
return
|
||||
case err != nil:
|
||||
errMsg := fmt.Sprintf("更新账号失败: %v", err)
|
||||
fmt.Printf("[%s] [ERROR] %s, UserID: %s, RequestID: %s, 错误详情: %v\n",
|
||||
time.Now().Format(time.RFC3339),
|
||||
errMsg,
|
||||
req.UserID,
|
||||
reqID,
|
||||
err,
|
||||
)
|
||||
c.JSON(http.StatusInternalServerError, UpdateAccountResponse{
|
||||
Success: false,
|
||||
Message: errMsg,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 更新成功
|
||||
response := UpdateAccountResponse{
|
||||
Success: true,
|
||||
Message: "账号更新成功",
|
||||
}
|
||||
response.Data.UserID = userID
|
||||
response.Data.Account = account
|
||||
|
||||
// 记录成功日志
|
||||
fmt.Printf("[%s] [INFO] 账号更新成功, RequestID: %s, UserID: %s, 新账号: %s, 耗时: %v\n",
|
||||
time.Now().Format(time.RFC3339),
|
||||
reqID,
|
||||
userID,
|
||||
account,
|
||||
time.Since(startTime),
|
||||
)
|
||||
|
||||
c.JSON(http.StatusOK, response)
|
||||
}
|
42
deploy/api/api_update_account/release.sh
Executable file
42
deploy/api/api_update_account/release.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
set -e # 当任何命令失败时立即退出脚本
|
||||
|
||||
# 定义镜像名称和标签
|
||||
IMAGE_NAME="user-update-account-api"
|
||||
IMAGE_TAG="1.0.0"
|
||||
FULL_IMAGE="${IMAGE_NAME}:${IMAGE_TAG}"
|
||||
TAR_FILE="${IMAGE_NAME}-${IMAGE_TAG}.tar"
|
||||
|
||||
echo "开始删除现有镜像 ${FULL_IMAGE}..."
|
||||
if sudo docker rmi -f "${FULL_IMAGE}" >/dev/null 2>&1; then
|
||||
echo "镜像 ${FULL_IMAGE} 删除成功"
|
||||
else
|
||||
echo "镜像 ${FULL_IMAGE} 不存在,跳过删除步骤"
|
||||
fi
|
||||
|
||||
echo "开始构建新镜像 ${FULL_IMAGE}..."
|
||||
if sudo docker build -t "${FULL_IMAGE}" .; then
|
||||
echo "镜像 ${FULL_IMAGE} 构建成功!"
|
||||
else
|
||||
echo "错误:镜像构建失败" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "开始处理镜像压缩包..."
|
||||
# 如果存在同名压缩包则删除
|
||||
if [ -f "${TAR_FILE}" ]; then
|
||||
echo "发现现有压缩包 ${TAR_FILE},正在删除..."
|
||||
rm -f "${TAR_FILE}"
|
||||
fi
|
||||
|
||||
# 打包镜像为tar文件
|
||||
echo "开始将镜像 ${FULL_IMAGE} 打包为 ${TAR_FILE}..."
|
||||
if sudo docker save -o "${TAR_FILE}" "${FULL_IMAGE}"; then
|
||||
echo "镜像打包成功!生成文件:${TAR_FILE}"
|
||||
# 添加最高级别的可读写权限
|
||||
sudo chmod 777 "${TAR_FILE}"
|
||||
echo "已为 ${TAR_FILE} 设置最高权限(777)"
|
||||
else
|
||||
echo "错误:镜像打包失败" >&2
|
||||
exit 1
|
||||
fi
|
Reference in New Issue
Block a user