# Go+Nextjs SSR standalone模式 github actions编译 + docker运行 示例 next.config.ts Dockerfile start.sh

**URL:** <https://www.sunai.net/t/topic/352>\
**Category:** IT\
**Tags:** github, standalone, docker, nextjs, go\
**Created:** [2025 年3 月 17 日 06:30 UTC](https://www.sunai.net/t/topic/352 "2025-03-17T06:30:41Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

作者： ![wood](https://www.sunai.net/user_avatar/www.sunai.net/wood/32/1032_2.png) [@wood](https://www.sunai.net/u/wood)\
发布日期： [2025 年3 月 17 日 06:30 UTC](https://www.sunai.net/t/topic/352/1 "2025-03-17T06:30:42Z")

</div>

> 主要区别是使用前端编译后的standalone目录, 在里面使用`node server.js`来运行, 会比`npm run start`更轻量

> 这基本上是一个缩小尺寸的 NextJS 服务器，它只包含它的动态部分。观察表明 node\_modules 仅占项目 node\_modules 的 5% 左右，这在尺寸上是显着减小的（在我们有限的测试中）

## 后端

正常打包

## 前端

### next.config.ts

```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

```dockerfile
# 最终运行镜像
FROM node:22-alpine AS runner

WORKDIR /app

# 安装必要的依赖
RUN apk add --no-cache libc6-compat tzdata

# 设置时区为中国标准时间
ENV TZ=Asia/Shanghai
  
# 复制GitHub Actions构建的Go后端
# 使用ARG指定架构，由buildx自动设置
ARG TARGETARCH
COPY vps-monitor-backend-${TARGETARCH} /app/backend/vps-monitor-backend
RUN chmod +x /app/backend/vps-monitor-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

# 创建数据目录并设置权限
RUN mkdir -p /app/data && chmod 777 /app/data
  
# 设置工作目录环境变量
# 删除PORT环境变量，让docker-compose.yml中的设置生效
ENV NODE_ENV=production
ENV GIN_MODE=release
ENV DATA_DIR=/app/data

# 以root用户运行
USER root

# 暴露端口
EXPOSE 3000 8080

# 启动应用
CMD ["/app/start.sh"]

```

## 启动脚本 start.sh

```sh
#!/bin/sh

# 确保时区设置正确
export TZ=Asia/Shanghai

# 创建数据目录
mkdir -p /app/data

# 设置数据目录权限为全局可写
chmod -R 777 /app/data
echo "设置数据目录权限："
ls -la /app/data

# 确保环境变量存在
PORT=${PORT:-8080}
NEXT_PORT=${NEXT_PORT:-3000}
echo "后端将使用端口: $PORT"
echo "前端将使用端口: $NEXT_PORT"

# 启动后端应用
cd /app/backend
export PORT=$PORT
./vps-monitor-backend &
BACKEND_PID=$!
echo "后端启动，PID: $BACKEND_PID"

# 启动Next.js应用
cd /app/frontend
export PORT=$NEXT_PORT
node server.js &
FRONTEND_PID=$!
echo "前端启动，PID: $FRONTEND_PID"

# 监听子进程，如果任何一个退出，则退出容器
wait $BACKEND_PID $FRONTEND_PID

```

## github actions示例

```yml
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
        # 编译x86_64版本
        CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -tags timetzdata -o vps-monitor-backend-amd64 .
        # 编译arm64版本
        CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-w -s" -tags timetzdata -o vps-monitor-backend-arm64 .

    - 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
        platforms: linux/amd64,linux/arm64
        tags: ${{ secrets.DOCKER_HUB_USERNAME }}/vps-monitor:latest
        # 添加构建参数
        build-args: |
          BUILD_DATE=${{ github.event.repository.updated_at }}
          VCS_REF=${{ github.sha }}
    - name: 部署到服务器
      uses: appleboy/ssh-action@master
      env:
        DOCKER_IMAGE: ${{ secrets.DOCKER_HUB_USERNAME }}/vps-monitor:latest
        PROJECT_PATH: ${{ secrets.PROJECT_PATH }}
      with:
        host: ${{ secrets.SERVER_IP }}
        username: root
        key: ${{ secrets.SERVER_SSH_KEY }}
        envs: DOCKER_IMAGE,PROJECT_PATH
        script: |
          docker pull $DOCKER_IMAGE
          cd $PROJECT_PATH
          docker compose down
          docker compose up -d

```
