I have somewhat complicated setup with docker. Everything's working as expected except I have this weird problem. Visiting index page or /pages/_id pages I have no errors. But when I try to open /other-page it crashes. All are using the same API url.
Error found in the console when opening /other-page:
GET http://api:1337/games net::ERR_NAME_NOT_RESOLVED
Not sure what to do, any suggestions?
nuxt.config.js
axios: {
baseURL: 'http://api:1337'
},
docker-compose.yml
version: '3'
services:
api:
build: .
image: strapi/strapi
environment:
- APP_NAME=strapi-app
- DATABASE_CLIENT=mongo
- DATABASE_HOST=db
- DATABASE_PORT=27017
- DATABASE_NAME=strapi
- DATABASE_USERNAME=
- DATABASE_PASSWORD=
- DATABASE_SSL=false
- DATABASE_AUTHENTICATION_DATABASE=strapi
- HOST=api
- NODE_ENV=production
ports:
- 1337:1337
volumes:
- ./strapi-app:/usr/src/api/strapi-app
#- /usr/src/api/strapi-app/node_modules
depends_on:
- db
restart: always
links:
- db
nuxt:
# build: ./app/
image: "registry.gitlab.com/username/package:latest"
container_name: nuxt
restart: always
ports:
- "3000:3000"
links:
- api:api
command:
"npm run start"
nginx:
image: nginx:1.14.2
expose:
- 80
container_name: nginx
restart: always
ports:
- "80:80"
volumes:
- ./nginx:/etc/nginx/conf.d
depends_on:
- nuxt
links:
- nuxt
index.vue
...
async asyncData({ store, $axios }) {
const games = await $axios.$get('/games')
store.commit('games/emptyList')
games.forEach(game => {
store.commit('games/add', {
id: game.id || game._id,
...game
})
})
return { games }
},
...
page.vue
...
async asyncData({ store, $axios }) {
const games = await $axios.$get('/games')
store.commit('games/emptyList')
games.forEach(game => {
store.commit('games/add', {
id: game.id || game._id,
...game
})
})
return { games }
},
...
Nginx conf
upstream webserver {
ip_hash;
server nuxt:3000;
}
server {
listen 80;
access_log off;
connection_pool_size 512k;
large_client_header_buffers 4 512k;
location / {
proxy_pass http://webserver;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_max_temp_file_size 0;
}
UPDATE:
Tried what Thomasleveil suggested. Now I'm receiving following error:
nuxt | [2:09:35 PM] Error: connect ECONNREFUSED 127.0.0.1:80
So, it seems like now /api is being forwarded to 127.0.0.1:80. Not sure why ^^
nuxt.config.js
axios: {
baseURL: '/api'
},
server: {
proxyTable: {
'/api': {
target: 'http://localhost:1337',
changeOrigin: true,
pathRewrite: {
"^/api": ""
}
}
}
}
docker-compose.yml
version: '3'
services:
reverse-proxy:
image: traefik # The official Traefik docker image
command: --api --docker # Enables the web UI and tells Traefik to listen to docker
ports:
- "80:80" # The HTTP port
- "8080:8080" # The Web UI (enabled by --api)
volumes:
- /var/run/docker.sock:/var/run/docker.sock # listen to the Docker events
networks:
- mynet
api:
build: .
image: strapi/strapi
container_name: api
environment:
- APP_NAME=strapi-app
- DATABASE_CLIENT=mongo
- DATABASE_HOST=db
- DATABASE_PORT=27017
- DATABASE_NAME=strapi
- DATABASE_USERNAME=
- DATABASE_PASSWORD=
- DATABASE_SSL=false
- DATABASE_AUTHENTICATION_DATABASE=strapi
- HOST=api
- NODE_ENV=development
ports:
- 1337:1337
volumes:
- ./strapi-app:/usr/src/api/strapi-app
#- /usr/src/api/strapi-app/node_modules
depends_on:
- db
restart: always
networks:
- mynet
labels:
- "traefik.backend=api"
- "traefik.docker.network=mynet"
- "traefik.frontend.rule=Host:example.com;PathPrefixStrip:/api"
- "traefik.port=1337"
db:
image: mongo
environment:
- MONGO_INITDB_DATABASE=strapi
ports:
- 27017:27017
volumes:
- ./db:/data/db
restart: always
networks:
- mynet
nuxt:
# build: ./app/
image: "registry.gitlab.com/username/package:latest"
container_name: nuxt
restart: always
ports:
- "3000:3000"
command:
"npm run start"
networks:
- mynet
labels:
- "traefik.backend=nuxt"
- "traefik.frontend.rule=Host:example.com;PathPrefixStrip:/"
- "traefik.docker.network=web"
- "traefik.port=3000"
networks:
mynet:
external: true
Visiting index page or /pages/_id pages I have no errors. But when I try to open /other-page it crashes.
To reformulate:
/
that shows some links targeting pages at /pages/_id
(where _id
is a valid game id)/
or /pages/_id
, the content shows up/
targeting /pages/xxx
(where xxx
is a valid id), I got an errorThe way asyncData works in nuxt.js is the following:
http://yourserver/pages/123
in its browserasyncData
method from the vue component is called from the nuxt.js server sidehttp://api:1337/games/123
, receive the response and the content renders.Something a bit different happens now.
http://api:1337/games/123
which has a link to the main page listing all the games (http://yourserver/
) and click it.http://api:1337/games
to try to fetch the new content. And fails due to a name resolution errorThis is a feature brought to you by nuxt.js to speed up page content loading time. from the documentation, the important bit of information is:
asyncData
is called every time before loading the page component. It will be called server-side once (on the first request to the Nuxt app) and client-side when navigating to further routes.
server-side
means the call is made from the nuxt server to the api serverclient-side
means the call is made from the user browser to the api serverNow the fun part:
1337
http://api:1337/
, and this works finehttp://api:1337
fails (net::ERR_NAME_NOT_RESOLVED
) because the user computer does not know how to translate the domain name api
to an IP address. And even if it could, this IP Address would be unreachable anyway.http://yourserver/api/
to the api
container on port 1337
.client-side
(from the user browser) use the url http://yourserver/api
instead of http://api:1337/
http://api:1337
for calls made server-side
.server-side
)Since you are using the nuxt.js Axios module to make calls to the api container, you are half way there.
The Axios module has a proxy option that can be set to true
in nuxtjs.config.js
Bellow is an example of setting up a reverse proxy for your project using Traefik, but the documentation state that the proxy is incompatible with the usage of the baseURL option. The prefix option must be used instead.
Your nuxt.config.js should then look like this:
axios: {
prefix: '/api',
proxy: true
},
proxy: {
'/api/': {
target: 'http://localhost:1337',
pathRewrite: {
'^/api/': ''
}
}
},
This works fine from your development computer, where if strapi is running and responding at http://localhost:1337
. But this won't work in a container because we there need to replace http://localhost:1337
with http://api:1337
.
To do so, we can introduce an environment variable (STRAPI_URL
):
axios: {
prefix: '/api',
proxy: true
},
proxy: {
'/api/': {
target: process.env.STRAPI_URL || 'http://localhost:1337',
pathRewrite: {
'^/api/': ''
}
}
},
We will later set the STRAPI_URL
in the docker-compose.yml file.
client-side
)Since I gave up on implementing reverse proxies with nginx when using docker, here's an example with Traefik:
docker-compose.yml:
version: '3'
services:
reverseproxy: # see https://docs.traefik.io/#the-traefik-quickstart-using-docker
image: traefik:1.7
command: --docker
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
api:
image: strapi/strapi
environment:
- ...
expose:
- 1337
labels:
traefik.frontend.rule: PathPrefixStrip:/api
traefik.port: 1337
nuxt:
image: ...
expose:
- 3000
command:
"npm run start"
labels:
traefik.frontend.rule: PathPrefixStrip:/
traefik.port: 3000
Now all HTTP requests made by the user browser to http://yourserver
will be handled by the Traefik reverse proxy.
Traefik will configure forwarding rules by looking at labels starting with traefik.
on the nuxt
and api
containers.
You now have 2 reverse proxies:
server-side
requests (the nuxt.js Proxy module)client-side
requests (Traefik)We now need to instruct the nuxt.js Proxy module that it must forward requests to http://api:1337/
. We are going to use the STRAPI_URL
environment variable for that.
And we need to instruct nuxt Axios module that the user browser must call the api on http://yourserver/api
. This is done with the API_URL_BROWSER environment variable.
axios: {
prefix: '/api',
proxy: true
},
proxy: {
'/api/': {
target: process.env.STRAPI_URL || 'http://localhost:1337',
pathRewrite: {
'^/api/': ''
}
}
},
version: '3'
services:
reverseproxy: # see https://docs.traefik.io/#the-traefik-quickstart-using-docker
image: traefik:1.7
command: --docker
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
api:
image: strapi/strapi
environment:
- ...
expose:
- 1337
labels:
traefik.frontend.rule: PathPrefixStrip:/api
traefik.port: 1337
nuxt:
image: ...
expose:
- 3000
command:
"npm run start"
environment:
NUXT_HOST: 0.0.0.0
STRAPI_URL: http://api:1337/
API_URL_BROWSER: /api
labels:
traefik.frontend.rule: PathPrefixStrip:/
traefik.port: 3000
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With