From eea801bef3852db8ff11b2976302cc554210a516 Mon Sep 17 00:00:00 2001 From: rbetree Date: Thu, 19 Feb 2026 17:53:48 +0800 Subject: [PATCH] feat(docker): add production-ready container deployment --- .dockerignore | 21 +++++++++++++++++ Dockerfile | 37 ++++++++++++++++++++++++++++++ README.md | 48 ++++++++++++++++++++++++++++++++++++++- docker-compose.yml | 13 +++++++++++ docker/nginx/default.conf | 30 ++++++++++++++++++++++++ 5 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 docker/nginx/default.conf diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..d38aa90 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,21 @@ +.git +.github +.husky +.vscode +.idea + +node_modules +dist +dev +coverage +.nyc_output + +docs +*.log +npm-debug.log* + +.specstory +.spec-workflow +.serena +.claude + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..eaae827 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,37 @@ +# syntax=docker/dockerfile:1.7 + +FROM node:22-alpine AS builder + +WORKDIR /app + +ENV HUSKY=0 + +COPY package.json package-lock.json ./ +RUN npm ci + +COPY . . + +ARG MENAV_ENABLE_SYNC=false +ARG MENAV_IMPORT_BOOKMARKS=false + +RUN if [ "${MENAV_IMPORT_BOOKMARKS}" = "true" ]; then \ + MENAV_BOOKMARKS_DETERMINISTIC=1 npm run import-bookmarks; \ + fi \ + && if [ "${MENAV_ENABLE_SYNC}" = "true" ]; then \ + npm run build; \ + else \ + PROJECTS_ENABLED=false HEATMAP_ENABLED=false RSS_ENABLED=false npm run build; \ + fi + +FROM nginx:1.27-alpine AS runtime + +WORKDIR /usr/share/nginx/html + +COPY docker/nginx/default.conf /etc/nginx/conf.d/default.conf +COPY --from=builder /app/dist ./ + +EXPOSE 80 + +STOPSIGNAL SIGQUIT + +CMD ["nginx", "-g", "daemon off;"] diff --git a/README.md b/README.md index 458f6d9..eabbc44 100644 --- a/README.md +++ b/README.md @@ -453,6 +453,52 @@ npm run format +### Docker 部署(推荐) + +
+点击展开 + +MeNav 构建后是纯静态站点(`dist/`),仓库已内置 Docker 部署文件,可直接构建并运行。 + +#### 方式一:Docker Compose(推荐) + +1. 准备配置(首次使用): + - 按 [设置配置文件](#设置配置文件) 完成 `config/user/` 配置 + - 如果要导入书签,可先把书签 HTML 放到 `bookmarks/` 目录 + +2. 构建并启动: + +```bash +docker compose up -d --build +``` + +默认访问地址:`http://localhost:8080` + +3. 常用可选参数(通过环境变量传入): + +```bash +MENAV_PORT=80 MENAV_ENABLE_SYNC=true MENAV_IMPORT_BOOKMARKS=true docker compose up -d --build +``` + +- `MENAV_PORT`:宿主机端口(默认 `8080`) +- `MENAV_ENABLE_SYNC`:是否在镜像构建时联网执行 `sync-*`(默认 `false`,更稳定) +- `MENAV_IMPORT_BOOKMARKS`:是否在镜像构建时执行 `npm run import-bookmarks`(默认 `false`) + +4. 更新站点: + - 修改配置或内容后,重新执行 `docker compose up -d --build` + +#### 方式二:直接使用 Docker 命令 + +```bash +docker build -t menav \ + --build-arg MENAV_ENABLE_SYNC=false \ + --build-arg MENAV_IMPORT_BOOKMARKS=false . + +docker run -d --name menav -p 8080:80 --restart unless-stopped menav +``` + +
+ ### 部署到服务器
@@ -483,7 +529,7 @@ server { index index.html; location / { - try_files $uri $uri/ /index.html; + try_files $uri $uri/ /404.html; } } ``` diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..5e151c2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +services: + menav: + container_name: menav + image: menav:latest + build: + context: . + dockerfile: Dockerfile + args: + MENAV_ENABLE_SYNC: ${MENAV_ENABLE_SYNC:-false} + MENAV_IMPORT_BOOKMARKS: ${MENAV_IMPORT_BOOKMARKS:-false} + ports: + - '${MENAV_PORT:-8080}:80' + restart: unless-stopped diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf new file mode 100644 index 0000000..c8e12e7 --- /dev/null +++ b/docker/nginx/default.conf @@ -0,0 +1,30 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + charset utf-8; + + location = / { + try_files /index.html =404; + add_header Cache-Control "no-store"; + } + + location ~* \.(?:css|js|mjs|json|ico|png|jpe?g|gif|svg|webp|txt|xml|map)$ { + try_files $uri =404; + access_log off; + add_header Cache-Control "public, max-age=3600"; + } + + location ~* \.html$ { + try_files $uri =404; + add_header Cache-Control "no-store"; + } + + location / { + try_files $uri $uri/ /404.html; + add_header Cache-Control "no-store"; + } +}