Dockerizing strapi/next.js corporate starter (1): Next.js image build fails

System Information
  • Strapi Version: 3.6.3
  • Operating System: Windows 10 / Ubuntu 20.04 LTS (via WSL2)
  • Database: sqlite
  • Node Version: 14.17.1
  • Yarn Version: 1.22.5

Hello evryone!

I’m trying to dockerize a corporate starter (strapi/next.js).
Locally, installed with npx, it runs without a problem.

When I run docker-compose build (on ubuntu / wsl2) I get strapi image built but next.js build fails:

#17 118.2 > Build error occurred
#17 118.2 FetchError: request to http://localhost:1337/pages?_locale=en failed, reason: connect ECONNREFUSED 127.0.0.1:1337
#17 118.2 at ClientRequest. (/app/node_modules/node-fetch/lib/index.js:1461:11)
#17 118.2 at ClientRequest.emit (node:events:394:28)
#17 118.2 at Socket.socketErrorListener (node:_http_client:447:9)
#17 118.2 at Socket.emit (node:events:394:28)
#17 118.2 at emitErrorNT (node:internal/streams/destroy:193:8)
#17 118.2 at emitErrorCloseNT (node:internal/streams/destroy:158:3)
#17 118.2 at processTicksAndRejections (node:internal/process/task_queues:83:21) {
#17 118.2 type: ‘system’,
#17 118.2 errno: ‘ECONNREFUSED’,
#17 118.2 code: ‘ECONNREFUSED’
#17 118.2 }
#17 118.2 error Command failed with exit code 1.

What am I missing here? Should I have defined some env variable?
Can I build images like that given next.js needs accessing pages endpoint during its build?

Below are my Docker files:

My docker-compose file looks as follows:

version: '3'
services:
  strapi:
    build: ./backend
    image: mydockerhubid/project-cms:latest
    ports:
      - '1337:1337'
  next:
    build: ./frontend
    image: mydockerhubid/project-webui:latest
    ports:
      - '3000:3000'

127.0.0.1 is local to each container service. As both services are in the same docker network, you can access the services use their hostnames. So to access the “strapi” service from the “next” service, you need to use hostname “strapi” instead of “127.0.0.1”.

Change your next config to access strapi on “strapi:1337”.

I added this to my next.config.js:

module.exports = {
  i18n: {
    locales: ["en", "fr"],
    defaultLocale: "en",
  },
  serverRuntimeConfig: {
    // Will only be available on the server side
    URI: 'http://strapi:1337'
  },
  publicRuntimeConfig: {
    // Will be available on both server and client
    URI: 'http://localhost:1337'
  }
}

In the api.js:

import getConfig from 'next/config';
const { serverRuntimeConfig, publicRuntimeConfig } = getConfig();
const API_URI = serverRuntimeConfig.URI || publicRuntimeConfig.URI;

export function getStrapiURL(path) {
  console.log(`api url: ${API_URI}${path}`)
  return `${API_URI}${path}`
}

The Strapi container build first and without errors.
Then I get the following during the Next container build:

#17 84.28 info  - Creating an optimized production build...
#17 476.4 info  - Compiled successfully
#17 476.4 info  - Collecting page data...
#17 482.2 Warning: You have opted-out of Automatic Static Optimization due to `getInitialProps` in `pages/_app`. This does not opt-out pages with `getStaticProps`
#17 482.2 Read more: https://nextjs.org/docs/messages/opt-out-auto-static-optimization
#17 482.2
#17 485.0 api url: http://strapi:1337/pages?_locale=en
#17 485.0 api url: http://strapi:1337/pages?_locale=fr
#17 490.1
#17 490.1 > Build error occurred
#17 490.1 FetchError: request to http://strapi:1337/pages?_locale=en failed, reason: getaddrinfo EAI_AGAIN strapi
#17 490.1     at ClientRequest.<anonymous> (/app/node_modules/node-fetch/lib/index.js:1461:11)
#17 490.1     at ClientRequest.emit (node:events:394:28)
#17 490.1     at Socket.socketErrorListener (node:_http_client:447:9)
#17 490.1     at Socket.emit (node:events:394:28)
#17 490.1     at emitErrorNT (node:internal/streams/destroy:193:8)
#17 490.1     at emitErrorCloseNT (node:internal/streams/destroy:158:3)
#17 490.1     at processTicksAndRejections (node:internal/process/task_queues:83:21) {
#17 490.1   type: 'system',
#17 490.1   errno: 'EAI_AGAIN',
#17 490.1   code: 'EAI_AGAIN'
#17 490.1 }
#17 490.2 error Command failed with exit code 1.
#17 490.2 info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
------
executor failed running [/bin/sh -c yarn build && yarn install --production --ignore-scripts --prefer-offline]: exit code: 1

Did you manage to find a solution? I am having the same issue.

I have an nginx reverse proxy plus nextjs and strapi. The nginx container can access the other containers but the nextjs app is having trouble during build time with getstaticprops/getstaticpaths.

I get the exact same error message.

Tried referencing the strapi container by it’s internal ip within docker but that didn’t work unfortunately.

1 Like

I’m at the exact same point like @happygrizzly

So I’m also interested in a solution to get the corporate starter up and running in docker for a demon of strapi in combination with nextjs.

Are there maybe any more “advanced” examples of dockerfiles and docker-compose that could maybe find their way into GitHub - strapi/strapi-docker: Install and run your first Strapi project using Docker ?

1 Like

Hey! No, unfortunately I didn’t find a solution. Maybe this will help: database - How can one make a Docker Compose service build depend on another service? - Stack Overflow. In other words build next.js app when container is created and started (here the depends_on might help, regarding the api container start order).

This is how i build it
docker-compose.yml

version: '3'
services:
  strapi:
    container_name: strapi
    build: .
    image: mystrapi:latest
    restart: unless-stopped
    env_file: .env
    environment:
      DATABASE_CLIENT: ${DATABASE_CLIENT}
      DATABASE_HOST: soraDB
      DATABASE_NAME: ${DATABASE_NAME}
      DATABASE_USERNAME: ${DATABASE_USERNAME}
      DATABASE_PORT: ${DATABASE_PORT}
      JWT_SECRET: ${JWT_SECRET}
      DATABASE_PASSWORD: ${DATABASE_PASSWORD}
      NODE_ENV: ${NODE_ENV}
    links:
      - strapiDB:strapiDB
    volumes:
      - ./:/srv/
      - ./uploads:/srv//public/uploads
    ports:
      - '1337:1337'
    networks:
      - strapi
    depends_on:
      - strapiDB

  strapiDB:
    image: postgres:12.0-alpine
    container_name: strapiDB
    restart: unless-stopped
    env_file: .env
    environment:
      POSTGRES_USER: ${DATABASE_USERNAME}
      POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
    volumes:
      - ./data:/var/lib/postgresql/data/
    ports:
      - '5432:5432'
    networks:
      - strapi

networks:
  strapi:
    name: Strapi
    driver: bridge

This will spin up a strapi instance with a postgres database.
You need to create an .env or use the one in strapi already.
From here you can build one just for the frontend, note the use of depends_on which tells docker it will wait for it to start.

Dockerfile

FROM node:14-alpine
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY ./package.json ./
COPY ./yarn.lock ./
ENV PATH /opt/node_modules/.bin:$PATH
RUN yarn config set network-timeout 600000 -g
RUN yarn install
WORKDIR /opt/app
COPY ./ .
RUN yarn build
EXPOSE 1337
CMD ["yarn", "start"]

Both files needs to be be in the root of the strapi project.

Then you can use 0.0.0.0 or localhost as normal and no need to say http://strapi:1337 as it runs on localhost.
If this is running on a server then you use the IP or domain to the server.

You can use IP:PORT docker container with your straps backend (ex.NEXT_PUBLIC_STRAPI_API_URL=http://10.105.178.74:1337)