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

551 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Go 服务 Dockerfile 模板
Go 后端服务的 Docker 容器化模板,支持多种构建场景。
## 模板类型
### 1. CI 构建镜像Dockerfile.ci
**适用场景**:在 CI/CD 中使用,二进制文件已在外部构建完成。
**优点**
- 镜像体积最小(~15MB
- 构建速度快
- 适合生产环境
```dockerfile
# 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 缓存加速
```dockerfile
# ============================================
# 构建阶段
# ============================================
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
```dockerfile
# ============================================
# 构建阶段
# ============================================
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基础版
```bash
#!/bin/sh
# Docker 健康检查脚本
# 检查应用端口是否在监听
if nc -z localhost 8080 2>/dev/null; then
exit 0
fi
exit 1
```
### docker-healthcheck.shHTTP 端点版)
```bash
#!/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多端口版
```bash
#!/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
# 在 Dockerfile 中设置默认环境变量
ENV MODE=production
ENV LOG_LEVEL=info
ENV GIN_MODE=release
# 运行时可覆盖
# docker run -e MODE=test -e LOG_LEVEL=debug your-image
```
### 配置文件挂载
```dockerfile
# 创建配置目录
RUN mkdir -p /app/configs
# 运行时挂载配置文件
# docker run -v ./configs:/app/configs your-image
```
### 非 root 用户运行
```dockerfile
# 创建非特权用户
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"]
```
### 多阶段构建优化
```dockerfile
# ============================================
# 依赖下载阶段(缓存 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. 减小镜像体积
```dockerfile
# 使用 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. 利用构建缓存
```dockerfile
# 先复制 go.mod 和 go.sum利用依赖缓存
COPY go.mod go.sum ./
RUN go mod download
# 再复制源码(源码变化频繁)
COPY . .
```
### 3. 合并 RUN 命令
```dockerfile
# 合并多个 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/
```
## 构建命令示例
### 本地构建
```bash
# 基础构建
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 构建
```bash
# 使用 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 \
.
```
## 运行容器示例
```bash
# 基础运行
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. 使用特定版本标签
```dockerfile
# 不推荐:使用 latest
FROM alpine:latest
# 推荐:使用特定版本
FROM alpine:3.21
```
### 2. 定期更新依赖
```bash
# 更新 Go 模块
go get -u ./...
go mod tidy
# 更新基础镜像
docker pull alpine:3.21
```
### 3. 扫描漏洞
```bash
# 使用 Trivy 扫描
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image your-service:latest
```
### 4. 最小权限原则
```dockerfile
# 使用非 root 用户
USER appuser
# 只读文件系统(如果适用)
# docker run --read-only your-service
```
## 常见问题
### Q1: 时区不正确
**原因**: 容器默认使用 UTC 时区
**解决方案**:
```dockerfile
RUN apk add --no-cache tzdata && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
```
### Q2: 网络连接超时
**原因**: DNS 解析问题或网络配置
**解决方案**:
```bash
# 运行时指定 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'`
**解决方案**:
```dockerfile
# 禁用 CGO
ENV CGO_ENABLED=0
# 或安装 gcc
RUN apk add --no-cache gcc musl-dev
```
### Q4: 静态链接失败
**错误信息**: `dynamic executable`
**解决方案**:
```dockerfile
# 确保 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
```
## 参考资源
- [Go 官方 Docker 指南](https://docs.docker.com/language/golang/)
- [Alpine Linux 包搜索](https://pkgs.alpinelinux.org/packages)
- [Docker 多阶段构建文档](https://docs.docker.com/build/building/multi-stage/)
- [Go 编译器标志](https://pkg.go.dev/cmd/go)