Skip to content

Commit 4acb256

Browse files
committed
feat(docker): 添加Docker配置和忽略文件
新增`.dockerignore`文件,用于指定在构建Docker镜像时忽略的文件和目录。 新增`.github/workflows/docker.yml`文件,用于定义GitHub Actions工作流,自动构建并推送Docker镜像到GitHub Container Registry。 新增`Dockerfile`,定义了构建前端和后端的多阶段构建过程,并最终生成运行时镜像。 新增`config.example.toml`文件,提供了一个配置文件的示例,用于初始化和配置应用程序。 修改`config.toml`文件,将S3存储的`bucket`和`region`字段默认值设置为空字符串,以便用户自定义配置。 修改`crates/common/src/config.rs`文件,添加对环境变量`MDP_STORAGE__FS__ROOT`和`MDP_STORAGE__S3__*`的支持,允许从环境变量中读取配置信息。 新增`docker-compose.yml`文件,用于定义Docker Compose服务,简化开发环境的启动和配置。
1 parent 95b5044 commit 4acb256

File tree

8 files changed

+261
-7
lines changed

8 files changed

+261
-7
lines changed

.dockerignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
target/
2+
web/node_modules/
3+
web/dist/
4+
.git/
5+
data/
6+
uploads/
7+
*.md
8+
LICENSE
9+
.claude/

.github/workflows/docker.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: Build and Push Docker Image
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
8+
env:
9+
REGISTRY: ghcr.io
10+
IMAGE_NAME: ${{ github.repository }}
11+
12+
jobs:
13+
build-and-push:
14+
runs-on: ubuntu-latest
15+
permissions:
16+
contents: read
17+
packages: write
18+
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
23+
- name: Set up Docker Buildx
24+
uses: docker/setup-buildx-action@v3
25+
26+
- name: Login to GHCR
27+
uses: docker/login-action@v3
28+
with:
29+
registry: ${{ env.REGISTRY }}
30+
username: ${{ github.actor }}
31+
password: ${{ secrets.GITHUB_TOKEN }}
32+
33+
- name: Extract version from tag
34+
id: meta
35+
uses: docker/metadata-action@v5
36+
with:
37+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
38+
tags: |
39+
type=semver,pattern={{version}}
40+
type=semver,pattern={{major}}.{{minor}}
41+
type=raw,value=latest
42+
43+
- name: Build and push
44+
uses: docker/build-push-action@v6
45+
with:
46+
context: .
47+
push: true
48+
tags: ${{ steps.meta.outputs.tags }}
49+
labels: ${{ steps.meta.outputs.labels }}
50+
cache-from: type=gha
51+
cache-to: type=gha,mode=max

.gitignore

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,29 @@
1+
# Rust
12
/target
23
**/*.rs.bk
34
*.pdb
5+
6+
# Node
7+
/web/node_modules
8+
/web/dist
9+
10+
# Data
11+
/data
12+
/uploads
13+
14+
# Config (may contain secrets)
15+
config.toml
416
.env
517
*.log
6-
/uploads
7-
/data
8-
/.claude
9-
/web/node_modules
10-
/web/dist
18+
19+
# IDE
20+
.vscode/
21+
.idea/
22+
*.swp
23+
24+
# OS
25+
.DS_Store
26+
Thumbs.db
27+
28+
# Claude
29+
/.claude

Dockerfile

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Stage 1: Build frontend
2+
FROM node:20-alpine AS frontend
3+
RUN corepack enable && corepack prepare pnpm@latest --activate
4+
WORKDIR /build
5+
COPY web/package.json web/pnpm-lock.yaml ./
6+
RUN pnpm install --frozen-lockfile
7+
COPY web/ ./
8+
RUN pnpm build
9+
10+
# Stage 2: Build backend
11+
FROM rust:1.85-bookworm AS backend
12+
WORKDIR /build
13+
# Copy manifests first for dependency caching
14+
COPY Cargo.toml Cargo.lock ./
15+
COPY crates/common/Cargo.toml crates/common/Cargo.toml
16+
COPY crates/auth/Cargo.toml crates/auth/Cargo.toml
17+
COPY crates/storage/Cargo.toml crates/storage/Cargo.toml
18+
COPY crates/core/Cargo.toml crates/core/Cargo.toml
19+
COPY crates/api/Cargo.toml crates/api/Cargo.toml
20+
COPY crates/webdav/Cargo.toml crates/webdav/Cargo.toml
21+
COPY migration/Cargo.toml migration/Cargo.toml
22+
# Create dummy sources so cargo can resolve the workspace
23+
RUN mkdir -p src && echo "fn main() {}" > src/main.rs \
24+
&& mkdir -p crates/common/src && echo "" > crates/common/src/lib.rs \
25+
&& mkdir -p crates/auth/src && echo "" > crates/auth/src/lib.rs \
26+
&& mkdir -p crates/storage/src && echo "" > crates/storage/src/lib.rs \
27+
&& mkdir -p crates/core/src && echo "" > crates/core/src/lib.rs \
28+
&& mkdir -p crates/api/src && echo "" > crates/api/src/lib.rs \
29+
&& mkdir -p crates/webdav/src && echo "" > crates/webdav/src/lib.rs \
30+
&& mkdir -p migration/src && echo "" > migration/src/lib.rs
31+
RUN cargo build --release 2>/dev/null || true
32+
# Copy real sources and build
33+
COPY src/ src/
34+
COPY crates/ crates/
35+
COPY migration/ migration/
36+
RUN touch src/main.rs crates/*/src/lib.rs migration/src/lib.rs \
37+
&& cargo build --release
38+
39+
# Stage 3: Runtime
40+
FROM debian:bookworm-slim
41+
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
42+
WORKDIR /app
43+
COPY --from=backend /build/target/release/mediadrive-pro ./
44+
COPY --from=frontend /build/dist/ ./web/dist/
45+
COPY config.example.toml ./config.toml
46+
47+
RUN mkdir -p data uploads
48+
49+
EXPOSE 8080
50+
CMD ["./mediadrive-pro"]

config.example.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[server]
2+
host = "0.0.0.0"
3+
port = 8080
4+
5+
[database]
6+
url = "sqlite:./data/mediadrive.db?mode=rwc"
7+
max_connections = 5
8+
auto_migrate = true
9+
10+
[storage]
11+
backend = "fs"
12+
13+
[storage.fs]
14+
root = "./uploads"
15+
16+
[storage.s3]
17+
bucket = ""
18+
region = ""
19+
endpoint = ""
20+
access_key_id = ""
21+
secret_access_key = ""
22+
23+
[auth]
24+
jwt_secret = "change-me-in-production"
25+
access_token_ttl_secs = 1800
26+
27+
[webdav]
28+
enabled = true
29+
prefix = "/dav"

config.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ backend = "fs"
1414
root = "./uploads"
1515

1616
[storage.s3]
17-
bucket = "mediadrive"
18-
region = "us-east-1"
17+
bucket = ""
18+
region = ""
1919
endpoint = ""
2020
access_key_id = ""
2121
secret_access_key = ""

crates/common/src/config.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,83 @@ impl AppConfig {
102102
if let Ok(val) = std::env::var("MDP_STORAGE__BACKEND") {
103103
config.storage.backend = val;
104104
}
105+
if let Ok(val) = std::env::var("MDP_STORAGE__FS__ROOT") {
106+
config
107+
.storage
108+
.fs
109+
.get_or_insert(FsStorageConfig {
110+
root: String::new(),
111+
})
112+
.root = val;
113+
}
114+
if let Ok(val) = std::env::var("MDP_STORAGE__S3__BUCKET") {
115+
config
116+
.storage
117+
.s3
118+
.get_or_insert(S3StorageConfig {
119+
bucket: String::new(),
120+
region: String::new(),
121+
endpoint: String::new(),
122+
access_key_id: String::new(),
123+
secret_access_key: String::new(),
124+
})
125+
.bucket = val;
126+
}
127+
if let Ok(val) = std::env::var("MDP_STORAGE__S3__REGION") {
128+
config
129+
.storage
130+
.s3
131+
.get_or_insert(S3StorageConfig {
132+
bucket: String::new(),
133+
region: String::new(),
134+
endpoint: String::new(),
135+
access_key_id: String::new(),
136+
secret_access_key: String::new(),
137+
})
138+
.region = val;
139+
}
140+
if let Ok(val) = std::env::var("MDP_STORAGE__S3__ENDPOINT") {
141+
config
142+
.storage
143+
.s3
144+
.get_or_insert(S3StorageConfig {
145+
bucket: String::new(),
146+
region: String::new(),
147+
endpoint: String::new(),
148+
access_key_id: String::new(),
149+
secret_access_key: String::new(),
150+
})
151+
.endpoint = val;
152+
}
153+
if let Ok(val) = std::env::var("MDP_STORAGE__S3__ACCESS_KEY_ID") {
154+
config
155+
.storage
156+
.s3
157+
.get_or_insert(S3StorageConfig {
158+
bucket: String::new(),
159+
region: String::new(),
160+
endpoint: String::new(),
161+
access_key_id: String::new(),
162+
secret_access_key: String::new(),
163+
})
164+
.access_key_id = val;
165+
}
166+
if let Ok(val) = std::env::var("MDP_STORAGE__S3__SECRET_ACCESS_KEY") {
167+
config
168+
.storage
169+
.s3
170+
.get_or_insert(S3StorageConfig {
171+
bucket: String::new(),
172+
region: String::new(),
173+
endpoint: String::new(),
174+
access_key_id: String::new(),
175+
secret_access_key: String::new(),
176+
})
177+
.secret_access_key = val;
178+
}
179+
if let Ok(val) = std::env::var("MDP_WEBDAV__ENABLED") {
180+
config.webdav.enabled = val == "true" || val == "1";
181+
}
105182

106183
Ok(config)
107184
}

docker-compose.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
services:
2+
mediadrive:
3+
build: .
4+
ports:
5+
- "8080:8080"
6+
volumes:
7+
- ./data:/app/data
8+
- ./uploads:/app/uploads
9+
# - ./config.toml:/app/config.toml # 自定义配置文件
10+
environment:
11+
- MDP_AUTH__JWT_SECRET=change-me-in-production
12+
# 切换 S3 存储:
13+
# - MDP_STORAGE__BACKEND=s3
14+
# - MDP_STORAGE__S3__BUCKET=my-bucket
15+
# - MDP_STORAGE__S3__REGION=us-east-1
16+
# - MDP_STORAGE__S3__ENDPOINT=https://s3.example.com
17+
# - MDP_STORAGE__S3__ACCESS_KEY_ID=xxx
18+
# - MDP_STORAGE__S3__SECRET_ACCESS_KEY=xxx
19+
restart: unless-stopped

0 commit comments

Comments
 (0)