feat: setup full 12-Factor docker and env configurations
This commit is contained in:
44
.github/workflows/go.yml
vendored
44
.github/workflows/go.yml
vendored
@@ -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
39
Dockerfile
Normal 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"]
|
||||
59
README.md
59
README.md
@@ -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
24
docker-compose.yml
Normal 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
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user