我的 docker-compose 配置文件有问题。我的目标是使用 docker-compose 文件运行 Next.js 应用程序并启用热重载。
从 Dockerfile 运行 Next.js 应用程序可以工作,但热重载不起作用。 从 docker-compose 文件运行 Next.js 应用程序会触发错误:
/bin/sh: next: not found
,我无法弄清楚出了什么问题......
Dockerfile
:(取自 Next.js 的文档网站)[但请注意,这是一个多阶段构建,我仅引用 docker-compose 文件中的
builder
阶段。]
# Install dependencies only when needed
FROM node:18-alpine AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install # --frozen-lockfile
# Rebuild the source code only when needed
FROM node:18-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
ENV NEXT_TELEMETRY_DISABLED 1
RUN yarn build
# If using npm comment out above and use below instead
# RUN npm run build
# Production image, copy all the files and run next
FROM node:18-alpine AS runner
WORKDIR /app
ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# You only need to copy next.config.js if you are NOT using the default configuration
# COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3001
ENV PORT 3001
CMD ["node", "server.js"]
docker-compose.yml
:version: "3.9"
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${POSTGRESQL_PASSWORD}
backend:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
environment:
DATABASE_USERNAME: ${MYAPP_DATABASE_USERNAME}
DATABASE_PASSWORD: ${POSTGRESQL_PASSWORD}
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
target: builder
command: yarn dev
volumes:
- ./frontend:/app
expose:
- "3001"
ports:
- "3001:3001"
depends_on:
- backend
environment:
FRONTEND_BUILD: ${FRONTEND_BUILD}
PORT: 3001
package.json
:{
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "latest",
"react": "^18.1.0",
"react-dom": "^18.1.0"
}
}
当从
yarn dev
调用 docker-compose.yml
时,它实际上调用 next dev
,这就是它触发错误 /bin/sh: next: not found
的时候。但是,直接从 Dockerfile
运行容器是可行的,不会导致此错误。
如果我从
volume
文件中删除 docker-compse.yml
属性,我不会收到 /bin/sh: next: not found
错误,并且容器会运行,但是,我现在没有获得我正在寻找的热重载功能。知道为什么音量会与 /bin/sh next
命令混淆吗?
发生这种情况是因为您的本地文件系统正在安装在 docker 容器中的文件系统上。您的 docker 容器确实在
builder
阶段构建了节点模块,但我猜您的本地文件系统中没有可用的节点模块。
要查看是否发生了这种情况,在本地文件系统上,您可以执行
yarn install
。然后再次尝试通过 docker 运行容器。我预测这会起作用,因为 yarn
将在本地安装 next
,并且它实际上是将在 docker 容器中运行的本地文件系统的节点模块。
解决此问题的一种方法是卷安装除节点模块文件夹之外的所有内容。有关如何执行此操作的详细信息:向 Docker 添加卷,但排除子文件夹 因此,就您而言,我相信您可以在撰写文件中添加一行:
frontend:
...
volumes:
- ./frontend:/app
- ./frontend/node_modules # <-- try adding this!
...
这应该允许 docker 容器的
node_modules
不会被任何卷挂载覆盖。您还可以将其解析为
frontend:
...
volumes:
- ./frontend:/app
- /app/node_modules # <-- creates the node_modules in frontend path
- /app/.next # <-- creates the .next folder in frontend path
...
如果您在 .dockerignore
条目,请将其删除并尝试解决我的问题。
并更新此cmd 来自=> CMD [“节点”,“server.js”] => CMD [“npm”,“运行”,“dev”]