Docker Community Forums

Share and learn in the Docker community.

Docker compose and nginx volumes 404

Hi,

I just started learning docker a couple of weeks ago and I’ve been able to do a few things.

Right now I’m trying to create a simple Express API with mongo and a couple of static HTML files to display the data from the API endpoints. The issue I’m facing is that when I try to set the static HTML pages to a volume in the nginx service I keep getting 404 Not Found.

This is one folder structure I tried:

|-- client
   |-- index.html
   |-- values.html
|-- nginx
   |-- default.conf
   |-- Dockerfile.dev
|-- server
   |-- server.js
   |-- package.json
   |-- Dockerfile.dev

And this is the docker-compose.yml file for this setup:

version: "3"
services:
  nginx:
    restart: always
    build:
      dockerfile: Dockerfile.dev
      context: ./nginx
    volumes:
      - ./client:/usr/share/nginx/html/
    ports: 
      - "8000:80"
  api:
    build:
      dockerfile: Dockerfile.dev
      context: ./server
    volumes:
      - /app/node_modules
      - ./server:/app

This is another setup I tried (server folder is the same):

|-- nginx
   |-- default.conf
   |-- Dockerfile.dev
   |-- client
      |-- index.html
      |-- values.html

And the corresponding docker-compose.yml:

services:
  nginx:
    restart: always
    build:
      dockerfile: Dockerfile.dev
      context: ./nginx
    volumes:
      - ./client:/usr/share/nginx/html/
    ports: 
      - "8000:80"

Also tried this config in the docker-compose.yml file for the second folder structure:

services:
  nginx:
    restart: always
    build:
      dockerfile: Dockerfile.dev
      context: ./nginx
    volumes:
      - ./nginx/client:/usr/share/nginx/html/
    ports: 
      - "8000:80"

The express api has two endpoints and I can get there without issues either in the browser or postman, but I keep getting a 404 when I try to navigate to either index.html or values.html.
I don’t know if it’d be useful but this is the default.conf file:

upstream api {
  server api:5000;
}

server {
  listen 80;

  location /api {
    proxy_pass http://api;
  }
}

Well … I’m not 100% sure about the behavior of docker-compose … but Afaik, if both containers want/need to access the same data, they both need to share the same volume.

In other words: Your first container has the static pages. In order to have them accessible by the second container, it’ll need to create a volume (e.g.) “static-pages” and link it to the path were the files reside
Now, the second container also needs this volume to get access to this files.

I don’t have much experience with docker-compose so volume handling might be different here … but I’d suggest try something like this:

version: "3"
services:
  nginx:
    restart: always
    build:
      dockerfile: Dockerfile.dev
      context: ./nginx
    volumes:
      - static:/usr/share/nginx/html
    ports: 
      - "8000:80"
  api:
    build:
      dockerfile: Dockerfile.dev
      context: ./server
    volumes:
      - static:/usr/share/nginx/html

… I assume that Nginx and you app expect the static pages to be found in /usr/share/nginx/html

Thanks for the answer, but it didn’t work. The API keeps working though.

Shouldn’t the API service not care about the static HTML files? After all the only purpose is to provide endpoints to get data from a database. The static HTML files contains the JS code to make the requests to the express API, but the express server is not serving any static files at all.

Thanks again!!,
Rodrigo.

Ok I was able to fix it :grin:

The issue was that the static files needed a server of their own, since the main nginx instance is used only to proxy the requests.

The folder structure is as follows:

|-- client
   |-- index.html
   |-- values.html
   |-- Dockerfile.dev
|-- nginx
   |-- default.conf
   |-- Dockerfile.dev
|-- server
   |-- server.js
|-- docker-compose.yml

The Dockerfile.dev in the client folder is as follow:

FROM nginx
WORKDIR /app
COPY ./ /usr/share/nginx/html
EXPOSE 80

The default.conf file in the nginx folder is this:

upstream static {
  server static:80;
}

upstream api {
  server api:5000;
}

server {
  listen 80;

  location / {
    proxy_pass http://static;
  }

  location /api {
    proxy_pass http://api;
  }
}

Finally the docker-compose.yml file looks like this:

version: "3"
services:
  nginx:
    restart: always
    build:
      dockerfile: Dockerfile.dev
      context: ./nginx
    ports: 
      - "8000:80"
  static:
    build:
      dockerfile: Dockerfile.dev
      context: ./client
    volumes:
      - ./client /app
  api:
    build:
      dockerfile: Dockerfile.dev
      context: ./server
    volumes:
      - /app/node_modules
      - ./server:/app

Hopefully this helps someone.

Cheers,
Rodrigo.