简体   繁体   English

Nextjs + Docker-Compose:如何解析容器主机名客户端?

[英]Nextjs + Docker-Compose: how to resolve container hostname client-side?

New to Docker here. Docker 的新手在这里。 I've been experiencing a confusing roadblock with my Nextjs app, which is running in its own container alongside API and database containers.我的 Nextjs 应用程序遇到了一个令人困惑的障碍,该应用程序与 API 和数据库容器一起在自己的容器中运行。

My Nextjs app consumes data from the API container.我的 Nextjs 应用使用来自 API 容器的数据。 This works great server-side: the Nextjs app resolves the container hostname as it should.这在服务器端工作得很好:Nextjs 应用程序会按应有的方式解析容器主机名。 Client-side, however, the app breaks because the container hostname means nothing to the browser (I think?).但是,在客户端,应用程序会中断,因为容器主机名对浏览器没有任何意义(我认为?)。 I'm rather lost as to how I can handle this.我对如何处理这个问题感到很迷茫。 Ideas?想法?

Here's my Docker Compose file, in the case that it helps elucidate my question.这是我的 Docker 撰写文件,以帮助阐明我的问题。 Note that I'm passing the hostname to the Nextjs app via the environment field:请注意,我通过environment字段将主机名传递给 Nextjs 应用程序:

version: '3.8'

services:
    # Redis 
    redis:
        image: redis
        command: redis-server --requirepass ${REDIS_PASSWORD} --bind redis
        ports:
            - "6379:6379"
        networks:
            - mywebappio
    # Data Processing Service
    mywebapp-api:
        container_name: mywebapp-api
        restart: always
        build: 
            context: packages/dps-api
            dockerfile: Dockerfile
        command: npm run dev # npm start prod
        working_dir: /usr/src/dps-api
        env_file: 
            - .env
        volumes: 
            - ./packages/dps-api:/usr/src/dps-api
        ports:
            - "5000:5000"
        networks:
            - mywebappio
        depends_on:
            - redis
    # SSR 'client' app
    nextjs:
        container_name: mywebapp-client
        build:
            context: packages/next-server
            dockerfile: Dockerfile
        command: /bin/bash -c "./wait-for-it.sh mywebapp-api:5000 -- npm run build && npm run start"
        environment: 
            - NEXT_PUBLIC_API_BASE=mywebapp-api:5000
        volumes:
            - ./packages/next-server:/usr/src/app
        ports:
            - "3000:3000"
        networks:
            - mywebappio
        depends_on:
            - mywebapp-api
            - redis
networks:
    mywebappio:
        driver: bridge

Additional information:附加信息:

  • Using curl on my API, as "localhost:5000", works.在我的 API 上使用curl作为“localhost:5000”,可以工作。

  • In dev console, Nextjs app makes a call to "localhost:3000/" to fetch data server-side.在开发控制台中,Nextjs 应用程序调用“localhost:3000/”以获取服务器端数据。 This makes sense given how Nextjs works.考虑到 Nextjs 的工作原理,这是有道理的。

  • In dev console, Nextjs app makes call to "mywebapp-api:5000/" to fetch data client-side.在开发控制台中,Nextjs 应用程序调用“mywebapp-api:5000/”以在客户端获取数据。 Obviously, this doesn't work.显然,这是行不通的。

Okay so i found a solution/workaround.好的,所以我找到了解决方案/解决方法。 I was reading online and i found only 1 way.我在网上阅读,我发现只有一种方式。 And that's to setup reverse-proxy to nextjs server sth like this: Proxy to backend with default Next.js dev server .这就是将反向代理设置为 nextjs 服务器,如下所示: Proxy to backend with default Next.js dev server But i fixed it differently: so nextjs has 2 types of env variables, the ones that are exposed only to SERVER(BACKEND_URL=http://servicename:port) and ones that are exposed to SERVER AND CLIENT( NEXT_PUBLIC _BACKEND_URL=http://localhost:port) - here i define localhost so the browser can read the api.但我以不同的方式修复它:所以 nextjs 有 2 种 env 变量,那些只暴露给 SERVER(BACKEND_URL=http://servicename:port) 和那些暴露给 SERVER AND CLIENT( NEXT_PUBLIC _BACKEND_URL=http:/ /localhost:port) - 这里我定义了 localhost 以便浏览器可以读取 api。 And you only do this to setup axios:你只需要设置 axios:

import axios from 'axios';

const instance = axios.create({
  baseURL: process.env.BACKEND_URL || process.env.NEXT_PUBLIC_BACKEND_URL,
});

export default instance;

Now on client side it will use http://localhost:port and on SSR will use http://servicename:port.现在在客户端它将使用 http://localhost:port 而在 SSR 上将使用 http://servicename:port。

If you want to work in your computer(local environment), you can change the IP for the backend in next.config.js.如果您想在您的计算机(本地环境)中工作,您可以在 next.config.js 中更改后端的 IP。 For example if your computer has the IP 192.168.1.23 and the container for the backend is running in the port 3000, then you next.config.js must have the next:例如,如果您的计算机具有 IP 192.168.1.23 并且后端容器在端口 3000 中运行,那么您的 next.config.js 必须具有下一个:

  env: {
    backendUrl: 'http://192.168.1.23:3000/api/v1',
  },

Also for you axios configuration can look like the next:也为你 axios 配置可以如下所示:

import axios from 'axios';

const wrapperAxios = axios.create({
  baseURL: process.env.backendUrl,
  headers: { 'Content-type': 'application/json' },
});
export default wrapperAxios;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM