主要区别是使用前端编译后的standalone目录, 在里面使用
node server.js
来运行, 会比npm run start
更轻量
这基本上是一个缩小尺寸的 NextJS 服务器,它只包含它的动态部分。观察表明 node_modules 仅占项目 node_modules 的 5% 左右,这在尺寸上是显着减小的(在我们有限的测试中)
后端
正常打包
前端
next.config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
rewrites: async () => [
{
source: "/api/:path*",
destination: "http://localhost:8080/api/:path*",
},
],
// 使用 standalone 模式替代静态导出
output: "standalone",
// output: "export",
// distDir: "out",
typescript: {
ignoreBuildErrors: true
},
eslint: {
ignoreDuringBuilds: true
}
};
export default nextConfig;
Dockerfile
# 最终运行镜像
FROM node:22-alpine AS runner
WORKDIR /app
# 安装必要的依赖
RUN apk add --no-cache libc6-compat tzdata
# 设置时区为中国标准时间
ENV TZ=Asia/Shanghai
# 复制GitHub Actions构建的Go后端
COPY czlconnect-backend /app/backend/
# 复制Next.js standalone构建结果
COPY web/.next/standalone /app/frontend/
COPY web/.next/static /app/frontend/.next/static
COPY web/public /app/frontend/public
# 添加启动脚本
COPY scripts/start.sh /app/
RUN chmod +x /app/start.sh
# 设置工作目录环境变量
ENV PORT=3000
ENV NODE_ENV=production
ENV GIN_MODE=release
# 设置用户
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
RUN chown -R nextjs:nodejs /app/frontend
USER nextjs
# 暴露端口
EXPOSE 3000 8080
# 启动应用
CMD ["/app/start.sh"]
启动脚本 start.sh
#!/bin/sh
# 确保时区设置正确
export TZ=Asia/Shanghai
# 启动后端应用
cd /app/backend
./czlconnect-backend &
# 启动Next.js应用
cd /app/frontend
# 在standalone模式下,不需要npm install和npm run build
# 直接用node启动server.js
node server.js
# 不需要额外的保持容器运行的逻辑,因为node进程会保持运行
# 如果node进程退出,容器也会退出,Docker可以重启容器
github actions示例
name: 构建并推送Docker镜像
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置Go环境
uses: actions/setup-go@v5
with:
go-version: '1.23'
- name: 设置Node.js环境
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- name: 构建后端
run: |
go mod download
# 添加CGO_ENABLED=0确保静态编译,添加时区数据
CGO_ENABLED=0 go build -ldflags="-w -s" -tags timetzdata -o czlconnect-backend .
- name: 构建前端
run: |
cd web
# 安装依赖并构建(使用standalone模式)
npm ci
npm run build
# 检查standalone构建文件是否生成成功
if [ ! -d ".next/standalone" ]; then
echo "Next.js standalone构建失败,缺少standalone目录"
exit 1
fi
- name: 设置Docker Buildx
uses: docker/setup-buildx-action@v3
- name: 登录到Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: 构建并推送Docker镜像
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/czlconnect:latest
# 添加构建参数
build-args: |
BUILD_DATE=${{ github.event.repository.updated_at }}
VCS_REF=${{ github.sha }}
评论区