Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serve static files with nginx inside of a docker container?

I'm using boot2docker since I'm running Mac OSX. I can't figure out how serve up static files using nginx that is running inside a docker container (that also contains the static assets, like my html and js).

I have four docker containers being spun up with this docker-compose.yml:

web:
   build: ./public
   links: 
     - nodeapi1:nodeapi1
   ports:
     - "80:80"

nodeapi1:
   build: ./api
   links:
     - redis
     - db
   ports:
     - "5000:5000"
   volumes:
     - ./api:/data

redis:
   image: redis:latest
   ports:
     - "6379:6379"

db:
   image: postgres:latest
   environment:
     POSTGRES_USER: root
   ports:
     - "5432:5432"

This is my nginx.conf:

worker_processes auto;

daemon off;

events {
  worker_connections 1024;
}

http {
  server_tokens off;
  upstream node-app {
    ip_hash;
    server 192.168.59.103:5000;
  }
  server {
    listen 80;
    index index.html;
    root /var/www;

    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
      expires 1d;
    }

    location / {
      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-NginX-Proxy true;

      proxy_http_version 1.1;
      proxy_pass http://node-app;
      proxy_cache_bypass $http_upgrade;
    }

  }
}

My Dockerfile for my web build (which contains my nginx.conf and static assets):

# Pull nginx base image
FROM nginx:latest

# Expost port 80
EXPOSE 80

# Copy custom configuration file from the current directory
COPY nginx.conf /etc/nginx/nginx.conf

# Copy static assets into var/www
COPY ./dist /var/www
COPY ./node_modules /var/www/node_modules

# Start up nginx server
CMD ["nginx"]

The contents of the ./dist folder is a bundle.js file and an index.html file. The file layout is:

public
  -- Dockerfile
  -- nginx.conf
  -- dist (directory)
    -- bundle.js
    -- index.html
  -- node_modules
    ...various node modules

It is properly sending requests to my node server (which is also in a docker container, which is why my upstream server points to the boot2docker ip), but I'm just getting 404s for attempts to retrieve my static assets.

I'm lost as to next steps. If I can provide any information, please let me know.

like image 389
Jimmy Gong Avatar asked Aug 04 '15 00:08

Jimmy Gong


People also ask

How do I serve a static file in nginx?

To serve static files with nginx, you should configure the path of your application's root directory and reference the HTML entry point as the index file. In this example, the root directory for the snake deployment is /home/futurestudio/apps/snake which contains all the files.

Is nginx used for serving static content?

Configure NGINX and NGINX Plus to serve static content, with type-specific root directories, checks for file existence, and performance optimizations.

Should nginx run inside Docker?

If nginx is running in a container then your site is going to be 100% dead to the world while Docker isn't running. Users will get a connection error. When nginx is installed directly on your host you can serve a 503 maintenance page that doesn't depend on Docker or any containers running.


1 Answers

Your issue isn't related to docker but to your nginx configuration.

In your nginx config file, you define /var/www/ as the document root (I guess to serve your static files). But below that you instruct nginx to act as a reverse proxy to your node app for all requests.

Because of that, if you call the /index.html URL, nginx won't even bother checking the content of /var/www and will forward that query to nodejs.

Usually you want to distinguish requests for static content from requests for dynamic content by using a URL convention. For instance, all requests starting with /static/ will be served by nginx while anything else will be forwarded to node. The nginx config file would then be:

worker_processes auto;

daemon off;

events {
  worker_connections 1024;
}

http {
  server_tokens off;
  upstream node-app {
    ip_hash;
    server 192.168.59.103:5000;
  }
  server {
    listen 80;

    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
      expires 1d;
    }

    location /static/ {
      alias /var/www/;
      index index.html;
    }

    location / {
      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-NginX-Proxy true;

      proxy_http_version 1.1;
      proxy_pass http://node-app;
      proxy_cache_bypass $http_upgrade;
    }

  }
}
like image 148
Thomasleveil Avatar answered Sep 22 '22 14:09

Thomasleveil