Files
opencode/skill/gitea/dockerfile-templates/go-service.md
voson 425ca5b5fd feat(gitea): 添加 Dockerfile 模板和 Rust 支持,优化 runner 网络配置说明
- 新增 Go、Node.js、Rust 服务的 Dockerfile 模板
- 新增 Rust 快速参考指南
- 新增 Rust 后端工作流模板
- 优化 create-runner.md,明确 host 网络模式为缓存必需条件
- 更新 gitea skill 主文档
2026-01-30 10:12:09 +08:00

11 KiB
Raw Blame History

Go 服务 Dockerfile 模板

Go 后端服务的 Docker 容器化模板,支持多种构建场景。

模板类型

1. CI 构建镜像Dockerfile.ci

适用场景:在 CI/CD 中使用,二进制文件已在外部构建完成。

优点

  • 镜像体积最小(~15MB
  • 构建速度快
  • 适合生产环境
# CI 构建专用 Dockerfile
# 将不常变化的层放在前面,最大化利用缓存
# 使用固定版本避免 latest 导致的缓存失效和不确定性

FROM alpine:3.21

# 基础设置层 - 很少变化,可以长期缓存
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
    apk add --no-cache tzdata wget netcat-openbsd && \
    ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

# 健康检查脚本 - 偶尔变化
COPY docker-healthcheck.sh .
RUN chmod +x docker-healthcheck.sh

# 应用二进制 - 每次构建都变化,放在最后
COPY your-binary-name .

# 健康检查(根据实际服务修改端口和端点)
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
    CMD ./docker-healthcheck.sh

CMD ["./your-binary-name"]

使用说明

  1. your-binary-name 替换为实际的二进制文件名
  2. 创建 docker-healthcheck.sh 健康检查脚本
  3. 在 CI workflow 中先构建二进制,再构建镜像

2. 完整构建镜像Dockerfile

适用场景:本地开发、无 CI 环境、独立构建。

优点

  • 自包含构建流程
  • 可在任何环境构建
  • 利用 Docker 缓存加速
# ============================================
# 构建阶段
# ============================================
FROM golang:1.25-alpine AS builder

# 安装构建依赖
RUN apk add --no-cache git make

# 设置工作目录
WORKDIR /build

# 设置 Go 代理(国内加速)
ENV GOPROXY=https://goproxy.cn,direct
ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64

# 先复制依赖文件,利用 Docker 层缓存
COPY go.mod go.sum ./
RUN go mod download

# 复制源码
COPY . .

# 构建应用(根据项目需求修改)
RUN go build -o app \
    -ldflags '-s -w -X main.GitTag=dev' \
    .

# ============================================
# 运行阶段
# ============================================
FROM alpine:3.21

# 安装运行时依赖
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
    apk add --no-cache tzdata wget netcat-openbsd && \
    ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

WORKDIR /app

# 从构建阶段复制二进制文件
COPY --from=builder /build/app .
COPY --from=builder /build/docker-healthcheck.sh .

RUN chmod +x app docker-healthcheck.sh

# 暴露端口(根据实际服务修改)
EXPOSE 8080

# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
    CMD ./docker-healthcheck.sh

CMD ["./app"]

使用说明

  1. 将构建命令修改为项目实际的构建命令
  2. 调整 ldflags 参数(版本号注入、符号表去除等)
  3. 修改端口号

3. 代码生成支持版Dockerfile.codegen

适用场景:需要在容器中生成代码(如 Ent、Wire、oapi-codegen

# ============================================
# 构建阶段
# ============================================
FROM golang:1.25-alpine AS builder

# 安装构建工具
RUN apk add --no-cache git make

WORKDIR /build

ENV GOPROXY=https://goproxy.cn,direct
ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64

# 复制依赖文件
COPY go.mod go.sum ./
RUN go mod download

# 安装代码生成工具(根据项目需求选择)
RUN go install entgo.io/ent/cmd/ent@latest && \
    go install github.com/google/wire/cmd/wire@latest && \
    go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest && \
    go install golang.org/x/tools/cmd/stringer@latest

# 复制源码
COPY . .

# 代码生成(根据项目需求修改)
RUN go generate ./...
# 或使用 go tool 调用
# RUN go tool ent generate ./ent/schema
# RUN go tool wire ./...
# RUN go tool oapi-codegen -config oapi.yaml api.yaml

# 测试(可选)
RUN go test ./...
RUN go vet ./...

# 构建
RUN go build -o app \
    -ldflags '-s -w' \
    .

# ============================================
# 运行阶段
# ============================================
FROM alpine:3.21

RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
    apk add --no-cache tzdata wget netcat-openbsd && \
    ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

WORKDIR /app

COPY --from=builder /build/app .
COPY --from=builder /build/docker-healthcheck.sh .

RUN chmod +x app docker-healthcheck.sh

EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
    CMD ./docker-healthcheck.sh

CMD ["./app"]

健康检查脚本

docker-healthcheck.sh基础版

#!/bin/sh
# Docker 健康检查脚本

# 检查应用端口是否在监听
if nc -z localhost 8080 2>/dev/null; then
    exit 0
fi

exit 1

docker-healthcheck.shHTTP 端点版)

#!/bin/sh
# Docker 健康检查脚本
# 检查 HTTP 端点是否可访问

# 使用 /health 或 /metrics 端点
if wget --spider --quiet --timeout=5 http://localhost:8080/health 2>/dev/null; then
    exit 0
fi

# 备用:检查端口是否在监听
if nc -z localhost 8080 2>/dev/null; then
    exit 0
fi

exit 1

docker-healthcheck.sh多端口版

#!/bin/sh
# Docker 健康检查脚本
# 检查多个端口(适用于多个 API 服务)

# 检查端口 2020 (Platform API)
if ! nc -z localhost 2020 2>/dev/null; then
    echo "Port 2020 is not responding"
    exit 1
fi

# 检查端口 2021 (WxMP API)
if ! nc -z localhost 2021 2>/dev/null; then
    echo "Port 2021 is not responding"
    exit 1
fi

# 或使用 HTTP 端点
# if ! wget --spider --quiet --timeout=5 http://localhost:2020/metrics 2>/dev/null; then
#     exit 1
# fi

exit 0

高级配置

环境变量配置

# 在 Dockerfile 中设置默认环境变量
ENV MODE=production
ENV LOG_LEVEL=info
ENV GIN_MODE=release

# 运行时可覆盖
# docker run -e MODE=test -e LOG_LEVEL=debug your-image

配置文件挂载

# 创建配置目录
RUN mkdir -p /app/configs

# 运行时挂载配置文件
# docker run -v ./configs:/app/configs your-image

非 root 用户运行

# 创建非特权用户
RUN addgroup -g 1000 appuser && \
    adduser -D -u 1000 -G appuser appuser

WORKDIR /app

# 复制文件
COPY --from=builder --chown=appuser:appuser /build/app .

# 切换用户
USER appuser

CMD ["./app"]

多阶段构建优化

# ============================================
# 依赖下载阶段(缓存 go.mod
# ============================================
FROM golang:1.25-alpine AS deps

WORKDIR /build

ENV GOPROXY=https://goproxy.cn,direct

COPY go.mod go.sum ./
RUN go mod download

# ============================================
# 构建阶段
# ============================================
FROM golang:1.25-alpine AS builder

WORKDIR /build

# 从依赖阶段复制缓存
COPY --from=deps /go/pkg /go/pkg

ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64

COPY . .

RUN go build -o app -ldflags '-s -w' .

# ============================================
# 运行阶段
# ============================================
FROM alpine:3.21

# ... 省略后续步骤

镜像优化技巧

1. 减小镜像体积

# 使用 Alpine 基础镜像
FROM alpine:3.21

# 去除符号表和调试信息
RUN go build -ldflags '-s -w' -o app

# 使用 upx 压缩(可选,启动时间会变长)
RUN apk add --no-cache upx && \
    upx --best --lzma app && \
    apk del upx

2. 利用构建缓存

# 先复制 go.mod 和 go.sum利用依赖缓存
COPY go.mod go.sum ./
RUN go mod download

# 再复制源码(源码变化频繁)
COPY . .

3. 合并 RUN 命令

# 合并多个 RUN 命令减少层数
RUN apk add --no-cache tzdata wget netcat-openbsd && \
    ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    addgroup -g 1000 appuser

4. 使用 .dockerignore

# .dockerignore
.git/
.gitignore
*.md
docs/
tests/
.github/
.gitea/
Dockerfile*
docker-compose.yml
*.log
tmp/
vendor/

构建命令示例

本地构建

# 基础构建
docker build -t your-service:latest .

# 指定 Dockerfile
docker build -f Dockerfile.ci -t your-service:latest .

# 传递构建参数
docker build --build-arg GIT_TAG=v1.0.0 -t your-service:1.0.0 .

# 查看构建过程
docker build --progress=plain -t your-service:latest .

CI/CD 构建

# 使用 BuildKit 缓存
export DOCKER_BUILDKIT=1

# 使用注册表缓存
docker build \
  --cache-from=type=registry,ref=your-service:buildcache \
  --cache-to=type=registry,ref=your-service:buildcache,mode=max \
  -t your-service:latest \
  .

运行容器示例

# 基础运行
docker run -d -p 8080:8080 your-service:latest

# 挂载配置文件
docker run -d \
  -p 8080:8080 \
  -v ./configs:/app/configs \
  -v ./logs:/app/logs \
  your-service:latest

# 设置环境变量
docker run -d \
  -p 8080:8080 \
  -e MODE=production \
  -e DATABASE_URL=postgres://... \
  your-service:latest

# 查看日志
docker logs -f <container-id>

# 进入容器调试
docker exec -it <container-id> /bin/sh

安全建议

1. 使用特定版本标签

# 不推荐:使用 latest
FROM alpine:latest

# 推荐:使用特定版本
FROM alpine:3.21

2. 定期更新依赖

# 更新 Go 模块
go get -u ./...
go mod tidy

# 更新基础镜像
docker pull alpine:3.21

3. 扫描漏洞

# 使用 Trivy 扫描
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image your-service:latest

4. 最小权限原则

# 使用非 root 用户
USER appuser

# 只读文件系统(如果适用)
# docker run --read-only your-service

常见问题

Q1: 时区不正确

原因: 容器默认使用 UTC 时区

解决方案:

RUN apk add --no-cache tzdata && \
    ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

Q2: 网络连接超时

原因: DNS 解析问题或网络配置

解决方案:

# 运行时指定 DNS
docker run --dns 8.8.8.8 your-service

# 或在 Dockerfile 中配置
RUN echo 'nameserver 8.8.8.8' > /etc/resolv.conf

Q3: CGO 依赖问题

错误信息: binary was compiled with 'CGO_ENABLED=1'

解决方案:

# 禁用 CGO
ENV CGO_ENABLED=0

# 或安装 gcc
RUN apk add --no-cache gcc musl-dev

Q4: 静态链接失败

错误信息: dynamic executable

解决方案:

# 确保 CGO_ENABLED=0
ENV CGO_ENABLED=0

# 或使用 musl 交叉编译
RUN apk add --no-cache musl-dev
RUN go build -ldflags '-linkmode external -extldflags "-static"' -o app

参考资源