From 551890abd5fb89a540940c22974b128ad7a4a249 Mon Sep 17 00:00:00 2001 From: zzw <1464003642@qq.com> Date: Tue, 11 Aug 2026 17:28:33 +0800 Subject: [PATCH 1/4] feat: cached --- deploy/docker-compose.yml | 30 -- pkg/discovery/nacos.go | 726 +++++++++++++++++++------------------- 2 files changed, 363 insertions(+), 393 deletions(-) delete mode 100644 deploy/docker-compose.yml diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml deleted file mode 100644 index 84292ed..0000000 --- a/deploy/docker-compose.yml +++ /dev/null @@ -1,30 +0,0 @@ -services: - rnacos: - image: qingpan/rnacos:stable - restart: unless-stopped - ports: - - "8848:8848" - volumes: - - ./rnacos/data:/app/data - environment: - RNACOS_SERVER_PORT: 8848 - RNACOS_ENABLE_NO_AUTH_CONSOLE: "true" - - apisix: - image: apache/apisix:3.17.0-debian - restart: unless-stopped - volumes: - - ./apisix/config.yaml:/usr/local/apisix/conf/config.yaml:ro - - ./apisix/apisix.yaml:/usr/local/apisix/conf/apisix.yaml:ro - # 单文件挂载到 /usr/local/apisix/auth.lua - - ./apisix/lua/auth.lua:/usr/local/apisix/auth.lua:ro - ports: - - "9080:9080" - - "9443:9443" - networks: - - default - -networks: - default: - external: true - name: services-network diff --git a/pkg/discovery/nacos.go b/pkg/discovery/nacos.go index 100ba20..97cbb37 100644 --- a/pkg/discovery/nacos.go +++ b/pkg/discovery/nacos.go @@ -1,363 +1,363 @@ -package discovery - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "net/url" - "strconv" - "strings" - "sync" - "time" -) - -type Config struct { - Hosts []string - NamespaceId string - Group string -} - -type Instance struct { - ServiceName string - IP string - Port uint64 - Group string -} - -type ServiceInstance struct { - IP string - Port uint64 - ServiceName string - Healthy bool - Weight float64 - Enabled bool - Ephemeral bool - ClusterName string - Metadata map[string]string -} - -var ( - mu sync.Mutex - baseURL string - namespace string - group string - httpClient = &http.Client{Timeout: 5 * time.Second} - current Instance - inited bool - registered bool - stopBeat chan struct{} - - pickMu sync.Mutex - pickRR = map[string]uint64{} -) - -func Init(cfg Config) error { - mu.Lock() - defer mu.Unlock() - - if inited { - return nil - } - if len(cfg.Hosts) == 0 { - return fmt.Errorf("discovery: Hosts is empty") - } - - host, port, err := parseHostPort(cfg.Hosts[0]) - if err != nil { - return err - } - - group = cfg.Group - if group == "" { - group = "default" - } - namespace = cfg.NamespaceId - baseURL = fmt.Sprintf("http://%s:%d", host, port) - inited = true - return nil -} - -func Register(inst Instance) error { - mu.Lock() - defer mu.Unlock() - - if !inited { - return fmt.Errorf("discovery: call Init first") - } - - g := inst.Group - if g == "" { - g = group - } - - form := url.Values{} - form.Set("ip", inst.IP) - form.Set("port", strconv.FormatUint(inst.Port, 10)) - form.Set("serviceName", joinGroupService(g, inst.ServiceName)) - form.Set("groupName", g) - form.Set("weight", "10") - form.Set("enable", "true") - form.Set("healthy", "true") - form.Set("ephemeral", "true") - form.Set("clusterName", "DEFAULT") - if namespace != "" { - form.Set("namespaceId", namespace) - } - - if err := doForm(http.MethodPost, "/nacos/v1/ns/instance", form); err != nil { - return fmt.Errorf("discovery: register: %w", err) - } - - current = inst - current.Group = g - registered = true - - if stopBeat != nil { - close(stopBeat) - } - stopBeat = make(chan struct{}) - go heartbeatLoop(stopBeat, current) - - return nil -} - -func Deregister() error { - mu.Lock() - defer mu.Unlock() - - if !inited || !registered { - return nil - } - - if stopBeat != nil { - close(stopBeat) - stopBeat = nil - } - - form := url.Values{} - form.Set("ip", current.IP) - form.Set("port", strconv.FormatUint(current.Port, 10)) - form.Set("serviceName", joinGroupService(current.Group, current.ServiceName)) - form.Set("groupName", current.Group) - form.Set("clusterName", "DEFAULT") - form.Set("ephemeral", "true") - if namespace != "" { - form.Set("namespaceId", namespace) - } - - if err := doForm(http.MethodDelete, "/nacos/v1/ns/instance", form); err != nil { - return fmt.Errorf("discovery: deregister: %w", err) - } - - registered = false - return nil -} - -func GetInstances(serviceName string, groupName ...string) ([]ServiceInstance, error) { - mu.Lock() - defer mu.Unlock() - - if !inited { - return nil, fmt.Errorf("discovery: call Init first") - } - - g := group - if len(groupName) > 0 && groupName[0] != "" { - g = groupName[0] - } - - q := url.Values{} - q.Set("serviceName", joinGroupService(g, serviceName)) - q.Set("groupName", g) - q.Set("healthyOnly", "true") - if namespace != "" { - q.Set("namespaceId", namespace) - } - - body, err := doGet("/nacos/v1/ns/instance/list", q) - if err != nil { - return nil, fmt.Errorf("discovery: select instances: %w", err) - } - - var resp listResponse - if err := json.Unmarshal(body, &resp); err != nil { - return nil, fmt.Errorf("discovery: decode instances: %w", err) - } - - out := make([]ServiceInstance, 0, len(resp.Hosts)) - for _, h := range resp.Hosts { - out = append(out, ServiceInstance{ - IP: h.IP, - Port: uint64(h.Port), - ServiceName: h.ServiceName, - Healthy: h.Healthy, - Weight: h.Weight, - Enabled: h.Enabled, - Ephemeral: h.Ephemeral, - ClusterName: h.ClusterName, - Metadata: h.Metadata, - }) - } - return out, nil -} - -// Pick returns one healthy instance for serviceName using round-robin. -func Pick(serviceName string, groupName ...string) (*ServiceInstance, error) { - list, err := GetInstances(serviceName, groupName...) - if err != nil { - return nil, err - } - if len(list) == 0 { - return nil, fmt.Errorf("discovery: no healthy instance for %q", serviceName) - } - - pickMu.Lock() - idx := pickRR[serviceName] % uint64(len(list)) - pickRR[serviceName]++ - pickMu.Unlock() - - inst := list[idx] - return &inst, nil -} - -type listResponse struct { - Hosts []hostInfo `json:"hosts"` -} - -type hostInfo struct { - IP string `json:"ip"` - Port float64 `json:"port"` - ServiceName string `json:"serviceName"` - Healthy bool `json:"healthy"` - Weight float64 `json:"weight"` - Enabled bool `json:"enabled"` - Ephemeral bool `json:"ephemeral"` - ClusterName string `json:"clusterName"` - Metadata map[string]string `json:"metadata"` -} - -type beatResponse struct { - ClientBeatInterval int64 `json:"clientBeatInterval"` -} - -func heartbeatLoop(stop <-chan struct{}, inst Instance) { - interval := 5 * time.Second - ticker := time.NewTicker(interval) - defer ticker.Stop() - - for { - select { - case <-stop: - return - case <-ticker.C: - if d := sendBeat(inst); d > 0 { - ticker.Reset(d) - } - } - } -} - -func sendBeat(inst Instance) time.Duration { - groupedName := joinGroupService(inst.Group, inst.ServiceName) - beat, _ := json.Marshal(map[string]any{ - "ip": inst.IP, - "port": inst.Port, - "serviceName": groupedName, - "weight": 10, - "ephemeral": true, - "cluster": "DEFAULT", - }) - - q := url.Values{} - q.Set("serviceName", groupedName) - q.Set("groupName", inst.Group) - q.Set("ip", inst.IP) - q.Set("port", strconv.FormatUint(inst.Port, 10)) - q.Set("beat", string(beat)) - if namespace != "" { - q.Set("namespaceId", namespace) - } - req, err := http.NewRequest(http.MethodPut, baseURL+"/nacos/v1/ns/instance/beat?"+q.Encode(), nil) - if err != nil { - return 0 - } - resp, err := httpClient.Do(req) - if err != nil { - return 0 - } - defer resp.Body.Close() - body, _ := io.ReadAll(resp.Body) - if resp.StatusCode >= 300 { - return 0 - } - - var br beatResponse - if json.Unmarshal(body, &br) == nil && br.ClientBeatInterval > 0 { - return time.Duration(br.ClientBeatInterval) * time.Millisecond - } - return 0 -} - -func doForm(method, path string, form url.Values) error { - req, err := http.NewRequest(method, baseURL+path, strings.NewReader(form.Encode())) - if err != nil { - return err - } - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - resp, err := httpClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - body, _ := io.ReadAll(resp.Body) - if resp.StatusCode >= 300 { - return fmt.Errorf("http %d: %s", resp.StatusCode, strings.TrimSpace(string(body))) - } - if s := strings.TrimSpace(string(body)); s != "" && s != "ok" && s != "true" { - // rnacos / nacos 成功时通常返回 "ok" - var ok bool - if err := json.Unmarshal(body, &ok); err == nil && ok { - return nil - } - if s != "ok" { - return fmt.Errorf("unexpected response: %s", s) - } - } - return nil -} - -func doGet(path string, q url.Values) ([]byte, error) { - resp, err := httpClient.Get(baseURL + path + "?" + q.Encode()) - if err != nil { - return nil, err - } - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - if resp.StatusCode >= 300 { - return nil, fmt.Errorf("http %d: %s", resp.StatusCode, strings.TrimSpace(string(body))) - } - return body, nil -} - -func parseHostPort(addr string) (string, uint64, error) { - host, portStr, ok := strings.Cut(addr, ":") - if !ok || host == "" || portStr == "" { - return "", 0, fmt.Errorf("discovery: invalid host %q, want host:port", addr) - } - port, err := strconv.ParseUint(portStr, 10, 64) - if err != nil { - return "", 0, fmt.Errorf("discovery: invalid port in %q: %w", addr, err) - } - return host, port, nil -} - -func joinGroupService(groupName, serviceName string) string { - if groupName == "" || strings.Contains(serviceName, "@@") { - return serviceName - } - return groupName + "@@" + serviceName -} +package discovery + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "strconv" + "strings" + "sync" + "time" +) + +type Config struct { + Hosts []string + NamespaceId string + Group string +} + +type Instance struct { + ServiceName string + IP string + Port uint64 + Group string +} + +type ServiceInstance struct { + IP string + Port uint64 + ServiceName string + Healthy bool + Weight float64 + Enabled bool + Ephemeral bool + ClusterName string + Metadata map[string]string +} + +var ( + mu sync.Mutex + baseURL string + namespace string + group string + httpClient = &http.Client{Timeout: 5 * time.Second} + current Instance + inited bool + registered bool + stopBeat chan struct{} + + pickMu sync.Mutex + pickRR = map[string]uint64{} +) + +func Init(cfg Config) error { + mu.Lock() + defer mu.Unlock() + + if inited { + return nil + } + if len(cfg.Hosts) == 0 { + return fmt.Errorf("discovery: Hosts is empty") + } + + host, port, err := parseHostPort(cfg.Hosts[0]) + if err != nil { + return err + } + + group = cfg.Group + if group == "" { + group = "default" + } + namespace = cfg.NamespaceId + baseURL = fmt.Sprintf("http://%s:%d", host, port) + inited = true + return nil +} + +func Register(inst Instance) error { + mu.Lock() + defer mu.Unlock() + + if !inited { + return fmt.Errorf("discovery: call Init first") + } + + g := inst.Group + if g == "" { + g = group + } + + form := url.Values{} + form.Set("ip", inst.IP) + form.Set("port", strconv.FormatUint(inst.Port, 10)) + form.Set("serviceName", joinGroupService(g, inst.ServiceName)) + form.Set("groupName", g) + form.Set("weight", "10") + form.Set("enable", "true") + form.Set("healthy", "true") + form.Set("ephemeral", "true") + form.Set("clusterName", "DEFAULT") + if namespace != "" { + form.Set("namespaceId", namespace) + } + + if err := doForm(http.MethodPost, "/nacos/v1/ns/instance", form); err != nil { + return fmt.Errorf("discovery: register: %w", err) + } + + current = inst + current.Group = g + registered = true + + if stopBeat != nil { + close(stopBeat) + } + stopBeat = make(chan struct{}) + go heartbeatLoop(stopBeat, current) + + return nil +} + +func Deregister() error { + mu.Lock() + defer mu.Unlock() + + if !inited || !registered { + return nil + } + + if stopBeat != nil { + close(stopBeat) + stopBeat = nil + } + + form := url.Values{} + form.Set("ip", current.IP) + form.Set("port", strconv.FormatUint(current.Port, 10)) + form.Set("serviceName", joinGroupService(current.Group, current.ServiceName)) + form.Set("groupName", current.Group) + form.Set("clusterName", "DEFAULT") + form.Set("ephemeral", "true") + if namespace != "" { + form.Set("namespaceId", namespace) + } + + if err := doForm(http.MethodDelete, "/nacos/v1/ns/instance", form); err != nil { + return fmt.Errorf("discovery: deregister: %w", err) + } + + registered = false + return nil +} + +func GetInstances(serviceName string, groupName ...string) ([]ServiceInstance, error) { + mu.Lock() + defer mu.Unlock() + + if !inited { + return nil, fmt.Errorf("discovery: call Init first") + } + + g := group + if len(groupName) > 0 && groupName[0] != "" { + g = groupName[0] + } + + q := url.Values{} + q.Set("serviceName", joinGroupService(g, serviceName)) + q.Set("groupName", g) + q.Set("healthyOnly", "true") + if namespace != "" { + q.Set("namespaceId", namespace) + } + + body, err := doGet("/nacos/v1/ns/instance/list", q) + if err != nil { + return nil, fmt.Errorf("discovery: select instances: %w", err) + } + + var resp listResponse + if err := json.Unmarshal(body, &resp); err != nil { + return nil, fmt.Errorf("discovery: decode instances: %w", err) + } + + out := make([]ServiceInstance, 0, len(resp.Hosts)) + for _, h := range resp.Hosts { + out = append(out, ServiceInstance{ + IP: h.IP, + Port: uint64(h.Port), + ServiceName: h.ServiceName, + Healthy: h.Healthy, + Weight: h.Weight, + Enabled: h.Enabled, + Ephemeral: h.Ephemeral, + ClusterName: h.ClusterName, + Metadata: h.Metadata, + }) + } + return out, nil +} + +// Pick returns one healthy instance for serviceName using round-robin. +func Pick(serviceName string, groupName ...string) (*ServiceInstance, error) { + list, err := GetInstances(serviceName, groupName...) + if err != nil { + return nil, err + } + if len(list) == 0 { + return nil, fmt.Errorf("discovery: no healthy instance for %q", serviceName) + } + + pickMu.Lock() + idx := pickRR[serviceName] % uint64(len(list)) + pickRR[serviceName]++ + pickMu.Unlock() + + inst := list[idx] + return &inst, nil +} + +type listResponse struct { + Hosts []hostInfo `json:"hosts"` +} + +type hostInfo struct { + IP string `json:"ip"` + Port float64 `json:"port"` + ServiceName string `json:"serviceName"` + Healthy bool `json:"healthy"` + Weight float64 `json:"weight"` + Enabled bool `json:"enabled"` + Ephemeral bool `json:"ephemeral"` + ClusterName string `json:"clusterName"` + Metadata map[string]string `json:"metadata"` +} + +type beatResponse struct { + ClientBeatInterval int64 `json:"clientBeatInterval"` +} + +func heartbeatLoop(stop <-chan struct{}, inst Instance) { + interval := 5 * time.Second + ticker := time.NewTicker(interval) + defer ticker.Stop() + + for { + select { + case <-stop: + return + case <-ticker.C: + if d := sendBeat(inst); d > 0 { + ticker.Reset(d) + } + } + } +} + +func sendBeat(inst Instance) time.Duration { + groupedName := joinGroupService(inst.Group, inst.ServiceName) + beat, _ := json.Marshal(map[string]any{ + "ip": inst.IP, + "port": inst.Port, + "serviceName": groupedName, + "weight": 10, + "ephemeral": true, + "cluster": "DEFAULT", + }) + + q := url.Values{} + q.Set("serviceName", groupedName) + q.Set("groupName", inst.Group) + q.Set("ip", inst.IP) + q.Set("port", strconv.FormatUint(inst.Port, 10)) + q.Set("beat", string(beat)) + if namespace != "" { + q.Set("namespaceId", namespace) + } + req, err := http.NewRequest(http.MethodPut, baseURL+"/nacos/v1/ns/instance/beat?"+q.Encode(), nil) + if err != nil { + return 0 + } + resp, err := httpClient.Do(req) + if err != nil { + return 0 + } + defer resp.Body.Close() + body, _ := io.ReadAll(resp.Body) + if resp.StatusCode >= 300 { + return 0 + } + + var br beatResponse + if json.Unmarshal(body, &br) == nil && br.ClientBeatInterval > 0 { + return time.Duration(br.ClientBeatInterval) * time.Millisecond + } + return 0 +} + +func doForm(method, path string, form url.Values) error { + req, err := http.NewRequest(method, baseURL+path, strings.NewReader(form.Encode())) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + resp, err := httpClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + body, _ := io.ReadAll(resp.Body) + if resp.StatusCode >= 300 { + return fmt.Errorf("http %d: %s", resp.StatusCode, strings.TrimSpace(string(body))) + } + if s := strings.TrimSpace(string(body)); s != "" && s != "ok" && s != "true" { + // rnacos / nacos 成功时通常返回 "ok" + var ok bool + if err := json.Unmarshal(body, &ok); err == nil && ok { + return nil + } + if s != "ok" { + return fmt.Errorf("unexpected response: %s", s) + } + } + return nil +} + +func doGet(path string, q url.Values) ([]byte, error) { + resp, err := httpClient.Get(baseURL + path + "?" + q.Encode()) + if err != nil { + return nil, err + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + if resp.StatusCode >= 300 { + return nil, fmt.Errorf("http %d: %s", resp.StatusCode, strings.TrimSpace(string(body))) + } + return body, nil +} + +func parseHostPort(addr string) (string, uint64, error) { + host, portStr, ok := strings.Cut(addr, ":") + if !ok || host == "" || portStr == "" { + return "", 0, fmt.Errorf("discovery: invalid host %q, want host:port", addr) + } + port, err := strconv.ParseUint(portStr, 10, 64) + if err != nil { + return "", 0, fmt.Errorf("discovery: invalid port in %q: %w", addr, err) + } + return host, port, nil +} + +func joinGroupService(groupName, serviceName string) string { + if groupName == "" || strings.Contains(serviceName, "@@") { + return serviceName + } + return groupName + "@@" + serviceName +} From 84433273c64bb23f69747fc72070f14dbee6975f Mon Sep 17 00:00:00 2001 From: zzw <1464003642@qq.com> Date: Tue, 11 Aug 2026 18:17:45 +0800 Subject: [PATCH 2/4] feat: .git buildkit --- .gitea/workflows/ci.yml | 6 ++-- admin/Dockerfile | 9 ++++-- bff/.gitignore | 1 + bff/Dockerfile | 9 ++++-- bff/etc/bff.yaml | 29 ------------------- product/.gitignore | 1 + product/Dockerfile | 9 ++++-- product/etc/product.yaml | 60 ---------------------------------------- 8 files changed, 26 insertions(+), 98 deletions(-) create mode 100644 bff/.gitignore delete mode 100644 bff/etc/bff.yaml create mode 100644 product/.gitignore delete mode 100644 product/etc/product.yaml diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index c957c9b..fc7f5ae 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -73,7 +73,7 @@ jobs: - name: Docker build run: | - docker build \ + DOCKER_BUILDKIT=1 docker build \ -f bff/Dockerfile \ -t ${{ vars.REGISTRY }}/$NAME:latest \ . @@ -98,7 +98,7 @@ jobs: - name: Docker build run: | - docker build \ + DOCKER_BUILDKIT=1 docker build \ -f product/Dockerfile \ -t ${{ vars.REGISTRY }}/$NAME:latest \ . @@ -123,7 +123,7 @@ jobs: - name: Docker build run: | - docker build \ + DOCKER_BUILDKIT=1 docker build \ -f admin/Dockerfile \ -t ${{ vars.REGISTRY }}/$NAME:latest \ . diff --git a/admin/Dockerfile b/admin/Dockerfile index 1c5da96..c5bb0b9 100644 --- a/admin/Dockerfile +++ b/admin/Dockerfile @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + FROM golang:1.26.5-alpine AS builder WORKDIR /src @@ -11,10 +13,13 @@ COPY pkg ./pkg COPY admin/go.mod admin/go.sum ./admin/ WORKDIR /src/admin -RUN go mod download +RUN --mount=type=cache,target=/go/pkg/mod \ + go mod download COPY admin/ ./ -RUN go build -ldflags="-s -w" -o /out/admin . +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + go build -ldflags="-s -w" -o /out/admin . FROM alpine:3.22 diff --git a/bff/.gitignore b/bff/.gitignore new file mode 100644 index 0000000..3355522 --- /dev/null +++ b/bff/.gitignore @@ -0,0 +1 @@ +etc/bff.yaml \ No newline at end of file diff --git a/bff/Dockerfile b/bff/Dockerfile index f0888f4..355234e 100644 --- a/bff/Dockerfile +++ b/bff/Dockerfile @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + FROM golang:1.26.5-alpine AS builder WORKDIR /src @@ -11,10 +13,13 @@ COPY pkg ./pkg COPY bff/go.mod bff/go.sum ./bff/ WORKDIR /src/bff -RUN go mod download +RUN --mount=type=cache,target=/go/pkg/mod \ + go mod download COPY bff/ ./ -RUN go build -ldflags="-s -w" -o /out/bff . +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + go build -ldflags="-s -w" -o /out/bff . FROM alpine:3.22 diff --git a/bff/etc/bff.yaml b/bff/etc/bff.yaml deleted file mode 100644 index fc64d57..0000000 --- a/bff/etc/bff.yaml +++ /dev/null @@ -1,29 +0,0 @@ -Name: bff-service -Host: 0.0.0.0 -Port: 10000 - -Nacos: - Hosts: - - rnacos:8848 - NamespaceId: test - Group: LONE_SERVICES - RegisterIP: bff - -Response: - IsDebug: true # true 不加密 - EncryptKey: "M17fcaPeHDr05H17fcaPH1deDH17l3Bd" - -Upstreams: - - Name: product - Grpc: - Target: product-service - Timeout: 5000 - ProtoSets: - - etc/product.pb - - - Name: admin - Grpc: - Target: admin-service - Timeout: 5000 - ProtoSets: - - etc/admin.pb \ No newline at end of file diff --git a/product/.gitignore b/product/.gitignore new file mode 100644 index 0000000..1c8f68c --- /dev/null +++ b/product/.gitignore @@ -0,0 +1 @@ +etc/product.yaml \ No newline at end of file diff --git a/product/Dockerfile b/product/Dockerfile index 59f0124..cdc9138 100644 --- a/product/Dockerfile +++ b/product/Dockerfile @@ -1,3 +1,5 @@ +# syntax=docker/dockerfile:1 + FROM golang:1.26.5-alpine AS builder WORKDIR /src @@ -11,10 +13,13 @@ COPY pkg ./pkg COPY product/go.mod product/go.sum ./product/ WORKDIR /src/product -RUN go mod download +RUN --mount=type=cache,target=/go/pkg/mod \ + go mod download COPY product/ ./ -RUN go build -ldflags="-s -w" -o /out/product . +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + go build -ldflags="-s -w" -o /out/product . FROM alpine:3.22 diff --git a/product/etc/product.yaml b/product/etc/product.yaml deleted file mode 100644 index 0b2fe32..0000000 --- a/product/etc/product.yaml +++ /dev/null @@ -1,60 +0,0 @@ -Name: product-service -ListenOn: 0.0.0.0:10100 -Mode: dev - -Log: - ServiceName: product-service - Mode: file # console | file | volume - Encoding: plain - Level: info - Path: logs - KeepDays: 7 - Compress: false - # Rotation: daily - # MaxSize: 100 - # MaxBackups: 10 - -Nacos: - Hosts: - - rnacos:8848 - NamespaceId: test - Group: LONE_SERVICES - RegisterIP: product - -Mysql: - Host: mysql - Port: 3306 - User: root - Password: "123123" - Database: dms-product - Charset: utf8mb4 - Prefix: - - # Host: "39.106.171.204" - # Port: 33066 - # User: root - # Password: "MOLXRZNOU4Y4" - # Database: dms-product - # Charset: utf8mb4 - # Prefix: - - # ReadHost: mysql-slave - # ReadPort: 3306 - # ReadUser: root - # ReadPassword: "123123" - # ReadDatabase: dms-product - -BizRedis: - Host: redis - Port: 6379 - Password: "" - DB: 0 - -AppLog: - Path: logs - InfoFile: info.log - ErrorFile: error.log - FatalFile: fatal.log - MaxSize: 100 - MaxBackups: 10 - MaxAge: 30 From 628ca3f0b6ca3c182aa5d91fa3806e727f7686ff Mon Sep 17 00:00:00 2001 From: zzw <1464003642@qq.com> Date: Wed, 12 Aug 2026 09:27:59 +0800 Subject: [PATCH 3/4] feat: docker build add buildx --- .gitea/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index fc7f5ae..7c0435b 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -73,7 +73,7 @@ jobs: - name: Docker build run: | - DOCKER_BUILDKIT=1 docker build \ + docker buildx build --load \ -f bff/Dockerfile \ -t ${{ vars.REGISTRY }}/$NAME:latest \ . @@ -98,7 +98,7 @@ jobs: - name: Docker build run: | - DOCKER_BUILDKIT=1 docker build \ + docker buildx build --load \ -f product/Dockerfile \ -t ${{ vars.REGISTRY }}/$NAME:latest \ . @@ -123,7 +123,7 @@ jobs: - name: Docker build run: | - DOCKER_BUILDKIT=1 docker build \ + docker buildx build --load \ -f admin/Dockerfile \ -t ${{ vars.REGISTRY }}/$NAME:latest \ . From 8befb1b326f78de3a947898f96c3f2d4b145a82b Mon Sep 17 00:00:00 2001 From: zzw <1464003642@qq.com> Date: Wed, 12 Aug 2026 10:08:30 +0800 Subject: [PATCH 4/4] fix: Dockerfile remove COPY --- admin/Dockerfile | 1 - bff/Dockerfile | 2 +- product/Dockerfile | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/admin/Dockerfile b/admin/Dockerfile index c5bb0b9..ba351eb 100644 --- a/admin/Dockerfile +++ b/admin/Dockerfile @@ -32,7 +32,6 @@ RUN apk add --no-cache tzdata \ && echo "Asia/Shanghai" > /etc/timezone COPY --from=builder /out/admin . -COPY admin/etc/admin.yaml ./etc/admin.yaml EXPOSE 10200 diff --git a/bff/Dockerfile b/bff/Dockerfile index 355234e..af97aab 100644 --- a/bff/Dockerfile +++ b/bff/Dockerfile @@ -32,7 +32,7 @@ RUN apk add --no-cache tzdata \ && echo "Asia/Shanghai" > /etc/timezone COPY --from=builder /out/bff . -COPY bff/etc/ ./etc/ +COPY bff/etc/*.pb ./etc/ EXPOSE 10000 diff --git a/product/Dockerfile b/product/Dockerfile index cdc9138..af79d54 100644 --- a/product/Dockerfile +++ b/product/Dockerfile @@ -32,7 +32,6 @@ RUN apk add --no-cache tzdata \ && echo "Asia/Shanghai" > /etc/timezone COPY --from=builder /out/product . -COPY product/etc/product.yaml ./etc/product.yaml EXPOSE 10100