这个网站现在怎样用 Docker 跑起来
按当前仓库梳理 Next.js 前台、独立管理端、Nginx 和持久化数据的部署关系。
这个网站已经不是把 out 目录交给 Nginx 就能结束的静态站。文章详情可以从 MDX 生成,但留言、评论、媒体上传、健康检查和备份等功能依赖 Next.js 的 Node.js 运行时。因此目前的部署核心,是让前台应用真正作为一个服务运行。
仓库里的 docker-compose.yml 管理两个应用:面向访客的博客和独立的管理端。博客容器内部监听 80 端口,对宿主机映射为 3000;管理端映射为 3001。生产环境再由宿主机上的 Nginx 根据域名把请求转发到对应端口。
为什么 Dockerfile 分成两段
前台 Dockerfile 使用 Node 20 Alpine,并把构建和运行拆开。
构建阶段先执行完整的 npm ci,因为 next build 还需要 TypeScript、Tailwind 等开发依赖。运行阶段重新安装生产依赖,只复制 .next、public、data 和 content 等运行所需文件。这样不会把整个源码目录和构建工具都带进最终镜像。
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
CMD ["npm", "run", "start"]上面只保留了结构,实际仓库还会复制内容数据并设置健康检查。构建参数和运行时密钥也不是一回事:以 NEXT_PUBLIC_ 开头的配置可能进入浏览器包,service role、R2 密钥和备份密钥则只能留在服务端环境中。
有一份数据不能困在容器里
应用仍保留 data-store 作为本地内容存储和降级方案。Compose 把宿主机的 ./data-store 挂载到容器内 /app/data-store。如果漏掉这个 volume,重建容器后写入容器层的数据就可能丢失。
Supabase 和 R2 也不能代替备份。数据库、对象存储、本地快照各自保存不同内容,至少要定期确认备份能被下载和读回,而不是只看定时任务显示成功。
更新时不只是一句 docker compose up
我的部署检查顺序更接近下面这样:
docker compose build
docker compose up -d
docker compose ps
curl --fail https://050906.xyz/api/health更新前还应该保存当前可回退的镜像或发布包,并备份持久化目录。启动成功只说明进程在运行;首页、文章页、管理端登录和上传链路是否正常,仍需要单独验证。
Nginx 负责 TLS、域名跳转、转发头和静态资源缓存。证书怎样申请取决于服务器环境,不需要为了“自动化”就一定换掉现有反向代理。对个人站而言,配置清楚、能回滚、出问题时容易定位,比把组件数量堆得更多重要。
Docker 解决的是环境一致性,不会自动解决密钥管理、数据持久化和上线验证。把这些边界写进仓库和部署文档,才是这套部署方式真正省心的地方。