Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Next.js getServerSideProps is not working using docker

Currently, I am trying to fetch data after communicating with the backend server through SSR through Next.js and sprinkle it on the page.

However, one problem is that when I run npm run dev locally, getServerSideProps runs well, but when I upload it to a container through Docker-compose, my API for getServerSideProps doesn't work.

    const ResultMenu: NextPage<Props> = ({ CategoryData }) => {  
     ...
    };
    
    export default ResultMenu;
    
    export const getServerSideProps: GetServerSideProps = async (context) => {
      try {
        const { menuId } = context.query;
        const response = await axios.get<CategoryType[]>(
          "http://localhost:8080/category/get/menu",
          {
            headers: {
              "Content-Type": "application/json",
              "Access-Control-Allow-Origin": "*",
            },
            params: {
              menuId: menuId,
            },
          }
        );
        const data = response.data;
        console.log(data);
        return {
          props: {
            CategoryData: data,
          },
        };
      } catch (err) {
        console.log(err);
        return {
          props: {},
        };
      }
    };

In the frontend container, this error code appears

Error: connect ECONNREFUSED 127.0.0.1:8080

    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1195:16) {

  errno: -111,

  code: 'ECONNREFUSED',

  syscall: 'connect',

  address: '127.0.0.1',

  port: 8080,

  config: {

    transitional: {

      silentJSONParsing: true,

      forcedJSONParsing: true,

      clarifyTimeoutError: false

    },

    adapter: [Function: httpAdapter],

    transformRequest: [ [Function: transformRequest] ],

    transformResponse: [ [Function: transformResponse] ],

    timeout: 0,

    xsrfCookieName: 'XSRF-TOKEN',

    xsrfHeaderName: 'X-XSRF-TOKEN',

    maxContentLength: -1,

    maxBodyLength: -1,

    validateStatus: [Function: validateStatus],

    headers: {

      Accept: 'application/json, text/plain, */*',

      'Content-Type': 'application/json',

      'Access-Control-Allow-Origin': '*',

      'User-Agent': 'axios/0.26.1'

    },

    params: { menuId: '1' },

    method: 'get',

    url: 'http://localhost:8080/category/get/menu',

    data: undefined

  },

  request: <ref *1> Writable {

    _writableState: WritableState {

      objectMode: false,

      highWaterMark: 16384,

      finalCalled: false,

      needDrain: false,

      ending: false,

      ended: false,

      finished: false,

      destroyed: false,

      decodeStrings: true,

      defaultEncoding: 'utf8',

      length: 0,

      writing: false,

      corked: 0,

      sync: true,

      bufferProcessing: false,

      onwrite: [Function: bound onwrite],

      writecb: null,

      writelen: 0,

      afterWriteTickInfo: null,

      buffered: [],

      bufferedIndex: 0,

      allBuffers: true,

      allNoop: true,

      pendingcb: 0,

      constructed: true,

      prefinished: false,

      errorEmitted: false,

      emitClose: true,

      autoDestroy: true,

      errored: null,

      closed: false,

      closeEmitted: false,

      [Symbol(kOnFinished)]: []

    },

    _events: [Object: null prototype] {

      response: [Function: handleResponse],

      error: [Function: handleRequestError],

      socket: [Function: handleRequestSocket]

    },

    _eventsCount: 3,

    _maxListeners: undefined,

    _options: {

      maxRedirects: 21,

      maxBodyLength: 10485760,

      protocol: 'http:',

      path: '/category/get/menu?menuId=1',

      method: 'GET',

      headers: [Object],

      agent: undefined,

      agents: [Object],

      auth: undefined,

      hostname: 'localhost',

      port: '8080',

      nativeProtocols: [Object],

      pathname: '/category/get/menu',

      search: '?menuId=1'

    },

    _ended: true,

    _ending: true,

    _redirectCount: 0,

    _redirects: [],

    _requestBodyLength: 0,

    _requestBodyBuffers: [],

    _onNativeResponse: [Function (anonymous)],

    _currentRequest: ClientRequest {

      _events: [Object: null prototype],

      _eventsCount: 7,

      _maxListeners: undefined,

      outputData: [],

      outputSize: 0,

      writable: true,

      destroyed: false,

      _last: true,

      chunkedEncoding: false,

      shouldKeepAlive: false,

      maxRequestsOnConnectionReached: false,

      _defaultKeepAlive: true,

      useChunkedEncodingByDefault: false,

      sendDate: false,

      _removedConnection: false,

      _removedContLen: false,

      _removedTE: false,

      _contentLength: 0,

      _hasBody: true,

      _trailer: '',

      finished: true,

      _headerSent: true,

      _closed: false,

      socket: [Socket],

      _header: 'GET /category/get/menu?menuId=1 HTTP/1.1\r\n' +

        'Accept: application/json, text/plain, */*\r\n' +

        'Content-Type: application/json\r\n' +

        'Access-Control-Allow-Origin: *\r\n' +

        'User-Agent: axios/0.26.1\r\n' +

        'Host: localhost:8080\r\n' +

        'Connection: close\r\n' +

        '\r\n',

      _keepAliveTimeout: 0,

      _onPendingData: [Function: nop],

      agent: [Agent],

      socketPath: undefined,

      method: 'GET',

      maxHeaderSize: undefined,

      insecureHTTPParser: undefined,

      path: '/category/get/menu?menuId=1',

      _ended: false,

      res: null,

      aborted: false,

      timeoutCb: null,

      upgradeOrConnect: false,

      parser: null,

      maxHeadersCount: null,

      reusedSocket: false,

      host: 'localhost',

      protocol: 'http:',

      _redirectable: [Circular *1],

      [Symbol(kCapture)]: false,

      [Symbol(kNeedDrain)]: false,

      [Symbol(corked)]: 0,

      [Symbol(kOutHeaders)]: [Object: null prototype]

    },

    _currentUrl: 'http://localhost:8080/category/get/menu?menuId=1',

    [Symbol(kCapture)]: false

  },

  response: undefined,

  isAxiosError: true,

  toJSON: [Function: toJSON]

}

1

undefined

Dockerfile

FROM node:12

ENV PORT 3000

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Installing dependencies
COPY package*.json /usr/src/app/
RUN npm install

# Copying source files
COPY . /usr/src/app

# Building app
RUN npm run build
EXPOSE 3000

# Running the app
CMD "npm" "run" "dev"

docker-compose.yml

version: "3"

services:
  frontend:
    container_name: frontend
    build:
      context: ./frontend
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    volumes:
      - ./frontend:/usr/src/app
      - /usr/src/app/node_modules
      - /usr/src/app/.next
    networks:
      - network-tier
      
  backend:
    container_name: backend
    build: ./backend
    depends_on:
      - mysqldb
    ports:
      - 8080:8080
    environment:
      spring.datasource.url: "jdbc:mysql://mysqldb:3306/test_db?useSSL=false&useLegacyDatetimeCode=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&characterEncoding=UTF-8&autoReconnect=true&createDatabaseIfNotExist=true"
    volumes:
      - ./menu-canvas:/usr/src/backend
    networks:
      - network-tier
    tty: true

  mysqldb:
    image: mysql:5.7
    container_name: mysqldb
    environment:
      MYSQL_DATABASE: test_db
      MYSQL_ROOT_PASSWORD: "0000"
      MYSQL_ROOT_HOST: "%"
      CHARACTER_SET_SERVER: utf8
    command:
      [
        "--character-set-server=utf8mb4",
        "--collation-server=utf8mb4_unicode_ci",
      ]
    volumes:
      - ./menu-canvas:/usr/src/db
    ports:
      - "3306:3306"

    networks:
      - network-tier
    platform: linux/amd64

networks:
  network-tier:
    external: true

volumes:
  menu-canvas:

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    domains: ["localhost", "*"],
  },
  reactStrictMode: true,
};

module.exports = nextConfig;

package.json

{
  "name": "frontend",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
 ...
  },
  "devDependencies": {
 ...
  },
  "proxy": {
    "*": {
      "target": "http://localhost:8080"
    }
  }
}

I've been thinking a lot all day, but I don't know how... Help!

like image 805
kenma Avatar asked Feb 16 '26 07:02

kenma


1 Answers

When running the getServerSideProps the communication would be container to container. So for these requests, routes to localhost would not work. Instead it would need to be something like backend:8080 (when communicating from the frontend service to the backend service).

The localhost domain would work as expected on the client side requests assuming you were exposing all ports as expected.

When you run this without docker everything works because all services are on localhost. When run via docker-compose they no longer are.

If you really wanted to use localhost instead of the service name you may be able to use a network host https://docs.docker.com/network/host/

like image 199
Redeyes10 Avatar answered Feb 18 '26 21:02

Redeyes10