feat: setup full 12-Factor docker and env configurations

This commit is contained in:
RainySY
2026-04-09 03:54:53 +08:00
parent 0347499b10
commit 33b2ced419
5 changed files with 194 additions and 23 deletions

View File

@@ -64,3 +64,47 @@ jobs:
with:
files: dist/${{ matrix.name }}
generate_release_notes: true
# ==== 🌟 新增的 DockerHub 全自动推送组 ====
docker:
# 避免在其他人的野鸡 PR 测试中乱发
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
steps:
- name: Checkout codebase
uses: actions/checkout@v4
- name: Set up QEMU (支持多架构底层)
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx (全能无缝打包引流引擎)
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract Docker metadata (自动打标签系统)
id: meta
uses: docker/metadata-action@v5
with:
# 自动组合 "你的名字 / 项目名"
images: ${{ secrets.DOCKERHUB_USERNAME }}/123pan-imagehost
tags: |
type=ref,event=branch
type=ref,event=tag
# 原本的 latest 标签会在 master/main 分支时被自动赋予
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push to Space (核心推流指令)
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# 借用 Github 的高速缓存,让你后续的打包时间缩短成几秒!
cache-from: type=gha
cache-to: type=gha,mode=max

39
Dockerfile Normal file
View File

@@ -0,0 +1,39 @@
# ==== 第一阶段: 编译打包层 ====
FROM golang:1.21-alpine AS builder
# 配置国内高速 Go 代理环境,开启跨平台交叉编译所需变量
ENV GO111MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64 \
GOPROXY=https://goproxy.cn,direct
WORKDIR /app
# 优先缓存和下载项目依赖
COPY go.mod go.sum ./
RUN go mod download
# 载入完整代码并执行剥离调试信息的极限压缩静态编译 (-ldflags="-w -s")
COPY . .
RUN go build -ldflags="-w -s" -o imagehost ./cmd/main.go
# ==== 第二阶段: 纯净运行环境层 ====
FROM alpine:latest
# 123云盘采用硬 TLS 协议,必须拉取 ca-certificates否则网络连接拦截报错
# TZdata 用于纠正容器运行内的时间对齐,保障授权握手不过期
RUN apk --no-cache add ca-certificates tzdata
ENV TZ=Asia/Shanghai
WORKDIR /app
# 将上一阶段萃取好的精华可执行程序抓取过来
COPY --from=builder /app/imagehost .
# 暴露对外的 HTTP 接口
EXPOSE 8080
# 触发点火
CMD ["./imagehost"]

View File

@@ -75,6 +75,65 @@ go run cmd/main.go
---
## 🐳 Docker 云原生极简部署
如果你使用的是 NAS如群晖、威联通、软路由系统或原生携带 Docker 的云服务器,我们极力推荐使用此方案。
本项目完全遵循 **云原生十二要素 (12-Factor App)** 规范。全核心参数支持通过 **环境变量 (Environment Variables)** 纯净直连,彻底告别繁杂凌乱的配置文件管理!
#### 👉 使用 docker-compose 启动
找一个空目录,新建 `docker-compose.yml` 文件并粘贴以下内容:
```yaml
version: '3.8'
services:
imagehost:
# 替换为你刚才在 DockerHub 推送的独特镜像名!
image: 你的用户名/123pan-imagehost:latest
container_name: 123pan-imagehost
restart: unless-stopped
ports:
- "8080:8080" # 左侧是你要暴露在外网的访问端口
environment:
# 🌍 全量环保注入,零文件残留!
- PORT=8080
- CLIENT_ID=请去123pan开放平台申请必填
- CLIENT_SECRET=请去123pan开放平台申请必填
- PARENT_FILE_ID= # 专用上传目标的文件夹ID(如果传到根目录则删掉注释留空)
- API_TOKEN=PRIVATE_123_KEY # 拦截门票:强烈建议设为复杂密码防御公网盗刷
- TZ=Asia/Shanghai
```
然后在同一目录下无脑执行:
```bash
docker-compose up -d
```
启动瞬间,图床将在后台以最高效率纯净运转,一切大功告成!
*(PS: 对于仍旧偏爱传统物理文件管理配置的老玩家,系统仍包含“智能回落构建”机制:当检测不到上述环境变量时,只要挂载一个空的 `/app/conf` 数据卷进去,系统便会依然乖乖在里面为你生成默认填报模板。)*
#### 👉 使用原生 Docker 命令行 (纯净一行流)
如果你连文件都不想建,就喜欢那种直接把代码拍在终端上一键起飞的爽感,可以直接复制并在终端运行以下指令:
```bash
docker run -d \
--name 123pan-imagehost \
--restart unless-stopped \
-p 8080:8080 \
-e PORT=8080 \
-e CLIENT_ID="【去123pan获取并在引流号内填入】" \
-e CLIENT_SECRET="【去123pan获取并在引号内填入】" \
-e PARENT_FILE_ID="" \
-e API_TOKEN="PRIVATE_123_KEY" \
-e TZ="Asia/Shanghai" \
你的用户名/123pan-imagehost:latest
```
---
## 🛠️ 第三方截图工具接入 (ShareX 等)
本图床严格遵守 `RESTful API` 规范,对第三方工具接入极为友好。以下使用 **ShareX** 为例进行配置:

24
docker-compose.yml Normal file
View File

@@ -0,0 +1,24 @@
version: '3.8'
services:
imagehost:
build: .
# 如果你不想编译而是直接拉你刚才推到云端发版的镜像,可以打开下面这行:
# image: sakuradairong/123pan-imagehost:latest
container_name: 123pan-imagehost
restart: unless-stopped
ports:
# 左边是暴露给外部(即你的访问端口),右边是容器内运行端口
- "8080:8080"
environment:
# 【无文件纯净启动模式】直接把秘钥通过变量投射进去,底层不会再去管 config.yaml 存不存在了!
- PORT=8080
- CLIENT_ID=这里输入你的客户端ID
- CLIENT_SECRET=这里填你的密钥Secret
- PARENT_FILE_ID=这里留下目标文件夹ID如果不填就放根目录
- API_TOKEN=PRIVATE_123_KEY # 请千万修改它防御野生网络扫描盗刷
- TZ=Asia/Shanghai
volumes:
# 如果你还是偏爱通过改动本地物理文件的老式习惯来管理配置,取消下面的注释即可。
# 此时你可以忽略上面的 environment 变量堆。
# - ./conf:/app/conf

View File

@@ -22,9 +22,24 @@ var GlobalConfig Config
// InitConfig 读取并解析配置文件
func InitConfig(cfgFile string) {
// 【部署容错机制】:判断是否是空白环境运行并进行智能抢险初始化
if _, err := os.Stat(cfgFile); os.IsNotExist(err) {
log.Printf("⚠️ 尚未检测到配置节点,系统正在初始化并创建框架包至:[%s]", cfgFile)
viper.SetConfigFile(cfgFile)
viper.SetConfigType("yaml")
// 映射环境变量并设置默认值防穿透,让用户能够通过 Docker ENV 变量纯净启动!
viper.AutomaticEnv()
viper.SetDefault("port", 8080)
viper.SetDefault("custom_domain", "")
viper.SetDefault("client_id", "")
viper.SetDefault("client_secret", "")
viper.SetDefault("parent_file_id", "")
viper.SetDefault("api_token", "")
err := viper.ReadInConfig()
// 【部署容错机制】:当没有配置文件,且!系统环境变量中也没有提取到 client_id 等有效配置时,才触发布署断绝。
if err != nil && viper.GetString("client_id") == "" {
if _, statErr := os.Stat(cfgFile); os.IsNotExist(statErr) {
log.Printf("⚠️ 尚未检测到物理配置节点及外部环境变量,系统正在初始化框架包至:[%s]", cfgFile)
if err := os.MkdirAll(filepath.Dir(cfgFile), 0755); err != nil {
log.Fatalf("❌ 构建部署文件夹遇到致命阻塞: %v", err)
}
@@ -49,18 +64,8 @@ api_token: "PRIVATE_123_KEY"
}
// 主动断开并友善通知管理员
log.Fatalf("✅ 系统底层初始部署圆满完成!打开刚生成的 %s 文件,填入属于你的密钥,然后再重新运行", cfgFile)
log.Fatalf("✅ 底层初始部署圆满完成!你可以打开刚生成的 %s 填写密钥,或者直接通过在 Docker/系统环境变量中注入 CLIENT_ID 等参数来免密运行!", cfgFile)
}
viper.SetConfigFile(cfgFile)
viper.SetConfigType("yaml")
// 默认值
viper.SetDefault("port", 8080)
viper.SetDefault("custom_domain", "")
if err := viper.ReadInConfig(); err != nil {
log.Fatalf("配置文件读取失败: %v", err)
}
if err := viper.Unmarshal(&GlobalConfig); err != nil {