# =============================================================== # Storage 一体化镜像: 静态前端 (dist/) + Express/DuckDB 服务端 (server/) 同进程 # 构建: docker build -t storage:latest . # 可选 --build-arg VITE_API_BASE=https://api.example.com 让前端走绝对地址 (默认同源 /api) # 运行: docker run -d --name storage -p 3003:3003 -v storage-data:/app/data storage:latest # 端口: 与 Wardrobe(:3002) / iboard(:3001) 同机共存, 按部署环境分配 (见 部署环境.md) # 数据: DuckDB (data/storage.duckdb) + 图片 (data/uploads) 都在 /app/data 卷, 部署不丢数据 # =============================================================== FROM node:22-slim AS builder WORKDIR /app # 国内构建时可换源 RUN npm config set registry https://registry.npmmirror.com # 先拷贝 package 文件, 利用 Docker 缓存 COPY package*.json ./ RUN npm install # 拷贝源码 COPY . . # 构建前端 (输出到 dist/); 留空 = 同源 /api ARG VITE_API_BASE= ENV VITE_API_BASE=$VITE_API_BASE RUN npm run build # 运行时阶段 (slim: @duckdb/node-api 用 glibc 预编译, 不能用 alpine musl) FROM node:22-slim WORKDIR /app RUN npm config set registry https://registry.npmmirror.com # 只装运行时依赖 COPY package*.json ./ RUN npm install --omit=dev # 业务数据目录: DuckDB + 图片上传, 运行时挂 -v storage-data:/app/data 持久化 RUN mkdir -p /app/data ENV DB_PATH=/app/data/storage.duckdb ENV UPLOAD_DIR=/app/data/uploads # 拷贝构建产物 (server/ 为纯 JS, 直接 node 运行, 无需 strip-types) COPY --from=builder /app/dist ./dist COPY --from=builder /app/server ./server HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD wget -qO- http://127.0.0.1:3003/healthz || exit 1 ENV NODE_ENV=production ENV PORT=3003 EXPOSE 3003 CMD ["node", "server/index.js"]