签入版本
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
# ============================================================
|
||||
# Docker Compose 环境变量模板
|
||||
# 用法:复制为同目录 .env(同目录被 .gitignore 与 .dockerignore 双重排除)
|
||||
# copy .env.example .env
|
||||
# 说明:本文件使用 MYSQL_HOST 等友好名,由 docker-compose.yml 的
|
||||
# environment 块映射为 GF_ 规范键(如 GF_DATABASE_DEFAULT_LINK)
|
||||
# 注入容器——应用只认 GF_ 前缀键,勿将友好名原样透传给应用
|
||||
# 注意:值中含 $ 须写成 $$(compose 变量插值会吞掉单 $,
|
||||
# 如密码 abc#$^ 应写为 abc#$$^)
|
||||
# ============================================================
|
||||
|
||||
# ===== 应用 =====
|
||||
APP_PORT=8000
|
||||
|
||||
# JWT 签名密钥(生产必改):要求 ≥32 字节密码学随机,禁止词典词/项目名
|
||||
# 生成方式(任选其一,生成后替换下方示例值):
|
||||
# Linux 部署机: openssl rand -hex 32
|
||||
# 无 openssl 时: python3 -c "import secrets; print(secrets.token_hex(32))"
|
||||
# Windows: [Convert]::ToBase64String([Security.Cryptography.RandomNumberGenerator]::GetBytes(32))
|
||||
# 生成示例:a3f8c2d91e4b7f05...(64 位十六进制,各环境独立生成、勿复用同一值)
|
||||
# 注意:轮换此值后所有已签发令牌立即失效,用户需重新登录(安排发版窗口执行)
|
||||
JWT_SECRET=please-change-this-jwt-secret
|
||||
|
||||
# ===== MySQL =====
|
||||
# 数据库地址(容器网络内地址)
|
||||
# 连 compose 自带 mysql 服务:保持默认服务名 mysql
|
||||
# 连宿主机数据库:Mac/Windows Docker Desktop 用 host.docker.internal,
|
||||
# Linux 用宿主机实际 IP 或 --add-host=host.docker.internal:host-gateway
|
||||
# 注意:容器内 127.0.0.1 指向容器自身,连不上宿主机数据库
|
||||
MYSQL_HOST=mysql
|
||||
# 数据库监听端口(进连接串;连外部库时填外部库端口)
|
||||
# 注:自带 mysql/redis 服务的宿主映射端口已在 compose 写死(3306/6379),
|
||||
# 仅供宿主机客户端直连调试,占用冲突时改 compose 的 ports
|
||||
MYSQL_PORT=3306
|
||||
MYSQL_USER=root
|
||||
MYSQL_PASSWORD=root
|
||||
MYSQL_DATABASE=easygoadmin.goframe.elevue
|
||||
|
||||
# ===== Redis =====
|
||||
# 同 MYSQL_HOST 规则;容器内 127.0.0.1 指向容器自身,连不上宿主机 Redis
|
||||
REDIS_HOST=redis
|
||||
# 连宿主机 Redis 时改为(Windows/Mac Docker Desktop):
|
||||
# REDIS_HOST=host.docker.internal
|
||||
# Redis 监听端口(进连接串;连外部库时填外部端口)
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=123456
|
||||
@@ -0,0 +1,97 @@
|
||||
# ============================================================
|
||||
# Dockerfile:EasyGoAdmin 后端镜像(多阶段构建)
|
||||
# 构建命令(上下文为项目根目录,在项目根执行):
|
||||
# docker build -f docker/Dockerfile -t easygoadmin:latest .
|
||||
#
|
||||
# 设计要点
|
||||
# - 纯 Go 项目(sqlite 驱动为 modernc 系,无 CGO),CGO_ENABLED=0 静态编译
|
||||
# - builder 只负责编译,runtime 仅含二进制 + 运行时资产,镜像最小化
|
||||
# - 运行时资产四件:manifest/config、manifest/data(ip2region.xdb)、
|
||||
# resource(字体/swagger)、templates(代码生成器模板)
|
||||
# - 敏感配置不改镜像内文件,运行时用 GF_ 前缀环境变量覆盖
|
||||
# (见 manifest/config/config.yaml 头部说明)
|
||||
# - 源码 COPY 放在依赖下载之后,保护 go mod 层缓存
|
||||
#
|
||||
# 构建参数
|
||||
# VAR_PORT 应用监听端口
|
||||
# ============================================================
|
||||
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# 全局构建参数
|
||||
# 在 FROM 之前声明,可供后续各阶段引用
|
||||
# ------------------------------------------------------------
|
||||
ARG VAR_GOLANG_IMAGE=golang:1.27-alpine
|
||||
ARG VAR_RUNTIME_IMAGE=alpine:3.22
|
||||
ARG VAR_PORT=8000
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 阶段一:builder —— 编译静态二进制
|
||||
# ============================================================
|
||||
FROM ${VAR_GOLANG_IMAGE} AS builder
|
||||
|
||||
LABEL MAINTAINER="easygoadmin@163.com"
|
||||
|
||||
# 国内代理:加速 go mod 下载(海外环境可改为 https://proxy.golang.org,direct)
|
||||
ENV GOPROXY=https://goproxy.cn,direct \
|
||||
GO111MODULE=on \
|
||||
CGO_ENABLED=0 \
|
||||
GOOS=linux
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# 先拷依赖清单,利用层缓存:源码变更但 go.mod/go.sum 未变时不重复下载
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
|
||||
# 拷源码并编译(-trimpath 去除本地路径,-s -w 去除符号表与调试信息)
|
||||
COPY . .
|
||||
RUN go build -trimpath -ldflags "-s -w" -o /build/bin/admin-server main.go
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 阶段二:runtime —— 最终业务镜像
|
||||
# ============================================================
|
||||
FROM ${VAR_RUNTIME_IMAGE} AS runtime
|
||||
|
||||
LABEL MAINTAINER="easygoadmin@163.com"
|
||||
|
||||
# 时区(应用配置 app.timezone=Asia/Shanghai,日志与定时任务依赖系统时区)
|
||||
ENV TZ=Asia/Shanghai
|
||||
|
||||
# tzdata 提供时区数据库;ca-certificates 供 HTTPS 外呼(无外呼场景可去掉)
|
||||
RUN set -eux; \
|
||||
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories; \
|
||||
apk add --no-cache tzdata ca-certificates; \
|
||||
# 非 root 运行(低权限用户跑业务)
|
||||
addgroup -g 1000 app && adduser -u 1000 -G app -s /sbin/nologin -D app; \
|
||||
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
||||
|
||||
WORKDIR /opt/easygoadmin
|
||||
|
||||
# 运行时资产(先于二进制 COPY,业务代码变动不破坏资产层缓存)
|
||||
COPY --chown=app:app manifest/config ./manifest/config
|
||||
COPY --chown=app:app manifest/data ./manifest/data
|
||||
COPY --chown=app:app resource ./resource
|
||||
COPY --chown=app:app templates ./templates
|
||||
|
||||
# 二进制
|
||||
COPY --chown=app:app --from=builder /build/bin/admin-server ./bin/admin-server
|
||||
|
||||
# 上传目录与日志目录:预建并授权,compose 挂载宿主卷时属主一致
|
||||
RUN mkdir -p /data/upload /opt/easygoadmin/log && \
|
||||
chown -R app:app /data/upload /opt/easygoadmin/log
|
||||
|
||||
USER app
|
||||
|
||||
# ARG 转 ENV,运行期与 compose/HEALTHCHECK 可读
|
||||
ENV VAR_PORT=${VAR_PORT}
|
||||
EXPOSE ${VAR_PORT}
|
||||
|
||||
# 健康检查(/api/health 为公开白名单路径,不带 /v1)
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
||||
CMD wget -qO- "http://127.0.0.1:${VAR_PORT}/api/health" || exit 1
|
||||
|
||||
# 前台运行;优雅重启由框架 graceful 配置处理
|
||||
ENTRYPOINT ["./bin/admin-server"]
|
||||
@@ -0,0 +1,110 @@
|
||||
# +======================================================================
|
||||
# | 模块: Docker Compose 配置
|
||||
# | 说明: EasyGoAdmin 后端服务容器编排(后端 + MySQL + Redis)
|
||||
# | 位置: 位于 docker/ 目录,宿主路径均以 ../ 相对项目根
|
||||
# | 启动(在 docker/ 目录执行):
|
||||
# | copy .env.example .env # 首次,按需修改密钥
|
||||
# | docker compose up -d --build
|
||||
# +======================================================================
|
||||
|
||||
services:
|
||||
# ------------------------------------------------------------
|
||||
# 后端服务(GoFrame)
|
||||
# ------------------------------------------------------------
|
||||
easygoadmin:
|
||||
image: easygoadmin:latest
|
||||
container_name: easygoadmin
|
||||
build:
|
||||
# 上下文为项目根目录(compose 文件所在目录的上一级)
|
||||
context: ..
|
||||
dockerfile: docker/Dockerfile
|
||||
restart: always
|
||||
ports:
|
||||
- "${APP_PORT:-8000}:8000"
|
||||
# 敏感/环境相关配置一律 GF_ 前缀覆盖,不改镜像内 config.yaml
|
||||
# (GF_ 键名 = 配置路径大写下划线,如 file.uploadDir → GF_FILE_UPLOADDIR)
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
GF_DATABASE_DEFAULT_LINK: "mysql:${MYSQL_USER:-root}:${MYSQL_PASSWORD:-root}@tcp(${MYSQL_HOST:-mysql}:${MYSQL_PORT:-3306})/${MYSQL_DATABASE:-easygoadmin.goframe.elevue}?charset=utf8mb4&parseTime=true&loc=Local"
|
||||
GF_REDIS_DEFAULT_ADDRESS: "${REDIS_HOST:-redis}:${REDIS_PORT:-6379}"
|
||||
GF_REDIS_DEFAULT_PASS: "${REDIS_PASSWORD:-123456}"
|
||||
GF_FILE_UPLOADDIR: "/data/upload"
|
||||
GF_JWT_SECRET: "${JWT_SECRET:-please-change-this-jwt-secret}"
|
||||
GF_CAPTCHA_BYPASSCODE: "" # 生产环境清空万能验证码
|
||||
GF_APP_ERRORMSG: "false" # 生产环境关闭详细错误信息
|
||||
volumes:
|
||||
# 上传文件持久化(两段式上传的 temp 与正式目录都在 uploadDir 下)
|
||||
- ../upload:/data/upload
|
||||
# 日志目录持久化
|
||||
- ../log:/opt/easygoadmin/log
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "500m"
|
||||
max-file: "10"
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# MySQL 8(首次启动自动导入定稿库结构)
|
||||
# ------------------------------------------------------------
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
container_name: easygoadmin-mysql
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD:-root}
|
||||
MYSQL_DATABASE: ${MYSQL_DATABASE:-easygoadmin.goframe.elevue}
|
||||
TZ: Asia/Shanghai
|
||||
ports:
|
||||
# 宿主映射端口写死(仅供宿主机客户端直连调试;宿主机 3306 被占用时改此处)
|
||||
- "3306:3306"
|
||||
volumes:
|
||||
- mysql-data:/var/lib/mysql
|
||||
# 首次初始化:导入定稿 SQL(仅空数据卷时执行一次)
|
||||
- ../document/mysql/easygoadmin.goframe.elevue.sql:/docker-entrypoint-initdb.d/init.sql:ro
|
||||
command:
|
||||
- --character-set-server=utf8mb4
|
||||
- --collation-server=utf8mb4_unicode_ci
|
||||
- --lower_case_table_names=1
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-p${MYSQL_PASSWORD:-root}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "500m"
|
||||
max-file: "10"
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Redis(JWT黑名单/验证码/字典/身份缓存;宕机时应用自动降级内存)
|
||||
# ------------------------------------------------------------
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: easygoadmin-redis
|
||||
restart: always
|
||||
command: ["redis-server", "--requirepass", "${REDIS_PASSWORD:-123456}", "--appendonly", "yes"]
|
||||
ports:
|
||||
# 宿主映射端口写死(仅供宿主机客户端直连调试;宿主机 6379 被占用时改此处)
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-123456}", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "500m"
|
||||
max-file: "10"
|
||||
|
||||
volumes:
|
||||
mysql-data:
|
||||
redis-data:
|
||||
Reference in New Issue
Block a user