Nextjs + Prisma/postgres + Docker 不会显示layout.tsx 子页面

问题描述 投票:0回答:1

我有一个 docker 设置,其中一个容器中有一个 nextjs 应用程序,另一个容器中有一个 postgres 数据库,使用 prisma 作为 ORM。容器启动正常,我可以在 localhost:3000 上访问我的 nextjs 应用程序,但没有显示 layout.tsx 或根 page.tsx 中的内容?我也在这些文件中放入了一些日志,但没有看到任何输出。

我相信这是连接到数据库的一些问题,因为我可以在我的开发设置中重现这个问题,只需设置不正确的 postgres .env 变量。在开发过程中,我使用 Neon 作为远程数据库,但我想继续生产,我想要在容器中使用本地 postgres 数据库,这就是问题开始的地方。切换回 Neon 连接变量,站点按预期正常加载。

我可以使用 pgadmin 服务访问数据库,并且可以连接到数据库服务,我可以看到那里的所有表,但是它们是空的,因为该网站不会加载正文内容。

我可以成功地在容器之间执行 ping 操作,因此它们必须以某种方式进行通信。使用 docker dekstop 界面并使用 nextjs-app logobrewer 中的终端:

/app $ ping postgres_db
PING postgres_db (172.31.0.2): 56 data bytes
64 bytes from 172.31.0.2: seq=0 ttl=42 time=0.038 ms
64 bytes from 172.31.0.2: seq=1 ttl=42 time=0.053 ms

.env

DATABASE_URL=postgres://postgres:password@postgres_db:5432/logobrewer?schema=public
PGHOST=postgres_db
PGDATABASE=logobrewer
PGUSER=postgres
PGPASSWORD=password

Docker-compose.yml(Ravis 评论后编辑)

version: '3.8'

services:
  postgres_db:
    image: postgres:15
    container_name: postgres_db
    restart: always
    environment:
      POSTGRES_DB: $PGDATABASE
      POSTGRES_USER: $PGUSER
      POSTGRES_PASSWORD: $PGPASSWORD
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
    - app_network

  app:
    container_name: logobrewer
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
      - "5555:5555"
    environment:
      NODE_ENV: production
      DATABASE_URL: postgres://postgres:password@postgres_db:5432/logobrewer?schema=public
    volumes:
      - F:\React\LogoAi\logo-ai\logs:/logs
    command: >
      sh -c "
      until pg_isready -h postgres_db -p 5432 -U postgres; do
        echo 'Waiting for Postgres...';
        sleep 2;
      done;
      npx prisma migrate deploy && node server.js"
    depends_on: 
      postgres_db: 
        condition: service_healthy
    networks:
    - app_network

  pgadmin:
    image: dpage/pgadmin4
    container_name: pgadmin4_container
    restart: always
    ports:
      - "8888:80"
    environment:
      PGADMIN_DEFAULT_EMAIL: [email protected]
      PGADMIN_DEFAULT_PASSWORD: 1234
    volumes:
      - pgadmin_data:/var/lib/pgadmin
    depends_on:
      - postgres_db
    networks:
      - app_network
       
volumes:
 postgres_data:
 pgadmin_data:

networks:
  app_network:
    driver: bridge

schema.prisma:

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
  provider      = "prisma-client-js"
  binaryTargets = ["native", "debian-openssl-1.1.x", "debian-openssl-3.0.x", "linux-musl", "linux-musl-openssl-3.0.x", "linux-musl-arm64-openssl-1.1.x"]
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Product {
  id              String  @id @default(cuid())
  name            String
  description     String?
  stripeProductId String
  type            String
  orders          Order[] // Establishes a one-to-many relationship with Order
}

Dockerfile:

FROM node:18.18-alpine AS deps

WORKDIR /app

RUN apk add --no-cache \
    libc6-compat \
    cairo-dev \
    pango-dev \
    cairo-tools \
    giflib-dev \
    pixman-dev \
    libjpeg-turbo-dev \
    build-base \
    python3 \
    make \
    g++ \
    bash \
    pkgconfig \
    wget \
    && ln -sf /usr/bin/python3 /usr/bin/python

COPY package.json package-lock.json* ./ 
RUN \
    if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
    elif [ -f package-lock.json ]; then npm ci; \
    elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
    else echo "Lockfile not found." && exit 1; \
    fi

# Force canvas installation if it has issues
RUN npm install canvas --build-from-source --legacy-peer-deps

# Rebuild the source code only when needed
FROM deps AS builder

WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

RUN npx prisma generate
RUN npm run build

# Production image, copy all the files and run Next.js
FROM builder AS runner
WORKDIR /app

# Install Cairo runtime libraries (needed for canvas)
RUN apk add --no-cache \
    cairo \
    pango \
    fontconfig \
    libc6-compat  # Sometimes required for compatibility in Alpine

# Set environment variables
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
ENV HOME=/home/nextjs

# Create and configure non-root user
RUN addgroup -S nodejs && adduser -S -G nodejs -u 1001 -D -h /home/nextjs nextjs \
    && mkdir -p /home/nextjs \
    && chown -R nextjs:nodejs /home/nextjs

# Create and set permissions for the /logs directory
RUN mkdir -p /logs && chown nextjs:nodejs /logs

# Copy necessary files from builder stage
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next ./app/.next
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ 
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --from=builder --chown=nextjs:nodejs /app/prisma ./prisma

# Set ownership for the app directory
RUN chown -R nextjs:nodejs /app

#Use this to specify which folders instead of above which takes all the files
#RUN chown -R nextjs:nodejs /app/.next /app/public /app/prisma

# Use non-root user
USER nextjs

# Expose port and start the server
EXPOSE 3000

CMD ["node", "server.js"]

因此,在开发(本地启动应用程序 npm run dev)中使用 Neon 连接变量,效果很好。但现在切换到在同一 Docker 网络中的容器中并行运行的本地数据库,问题就开始了。

我相信我已经尝试了多种解决方案,例如重写 docker-compose、dockerfile、docker 网络配置。

编辑:经过更多思考,问题可能是在构建 docker 映像时我的 dockerfile 收到如下警告:

Invalid `prisma.generation.findFirst()` invocation:


Can't reach database server at `postgres_db:5432`

Please make sure your database server is running at `postgres_db:5432`. PrismaClientInitializationError: 
Invalid `prisma.generation.findFirst()` invocation:


Can't reach database server at `postgres_db:5432`

Please make sure your database server is running at `postgres_db:5432`.
    at qn.handleRequestError (F:\React\LogoAi\logo-ai\node_modules\@prisma\client\runtime\library.js:121:7615)


稍后将图像旋转到容器时会导致问题吗?

此外,我尝试使用 Postman 到达代码中的 api 端点,这会进行如下数据库查找:

export async function GET() {
    try {
        const getUserSession = await prisma.session.findFirst();

        if (getUserSession) {
            return NextResponse.json(getUserSession);
        }
}

我实际上从数据库中获取数据。那么我认为应用程序需要有连接吗?这太奇怪了。

由于某种原因,应用程序仍然不加载layout.tsx子项,但导航栏和页脚已加载。这是布局页面,我在其中进行了一些调试,但它们从未显示任何输出:

import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import SessionProvider from "./components/SessionProvider";
import CookieConsentBanner from "./components/CookieConsentBanner";
import Register from "./components/Register";
import { Toaster } from "react-hot-toast";
import Footer from "./components/Footer";
import logger from "@/utils/logger";
import Nav from "./components/Nav";
import { log } from "console";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "LogoBrewer",
  description: "Generated by create next app",
};

export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {

  try {

    console.log("RootLayout");
    logger.info("RootLayout");

    return (
      <html lang="en" className="bg-base-100 min-h-screen ">
        <SessionProvider>
          <body className={`${inter.className} min-h-screen flex flex-col`}>
            {/* only appears if user hasnt registered */}
            <Register />

            <Nav />
            <div className="flex justify-center">
              <Toaster
                position="bottom-center"
                toastOptions={{
                  duration: 5000,
                  style: {
                    padding: "1em",
                  },
                }}
              />
              {children}
              <CookieConsentBanner />
            </div>
            <Footer />
          </body>
        </SessionProvider>
      </html>
    );
  } catch (error) {
    logger.error(error);
  }
}

postgresql docker prisma
1个回答
0
投票

Prisma 依赖

DATABASE_URL
进行连接,如果数据库尚未准备好,迁移和后续查询将失败。

  1. 添加等待数据库逻辑: 确保数据库在 Next.js 应用程序启动之前准备就绪。更新
    command
    中的
    docker-compose.yml
    command: >
      sh -c "
      until pg_isready -h postgres_db -p 5432 -U postgres; do
        echo 'Waiting for Postgres...';
        sleep 2;
      done;
      npx prisma migrate deploy && node server.js"
    
    

调整depends_on:虽然depends_on确保启动顺序,但它不会等待准备就绪。使用适当的健康检查,您已经对 postgres_db 进行了检查。

重建容器:确保应用所有更改:

docker-compose down -v
docker-compose up --build
© www.soinside.com 2019 - 2024. All rights reserved.