当我在本地运行该应用程序时,该应用程序可以正常工作,但如果我尝试对其进行 dockerize,则会收到
500 fetch failed
错误,并且没有日志。我还尝试使用 node --trace-warnings
运行应用程序,但没有出现错误。该项目是一个pnpm
monorepo,文件夹结构是
apps
│
├── backend
│ ├── Dockerfile
│ └── package.json
│
├── frontend
│ ├── Dockerfile
| ├── nuxt.config.ts
│ └── package.json
│
├── docker-compose.yaml
├── package.json
├── pnpm-lock.yaml
└── pnpm-workspace.yaml
这里是
apps/frontend/Dockerfile
###################
# STAGE 1: BUILD
###################
FROM node:20-alpine AS build
# Set working directory inside the image
WORKDIR /app
# Copy application dependency manifests to the container image.
COPY --chown=node:node ./package.json ./pnpm-lock.yaml ./pnpm-workspace.yaml ./
COPY --chown=node:node ./apps/frontend/package.json ./apps/frontend/package.json
# Install pnpm globally
RUN npm install -g pnpm
# Install app dependencies using the `pnpm install --frozen-lockfile`
RUN pnpm install --frozen-lockfile
# Bundle app source
COPY --chown=node:node ./apps/frontend ./apps/frontend/
# Build the Nuxt.js application
RUN pnpm --filter=@myapp/frontend build
# Use the node user from the image (instead of the root user)
USER node
###################
# STAGE 2: PRODUCTION
###################
FROM node:20-alpine AS production
# Set working directory inside the image
WORKDIR /app
# Copy compiled static files from the build stage (Stage 1)
COPY --chown=node:node --from=build /app/apps/frontend/.output/ ./
# Port and host for the nitro
ENV NITRO_HOST=0.0.0.0
ENV NITRO_PORT=3000
# Expose the port the app runs on
EXPOSE 3000
# Use the node user from the image (instead of the root user)
USER node
# Default command to start Nuxt
CMD [ "node", "/app/server/index.mjs" ]
这里是
docker-compose.yaml
version: '3.8'
services:
frontend:
container_name: frontend
build:
context: .
dockerfile: apps/frontend/Dockerfile
ports:
- '3000:3000'
networks:
- mynetwork
depends_on:
- backend
backend:
container_name: backend
build:
context: .
dockerfile: apps/backend/Dockerfile
ports:
- '3001:3001'
depends_on:
- db
networks:
- mynetwork
environment:
- POSTGRES_HOST=postgres
- POSTGRES_PORT=5432
- POSTGRES_USERNAME=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_DATABASE=database
- SERVER_ADDRESS=0.0.0.0
- SERVER_PORT=3001
db:
container_name: postgres
image: postgres:13
ports:
- '5432:5432'
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: database
networks:
- mynetwork
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
networks:
mynetwork:
driver: bridge
这里是
nuxt.config.ts
export default defineNuxtConfig({
devtools: { enabled: true },
modules: [
"@nuxtjs/apollo",
"@nuxtjs/tailwindcss",
"@nuxtjs/color-mode",
"@nuxt/icon",
"@element-plus/nuxt",
"@nuxt/image",
],
plugins: [{ src: "~/plugins/vue-toastification.ts", mode: "client" }],
apollo: {
clients: {
default: {
httpEndpoint: `${ process.env.SERVER_URL ?? "http://127.0.0.1:3001/graphql"}`,
inMemoryCacheOptions: {
addTypename: false,
},
defaultOptions: {
watchQuery: {
fetchPolicy: "no-cache",
},
query: {
fetchPolicy: "no-cache",
},
},
},
},
},
css: ["@fontsource-variable/inter/index.css"],
});
我还尝试使用
frontend
服务容器的名称设置 SERVER_URL
服务环境变量 backend
,但我仍然遇到相同的错误。
services:
frontend:
container_name: frontend
build:
context: .
dockerfile: apps/frontend/Dockerfile
ports:
- '3000:3000'
networks:
- mynetwork
depends_on:
- backend
environment:
- SERVER_URL=backend:3001/graphql
backend:
container_name: backend
build:
context: .
dockerfile: apps/backend/Dockerfile
最后我发现了问题:需要在
nuxt.config.js
中为GraphQL设置两个不同的URL,一个用于服务器端,一个用于Nuxt中的客户端,让服务器端URL指向容器,而客户端 URL 指向容器公开的 URL。
这是更新后的 nuxt.config.js,我们在其中定义了
httpEndpoint
(针对服务器端)和 browserHttpEndpoint
(针对客户端):
export default defineNuxtConfig({
...
apollo: {
clients: {
default: {
httpEndpoint: `${ process.env.SERVER_URL ?? "http://127.0.0.1:3001/graphql"}`,
browserHttpEndpoint: "http://127.0.0.1:3001/graphql",
},
},
},
...
});
这是更新后的
docker-compose.yaml
,我们在其中传递 Nuxt.js 项目构建阶段使用的参数 SERVER_URL
。
services:
frontend:
container_name: frontend
build:
context: .
dockerfile: apps/frontend/Dockerfile
args:
- SERVER_URL=http://backend:3001/graphql
ports:
- '3000:3000'
networks:
- mynetwork
depends_on:
- backend
在Nuxt.js项目的
Dockerfile
中,我们需要在构建阶段添加环境变量SERVER_URL
,然后再运行构建命令
....
# Custom server URL
ARG SERVER_URL
ENV SERVER_URL=$SERVER_URL
# Build the Nuxt.js application
RUN pnpm --filter=@weroad/frontend build
....