-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathDockerfile
More file actions
85 lines (67 loc) · 3.37 KB
/
Copy pathDockerfile
File metadata and controls
85 lines (67 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# NOWEN - 高颜值 Bento 风格个人导航页
# 支持书签管理、分类管理、名言管理、自定义图标
# GitHub: https://github.com/cropflre/NOWEN
# 支持多架构: linux/amd64, linux/arm64 (RK3588/RK3576/RK3566 等)
# Build stage for frontend
FROM node:20-alpine AS frontend-builder
WORKDIR /app
# 前端已移除 bcrypt 等 native 模块,无需编译工具链
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# Production stage
FROM node:20-alpine AS production
# OCI 标准标签
LABEL org.opencontainers.image.title="NOWEN"
LABEL org.opencontainers.image.description="高颜值 Bento 风格个人导航页,支持书签管理、分类管理、名言管理、自定义图标,一键 Docker 部署"
LABEL org.opencontainers.image.url="https://github.com/cropflre/NOWEN"
LABEL org.opencontainers.image.source="https://github.com/cropflre/NOWEN"
LABEL org.opencontainers.image.vendor="cropflre"
LABEL org.opencontainers.image.licenses="MIT"
WORKDIR /app
# 🔑 强制覆盖 apk 仓库源为官方源
# 绿联/飞牛等 NAS 系统可能向容器注入自定义仓库配置(如 openresty),导致依赖解析失败
RUN echo "https://dl-cdn.alpinelinux.org/alpine/v$(cut -d. -f1,2 /etc/alpine-release)/main" > /etc/apk/repositories && \
echo "https://dl-cdn.alpinelinux.org/alpine/v$(cut -d. -f1,2 /etc/alpine-release)/community" >> /etc/apk/repositories && \
apk update && \
apk add --no-cache ca-certificates nginx && \
# docker-cli 为可选依赖(仅用于系统监控 fallback),安装失败不阻断构建
(apk add --no-cache docker-cli || echo "⚠️ docker-cli not available, skipping (optional)")
# Install production dependencies for backend
# server 使用 bcryptjs(纯 JS)而非 bcrypt,无需编译工具
COPY server/package*.json ./server/
RUN cd server && npm install --omit=dev
# Install tsx globally
RUN npm install -g tsx
# Copy backend source
COPY server/src ./server/src
COPY server/tsconfig.json ./server/
# Copy built frontend
COPY --from=frontend-builder /app/dist ./dist
# Copy nginx config
COPY nginx.conf /etc/nginx/http.d/default.conf
# Create data directory and safe backup directory
# 🔑 安全备份使用 /app/.nowen-safe(不在 VOLUME 声明中,属于镜像层)
# 这样即使 NAS Docker UI 重建容器,镜像层内的备份不受影响
RUN mkdir -p /app/server/data /app/.nowen-safe
# ⚠️ 故意不声明 VOLUME!
# 原因:绿联/飞牛等 NAS 的 Docker GUI 会为 VOLUME 声明的路径自动创建
# 以容器名为前缀的目录(如 cropflre_nowen-1/app_server_data),
# 更新容器时容器名变化(变成 cropflre_nowen-2),新目录是空的,数据丢失。
# 不声明 VOLUME,让用户通过 docker-compose.yml 中的 volumes 手动挂载,
# 或者 NAS GUI 的存储配置来指定固定路径。
# 🔑 防呆设计:直接在镜像内设置生产环境和固定 API 端口
# 用户通过 NAS GUI 部署时无需额外配置即可与 Nginx 反向代理保持一致
ENV NODE_ENV=production
ENV PORT=39001
# 生产端口:Nginx Web 39000,Express API 39001
EXPOSE 39000 39001
# 🔑 确保容器停止时发送 SIGTERM,让 start.sh 有机会保存数据
STOPSIGNAL SIGTERM
# Start script
COPY start.sh /app/start.sh
RUN sed -i 's/\r$//' /app/start.sh && \
sed -i 's/port 3001/port 39001/g; s/port 3000/port 39000/g' /app/start.sh && \
chmod +x /app/start.sh
CMD ["/app/start.sh"]