From f51808564cab2266812eb44faf1b980fd95406a7 Mon Sep 17 00:00:00 2001 From: luorijun Date: Sat, 19 Apr 2025 15:59:31 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=20Dockerfile=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=9E=84=E5=BB=BA=E8=BF=87=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 42 ++++++++++-- build.ps1 | 36 ----------- cmd/tasks/main.go | 132 -------------------------------------- docs/docker-deployment.md | 90 ++++++++++++++++++++++++++ go.mod | 8 +-- go.sum | 13 ---- 6 files changed, 130 insertions(+), 191 deletions(-) delete mode 100644 build.ps1 delete mode 100644 cmd/tasks/main.go create mode 100644 docs/docker-deployment.md diff --git a/Dockerfile b/Dockerfile index 86b4978..1a9eefa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,44 @@ -FROM ubuntu:20.04 +# 第一阶段:构建 +FROM golang:1.24.0 AS builder + +WORKDIR /build + +# 复制Go模块文件 +COPY go.mod go.sum ./ +RUN go mod download + +# 复制源代码 +COPY . . + +# 编译 +RUN GOOS=linux GOARCH=amd64 go build -ldflags '-w -s' -o bin/platform_linux_amd64 cmd/main/main.go + +# 第二阶段:运行环境 +FROM ubuntu:24.04 WORKDIR /app -COPY ./bin/platform_linux_amd64 /app/platform +# 安装依赖包 +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# 从构建阶段复制编译好的二进制文件 +COPY --from=builder /build/bin/platform_linux_amd64 /app/platform + +# 设置可执行权限 RUN chmod +x /app/platform -EXPOSE $APP_PORT +# 创建存放密钥文件的目录 +RUN mkdir -p /app/certs -CMD ["/app/proxy"] \ No newline at end of file +# 声明暴露端口(实际端口通过环境变量传入) +ENV APP_PORT=8080 +EXPOSE ${APP_PORT} + +# 声明卷,用于在运行时挂载私密的证书文件 +VOLUME ["/app/certs"] + +# 启动平台服务 +CMD ["/app/platform"] \ No newline at end of file diff --git a/build.ps1 b/build.ps1 deleted file mode 100644 index ebccf69..0000000 --- a/build.ps1 +++ /dev/null @@ -1,36 +0,0 @@ -Remove-Job * - -$tasks = 0 -$start = Get-Date - -$tasks++ -Write-Output "building platform for linux amd64..." -Start-Job -ScriptBlock { - $env:GOOS = "linux"; $env:GOARCH = "amd64"; go build -ldflags '-w -s' -o bin/platform_linux_amd64 cmd/main/main.go -} | Out-Null - -$tasks++ -Write-Output "building tasks for linux amd64..." -Start-Job -ScriptBlock { - $env:GOOS = "linux"; $env:GOARCH = "amd64"; go build -ldflags '-w -s' -o bin/tasks_linux_amd64 cmd/tasks/main.go -} | Out-Null - -# Wait for all jobs to complete -while ($tasks -gt 0) -{ - foreach ($job in Get-Job) - { - if ($job.State -eq "Completed") - { - $tasks-- - $job | Receive-Job - $job | Remove-Job - } - } -} - -$end = Get-Date - -Write-Output "build completed" -Write-Output "time taken: $( ($end - $start).TotalSeconds ) seconds" -Write-Output "output files are in ./bin/" \ No newline at end of file diff --git a/cmd/tasks/main.go b/cmd/tasks/main.go deleted file mode 100644 index 2229ecc..0000000 --- a/cmd/tasks/main.go +++ /dev/null @@ -1,132 +0,0 @@ -package main - -import ( - "context" - "encoding/json" - "errors" - "io" - "log/slog" - "net/http" - "platform/pkg/env" - "platform/pkg/logs" - "platform/pkg/rds" - "strconv" - "strings" - "sync" - "time" - - "github.com/redis/go-redis/v9" -) - -var RemoveEndpoint = "http://localhost:8080/api/channel/remove" - -func main() { - Start() -} - -var taskList = make(map[string]func(ctx context.Context, curr time.Time) error) - -func Start() { - ctx := context.Background() - - env.Init() - logs.Init() - rds.Init() - - taskList["stopChannels"] = stopChannels - - ticker := time.NewTicker(30 * time.Second) - defer ticker.Stop() - - // 互斥锁确保同一时间只有一个协程运行 - // 如果之前的 tick 操作未完成,则跳过当前 tick - var mutex = &sync.Mutex{} - for curr := range ticker.C { - if mutex.TryLock() { - err := process(ctx, curr) - if err != nil { - panic(err) - } - mutex.Unlock() - } else { - slog.Warn("skip tick", slog.String("tick", curr.Format("2006-01-02 15:04:05"))) - } - } -} - -func process(ctx context.Context, curr time.Time) error { - - // todo 异步化 - for name, task := range taskList { - err := task(ctx, curr) - if err != nil { - slog.Error("task failed", slog.String("task", name), slog.String("error", err.Error())) - } - } - - return nil -} - -func stopChannels(ctx context.Context, curr time.Time) error { - - // 查询过期的 channel - result, err := rds.Client.ZRangeByScore(ctx, "tasks:channel", &redis.ZRangeBy{ - Min: "0", - Max: strconv.FormatInt(curr.Unix(), 10), - }).Result() - if err != nil { - return err - } - if len(result) == 0 { - return nil - } - - ids := make([]int32, len(result)) - for i, str := range result { - id, err := strconv.ParseInt(str, 10, 32) - if err != nil { - return err - } - ids[i] = int32(id) - } - slog.Debug("stopChannels", slog.String("result", strings.Join(result, ","))) - - // 删除过期的 channel - body, err := json.Marshal(map[string]any{ - "by_ids": ids, - }) - if err != nil { - return err - } - req, err := http.NewRequest( - http.MethodPost, - RemoveEndpoint, - strings.NewReader(string(body)), - ) - if err != nil { - return err - } - req.Header.Set("Content-Type", "application/json") - req.SetBasicAuth("tasks", "tasks") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return err - } - defer func(Body io.ReadCloser) { - _ = Body.Close() - }(resp.Body) - - if resp.StatusCode != http.StatusOK { - body, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - return errors.New("failed to stop channels: " + string(body)) - } - - // 删除 redis 中的 channel - _, err = rds.Client.ZRemRangeByScore(ctx, "tasks:channel", "0", strconv.FormatInt(curr.Unix(), 10)).Result() - - return nil -} diff --git a/docs/docker-deployment.md b/docs/docker-deployment.md new file mode 100644 index 0000000..d40a747 --- /dev/null +++ b/docs/docker-deployment.md @@ -0,0 +1,90 @@ +# Docker 部署说明 + +本文档说明如何使用 Docker 构建和部署平台服务。 + +## 构建镜像 + +在项目根目录下执行以下命令构建 Docker 镜像: + +```bash +docker build -t platform:latest . +``` + +## 生产环境部署 + +由于涉及敏感的 `.pem` 证书文件,这些文件不包含在代码库或 Docker 镜像中,而是在运行时通过卷挂载的方式提供。 + +### 准备证书文件 + +1. 在生产服务器上创建一个目录用于存放证书文件,例如:`/path/to/certs/` +2. 将必要的证书文件放入此目录: + - `pub_key.pem` + - `apiclient_key.pem` + +### 运行容器 + +使用以下命令运行容器,挂载证书目录: + +```bash +docker run -d \ + --name platform \ + -p 8080:8080 \ + -e APP_PORT=8080 \ + -v /path/to/certs:/app/certs \ + platform:latest +``` + +### 环境变量 + +可以通过环境变量来配置应用程序: + +- `APP_PORT`: 应用监听的端口号(默认: 8080) +- 其他应用相关的环境变量可以通过 `-e` 参数添加 + +### 证书路径配置 + +如果应用程序需要知道证书的路径,可以通过环境变量配置: + +```bash +docker run -d \ + --name platform \ + -p 8080:8080 \ + -e APP_PORT=8080 \ + -e PUB_KEY_PATH=/app/certs/pub_key.pem \ + -e APICLIENT_KEY_PATH=/app/certs/apiclient_key.pem \ + -v /path/to/certs:/app/certs \ + platform:latest +``` + +## 使用 Docker Compose + +也可以通过 Docker Compose 进行部署,创建 `docker-compose.yml` 文件: + +```yaml +version: '3' + +services: + platform: + image: platform:latest + ports: + - "8080:8080" + environment: + - APP_PORT=8080 + - PUB_KEY_PATH=/app/certs/pub_key.pem + - APICLIENT_KEY_PATH=/app/certs/apiclient_key.pem + volumes: + - /path/to/certs:/app/certs + restart: unless-stopped +``` + +然后执行: + +```bash +docker-compose up -d +``` + +## 安全建议 + +1. 确保证书文件的权限设置正确,仅允许必要的用户访问 +2. 在生产环境中考虑使用 Docker Secrets 或 Kubernetes Secrets 来管理敏感信息 +3. 定期更新证书和密钥 \ No newline at end of file diff --git a/go.mod b/go.mod index 3b2e8e5..c07a02f 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module platform go 1.24.0 require ( - github.com/alibabacloud-go/darabonba-openapi v0.2.1 - github.com/alibabacloud-go/dysmsapi-20180501/v2 v2.0.6 + github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.7 + github.com/alibabacloud-go/dysmsapi-20170525/v4 v4.1.3 github.com/alicebob/miniredis/v2 v2.34.0 github.com/glebarez/sqlite v1.11.0 github.com/gofiber/fiber/v2 v2.52.6 @@ -27,15 +27,11 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect - github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.7 // indirect github.com/alibabacloud-go/debug v1.0.1 // indirect - github.com/alibabacloud-go/dysmsapi-20170525/v4 v4.1.3 // indirect github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect github.com/alibabacloud-go/openapi-util v0.1.1 // indirect github.com/alibabacloud-go/tea v1.3.8 // indirect - github.com/alibabacloud-go/tea-utils v1.4.3 // indirect github.com/alibabacloud-go/tea-utils/v2 v2.0.7 // indirect - github.com/alibabacloud-go/tea-xml v1.1.3 // indirect github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 // indirect github.com/aliyun/credentials-go v1.4.5 // indirect github.com/andybalholm/brotli v1.1.1 // indirect diff --git a/go.sum b/go.sum index 6c9dc9b..5d93920 100644 --- a/go.sum +++ b/go.sum @@ -15,15 +15,11 @@ github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8= github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc= github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc= -github.com/alibabacloud-go/darabonba-openapi v0.2.1 h1:WyzxxKvhdVDlwpAMOHgAiCJ+NXa6g5ZWPFEzaK/ewwY= -github.com/alibabacloud-go/darabonba-openapi v0.2.1/go.mod h1:zXOqLbpIqq543oioL9IuuZYOQgHQ5B8/n5OPrnko8aY= -github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.10/go.mod h1:26a14FGhZVELuz2cc2AolvW4RHmIO3/HRwsdHhaIPDE= github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.11/go.mod h1:wHxkgZT1ClZdcwEVP/pDgYK/9HucsnCfMipmJgCz4xY= github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.7 h1:ASXSBga98QrGMxbIThCD6jAti09gedLfvry6yJtsoBE= github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.7/go.mod h1:TBpgqm3XofZz2LCYjZhektGPU7ArEgascyzbm4SjFo4= github.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg= github.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ= -github.com/alibabacloud-go/darabonba-string v1.0.0/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA= github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo= github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA= github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY= @@ -32,11 +28,8 @@ github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc= github.com/alibabacloud-go/dysmsapi-20170525/v4 v4.1.3 h1:32N2pGk28weVZ5/rjNk9gPx/jrRkR0rX9i8Id6IlyUY= github.com/alibabacloud-go/dysmsapi-20170525/v4 v4.1.3/go.mod h1:gPbHx4BTxLIDNRfYNGGmp6aIpeNBamtdDlPcK4UTUto= -github.com/alibabacloud-go/dysmsapi-20180501/v2 v2.0.6 h1:XPck0S+7I8se2e8YnjA/D9OE6FzXwWo2UjlSziJs+z0= -github.com/alibabacloud-go/dysmsapi-20180501/v2 v2.0.6/go.mod h1:Ia7UzBNwNCeNR3TxGQAWi6yNttIFWGiR4HzIlA3Dasc= github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q= github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE= -github.com/alibabacloud-go/openapi-util v0.0.11/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws= github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws= github.com/alibabacloud-go/openapi-util v0.1.1 h1:ujGErJjG8ncRW6XtBBMphzHTvCxn4DjrVw4m04HsS28= github.com/alibabacloud-go/openapi-util v0.1.1/go.mod h1:/UehBSE2cf1gYT43GV4E+RxTdLRzURImCYY0aRmlXpw= @@ -45,20 +38,15 @@ github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeG github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= -github.com/alibabacloud-go/tea v1.1.19/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk= github.com/alibabacloud-go/tea v1.3.8 h1:Sk2+BDJC//xJ1/Eljf+Dlg2u2tgWpA9P7mlb87AEcEs= github.com/alibabacloud-go/tea v1.3.8/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg= github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE= -github.com/alibabacloud-go/tea-utils v1.4.3 h1:8SzwmmRrOnQ09Hf5a9GyfJc0d7Sjv6fmsZoF4UDbFjo= -github.com/alibabacloud-go/tea-utils v1.4.3/go.mod h1:KNcT0oXlZZxOXINnZBs6YvgOd5aYp9U67G+E3R8fcQw= github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4= github.com/alibabacloud-go/tea-utils/v2 v2.0.6/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I= github.com/alibabacloud-go/tea-utils/v2 v2.0.7 h1:WDx5qW3Xa5ZgJ1c8NfqJkF6w+AU5wB8835UdhPr6Ax0= github.com/alibabacloud-go/tea-utils/v2 v2.0.7/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I= -github.com/alibabacloud-go/tea-xml v1.1.2/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= -github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0= github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE= github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= @@ -67,7 +55,6 @@ github.com/alicebob/miniredis/v2 v2.34.0/go.mod h1:kWShP4b58T1CW0Y5dViCd5ztzrDqR github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw= github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0= github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM= -github.com/aliyun/credentials-go v1.3.10/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U= github.com/aliyun/credentials-go v1.4.5 h1:O76WYKgdy1oQYYiJkERjlA2dxGuvLRrzuO2ScrtGWSk= github.com/aliyun/credentials-go v1.4.5/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=