'Strapi + Next.JS + docker-compose: Is static generation impossible during build?

When I try to build my Next.JS application, which has a getStaticProps() function to get data from Strapi, the fetch fails. It fails because it is unable to resolve the alias for the Strapi container while building. Is there a way around this? Here's some info. Let me know if more info would be helpful:

Docker version 20.10.14

docker-compose version 1.29.2

Next.JS version 12.1.0

Node.JS version v17.6.0

In my pages/index.tsx file, I have the following:

export async function getStaticProps() {
  let data: PageData = null;

  try {
    const response = await axios.get(
      `${process.env.STRAPI_BACKEND_URL}/api/pages?filters[slug]=strapi-sample-homepage-content`,
      {
        headers: {
          Accept: "application/json",
        },
        timeout: 500,
      }
    );

    data = response.data.data[0].attributes || null;
  } catch (error) {
    console.log(error);
  }

  return {
    props: {
      data,
    },
    revalidate: 60,
  };
}  

This is what Next.JS wants to generate statically while building, and it's unable to because it cannot resolve the location of the Strapi container during build.

docker-compose.yml:

version: '3.8'
services:

  db-strapi:
    image: 'location/of/image'
    container_name: db-strapi
    restart: always
    volumes:
      - db-strapi:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=${STRAPI_DB_NAME}
      - POSTGRES_PASSWORD=${STRAPI_DB_PW}
      - POSTGRES_SCHEMA=${STRAPI_DB_SCHEMA}
      - POSTGRES_USER=${STRAPI_DB_USER}

  strapi-backend:
    image: 'location/of/image'
    container_name: strapi-backend
    environment:
      - ADMIN_JWT_SECRET=${STRAPI_ADMIN_JWT_SECRET}
      - API_TOKEN_SALT=${STRAPI_API_TOKEN_SALT}
      - APP_KEYS=${STRAPI_APP_KEYS}
      - DATABASE_CLIENT=${STRAPI_DB_CLIENT}
      - DATABASE_HOST=${STRAPI_DB_HOST}
      - DATABASE_NAME=${STRAPI_DB_NAME}
      - DATABASE_PASSWORD=${STRAPI_DB_PW}
      - DATABASE_PORT=${STRAPI_DB_PORT}
      - DATABASE_SCHEMA=${STRAPI_DB_SCHEMA}
      - DATABASE_USERNAME=${STRAPI_DB_USER}
      - JWT_SECRET=${STRAPI_JWT_SECRET}
      - NODE_ENV=${STRAPI_NODE_ENV}
    ports:
      - 1337:1337
    depends_on:
      - "db-strapi"

  db-nextjs:
    image: 'location/of/image'
    container_name: db-nextjs
    restart: always
    volumes:
      - db-nextjs:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=${NEXTJS_DB_NAME}
      - POSTGRES_PASSWORD=${NEXTJS_DB_PW}
      - POSTGRES_SCHEMA=${NEXTJS_DB_SCHEMA}
      - POSTGRES_USER=${NEXTJS_DB_USER}

  nextjs-app:
    image: 'location/of/image'
    container_name: nextjs-app
    environment:
      - STRAPI_BACKEND_URL
      - NEXTJS_DB_URL
      - SECRET_COOKIE_PASSWORD
      - NEXT_TELEMETRY_DISABLED=1
    restart: always
    depends_on:
      - "db-nextjs"

  nginx:
    image: 'location/of/image'
    container_name: nginx
    environment:
      - NGINX_SERVER_NAME
      - NGINX_STRAPI_SERVER_NAME=${STRAPI_BACKEND_HOST}
      - RESOLVER
      - ENVIRONMENT
      - NGINX_CERTIFICATE_NAME
      - NEXTJS_HOST
      - STRAPI_HOST
    ports:
      - 80:80
      - 443:443
    restart: always
    depends_on:
      - "nextjs-app"
      - "strapi-backend"
    volumes:
      - certbot_certificates:/etc/letsencrypt
      - certbot_challenges:/usr/share/nginx/html/.well-known/acme-challenge

volumes:
  db-strapi:
  db-nextjs:
  certbot_certificates:
  certbot_challenges:  

In my .env.local file:

STRAPI_BACKEND_HOST="strapi-backend"
STRAPI_BACKEND_PORT="1337"     
STRAPI_BACKEND_URL="http://${STRAPI_BACKEND_HOST}:${STRAPI_BACKEND_PORT}"

When I build, I have the following output:

info  - Generating static pages (0/7)
info  - Generating static pages (1/7)
info  - Generating static pages (3/7)
info  - Generating static pages (5/7)
Error: getaddrinfo ENOTFOUND strapi-backend
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:72:26) {
  errno: -3008,
  code: 'ENOTFOUND',
  syscall: 'getaddrinfo',
  hostname: 'strapi-backend',
  config: {
    transitional: {
      silentJSONParsing: true,
      forcedJSONParsing: true,
      clarifyTimeoutError: false
    },
    adapter: [Function: httpAdapter],
    transformRequest: [ [Function: transformRequest] ],
    transformResponse: [ [Function: transformResponse] ],
    timeout: 500,
    xsrfCookieName: 'XSRF-TOKEN',
    xsrfHeaderName: 'X-XSRF-TOKEN',
    maxContentLength: -1,
    maxBodyLength: -1,
    validateStatus: [Function: validateStatus],
    headers: { Accept: 'application/json', 'User-Agent': 'axios/0.24.0' },
    method: 'get',
    url: 'http://strapi-backend:1337/api/pages?filters[slug]=strapi-sample-homepage-content',
    data: undefined
  },

To me, it seems there's no way to resolve this, because Next.js doesn't seem to be on the docker network yet during build. Are there any solutions?



Solution 1:[1]

It seems that Docker's hostname resolution does not work during build time. On Mac, you can try STRAPI_BACKEND_HOST = "host.docker.internal". On Linux, using host networking during build worked for me:

nextjs-app:
  build:
    network: "host"
  # ...
  network_mode: "host"

This way, you can use STRAPI_BACKEND_HOST = localhost.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Thegaram