英文:
Networking a NextJS development server in docker
问题
我目前的设置是,我有一个在Docker Compose中以开发模式运行的NextJS应用,我们称之为"frontend"。
后端是一个ExpressJS应用,我们称之为"backend"。
在我的NextJS应用中有一个环境变量,它指定了后端的终端点,我可以将其设置为"http://backend:3000"或"http://localhost:3000"。根据我设置的终端点,NextJS会遇到一个问题(客户端与"服务器"端查询)。
有没有办法我可以从我的主机机器以及前端容器使用相同的"url"访问我的后端?
为了更清楚编辑:
version: "3.9"
services:
  frontend:
    image: node:18.14.2
    ports:
      - "8000:8000"
    volumes:
      - ./Frontend:/app
      #      - /app/node_modules/
      - /app/.next/
    environment:
      - NEXT_PUBLIC_BACKEND_BASE_URI=http://backend:3000
      - NEXT_PUBLIC_CMS_URL=http://cms:1337
    working_dir: /app
    command: sh -c "npm install --silent && npm run dev"
  frontend-graphql:
    image: node:18.14.2
    volumes:
      - ./Frontend:/app
      # - /app/node_modules/
      - /app/.next/
    environment:
      - NEXT_PUBLIC_BACKEND_BASE_URI=http://backend:3000
      - NEXT_PUBLIC_CMS_URL=http://cms:1337
    working_dir: /app
    command: sh -c "npm install --silent && npm run dev"
  backend:
    image: node:18.14.2
    ports:
      - "3000:3000"
    working_dir: /app
    volumes:
      - ./Backend:/app
    #      - /app/node_modules/
    command: sh -c "npm install && npm install -g ts-node && npm run dev"
  cms:
    image: node:18.14.2
    ports:
      - "1337:1337"
    working_dir: /app
    volumes:
      - ./CMS:/app
      - /app/node_modules/
    command: sh -c "npm install && npm install --platform=linux --arch=arm64v8 sharp && npm run dev"
以上是您提供的Docker Compose文件中的配置,无需翻译代码部分。
英文:
I currently have a setup where I have a NextJS app in development mode in a docker-compose lets call frontend.
The backend is an expressjs app lets call backend.
I have an environment variable in my NextJS app that specifies the backend endpoint which I can either set as http://backend:3000 or http://localhost:3000. Depending on which endpoint I set, NextJS runs into an issue (client vs "server" side querying).
Is there a way I can access my backend from my host machine as well as frontend container using the same "url"?
Edited for clairty
version: "3.9"
services:
  frontend:
    image: node:18.14.2
    ports:
      - "8000:8000"
    volumes:
      - ./Frontend:/app
      #      - /app/node_modules/
      - /app/.next/
    environment:
      - NEXT_PUBLIC_BACKEND_BASE_URI=http://backend:3000
      - NEXT_PUBLIC_CMS_URL=http://cms:1337
    working_dir: /app
    command: sh -c "npm install --silent && npm run dev"
  frontend-graphql:
    image: node:18.14.2
    volumes:
      - ./Frontend:/app
      # - /app/node_modules/
      - /app/.next/
    environment:
      - NEXT_PUBLIC_BACKEND_BASE_URI=http://backend:3000
      - NEXT_PUBLIC_CMS_URL=http://cms:1337
    working_dir: /app
    command: sh -c "npm install --silent && npm run dev"
  backend:
    image: node:18.14.2
    ports:
      - "3000:3000"
    working_dir: /app
    volumes:
      - ./Backend:/app
    #      - /app/node_modules/
    command: sh -c "npm install && npm install -g ts-node && npm run dev"
  cms:
    image: node:18.14.2
    ports:
      - "1337:1337"
    working_dir: /app
    volumes:
      - ./CMS:/app
      - /app/node_modules/
    command: sh -c "npm install && npm install --platform=linux --arch=arm64v8 sharp && npm run dev"
答案1
得分: 1
目前我找到的最佳解决方案是绕过 host.docker.internal 主机名的黑客手段。
如前所述,host.docker.internal 可以在 docker 容器内直接访问,但由于 nextjs 还需要从容器的“外部”(浏览器中)访问后端服务器,我在 /etc/hosts 中映射了
127.0.0.1 到 host.docker.internal
(在 Mac 和 Windows 上测试通过)。
这允许客户端请求访问 http://host.docker.internal:3000,使您能够使用与“服务器端查询”相同的主机名。
英文:
The best solution I have found so far was hacking around the host.docker.internal hostname.
As mentioned before, host.docker.internal can be accessed directly inside of a docker container but as nextjs also needs to access the backend server from "outside" the container (in the browser) I mapped
127.0.0.1 to host.docker.internal 
in /etc/hosts (tested on both mac and windows).
This allows the client-side requests to access http://host.docker.internal:3000, allowing you to use the same hostname as the "server-side-queries".
答案2
得分: 0
我找到了这个。看起来我们可以轻松设置服务器和公共运行时配置,但我担心它已经被弃用。不过,仍然可以设置服务器运行时配置。
- 在 
next.config.js中 
const nextConfig = {
  serverRuntimeConfig: {
    // 仅在服务器端可用
    apiUrl: process.env.NEXT_SERVER_API_URL || 'http://dockerbackend:8000'
  },
  publicRuntimeConfig: {
    // 在服务器和客户端都可用
    apiUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000'
  }
}
- 在 
@/config/index.ts中 
import getConfig from 'next/config';
const config = getConfig();
let apiUrl = process.env.NEXT_PUBLIC_API_URL;
if (config) {
  apiUrl = config?.serverRuntimeConfig?.apiUrl
}
export {
  apiUrl
}
- 在需要 API URL 的地方导入配置文件:
 
import { apiUrl } from '@/config';
英文:
I found this. It looks like we can easily set up server and public runtime configurations but I'm afraid it's been deprecated. Nevertheless, setting up server runtime configurations is still possible.
- In 
next.config.js 
const nextConfig = {
  serverRuntimeConfig: {
    // Will only be available on the server side
    apiUrl: process.env.NEXT_SERVER_API_URL || 'http://dockerbackend:8000'
  },
  publicRuntimeConfig: {
    // Will be available on both server and client
    apiUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000'
  }
}
- In 
@/config/index.ts 
import getConfig from 'next/config';
const config = getConfig();
let apiUrl = process.env.NEXT_PUBLIC_API_URL;
if (config) {
  apiUrl = config?.serverRuntimeConfig?.apiUrl
}
export {
  apiUrl
}
- Import the config file wherever you need the API URL:
 
import { apiUrl } from '@/config'
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论