简体   繁体   中英

Serving static files with Ngnix, Django and Docker

I am fairly new to Nginx and Docker and am currently facing an issue regarding a docker container setup. The setup consists of three containers: Nginx, Django and Postgres. It works as expected for the most part, however, I am not able to access static files through Nginx.

Here is the nginx.conf:

user nginx;
worker_processes  1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
  worker_connections 1024;
}
http {
  include /etc/nginx/mime.types;
  default_type application/octet-stream;
  log_format main '$remote_addr - $remote_user [$time_local]'
                  '"$request" $status $body_bytes_sent'
                  '"$http_referer" "$http_user_agent"'
                  '"$http_x_forwarded_for"';
  access_log /var/log/nginx/access.log main;
  upstream server {
    server server:8000;
  }
  server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name localhost;
    charset utf-8;
    root /usr/share/nginx/html;
    index index.html;
    location / {
      try_files $uri $uri/ @rewrites;
    }
    location @rewrites {
      rewrite ^(.+)$ /index.html last;
    }
    location ^~ /static/ {
      autoindex on;
      alias /usr/share/nginx/html/static/; 
    }
    location ~ ^/api {
      proxy_pass http://server;
    }
    location ~ ^/admin {
      proxy_pass http://server;
    }
  }
}

I would expect Nginx to serve /usr/share/nginx/html/static/ when I access the address localhost:8000/static . I did check the container fs at /usr/share/nginx/html/static/ , and the static files are present.

Here is the docker-compose.yml:

version: "3"
services:
  nginx:
    container_name: nginx
    build:
      context: .
      dockerfile: ./nginx/Dockerfile
    image: nginx
    restart: always
    volumes:
      - ./server/static:/usr/share/nginx/html/static
    ports:
      - 80:80
    depends_on:
      - server
    command: nginx -g 'daemon off';
  server:
    container_name: server
    build:
      context: ./server
      dockerfile: Dockerfile
    hostname: server
    ports:
      - 8000:8000
    volumes:
      - ./server:/src/project
    depends_on:
      - "db"
    restart: on-failure
    env_file: .env
    command: >
      bash -c '
      python manage.py makemigrations &&
      python manage.py migrate &&
      gunicorn project.wsgi -b 0.0.0.0:8000'
  db:
    container_name: postgres
    image: postgres:latest
    hostname: postgres
    ports:
      - 5432:5432
    volumes:
      - /var/lib/postgresql/data

The folder ./server/static contains all static files assembled trough python manage.py collectstatic and adds them to the volume /usr/share/nginx/html/static . However, when I try to access the static files, fe at localhost:8000/admin , I receive warnings for missing css files (base.css, login.css, ..).

Update: For anyone wondering, I had to change to nginx port in the docker-compose file to 8000, so that requests from client to localhost:8000 will be processed by nginx and not the server directly. With that in my mind I also changed the port of the server in the docker-compose file to expose so that it is only internally accessible. This will however prevent you from accessing the admin part of django as well.

Here is the nginx.conf:

user nginx;
worker_processes  1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
  worker_connections 1024;
}
http {
  include /etc/nginx/mime.types;
  default_type application/octet-stream;
  log_format main '$remote_addr - $remote_user [$time_local]'
                  '"$request" $status $body_bytes_sent'
                  '"$http_referer" "$http_user_agent"'
                  '"$http_x_forwarded_for"';
  access_log /var/log/nginx/access.log main;
  upstream server {
    server server:8000;
  }
  server {
    listen 8000 default_server;
    listen [::]:8000 default_server;
    server_name localhost;
    charset utf-8;
    root /usr/share/nginx/html;
    index index.html;
    location / {
      try_files $uri $uri/ @rewrites;
    }
    location @rewrites {
      rewrite ^(.+)$ /index.html last;
    }
    location ^~ /static/ {
      autoindex on;
      alias /usr/share/nginx/html/static/; 
    }
    location ~ ^/api {
      proxy_pass http://server;
    }
    location ~ ^/admin {
      proxy_pass http://server;
    }
  }
}

Here is the docker-compose.yml:

version: "3"
services:
  nginx:
    container_name: nginx
    build:
      context: .
      dockerfile: ./nginx/Dockerfile
    image: nginx
    restart: always
    volumes:
      - ./server/static:/usr/share/nginx/html/static
    ports:
      - 8000:8000
      - 80:8000
    depends_on:
      - server
    command: nginx -g 'daemon off';
  server:
    container_name: server
    build:
      context: ./server
      dockerfile: Dockerfile
    hostname: server
    expose:
      - "8000"
    volumes:
      - ./server:/src/project
    depends_on:
      - "db"
    restart: on-failure
    env_file: .env
    command: >
      bash -c '
      python manage.py makemigrations &&
      python manage.py migrate &&
      gunicorn project.wsgi -b 0.0.0.0:8000'
  db:
    container_name: postgres
    image: postgres:latest
    hostname: postgres
    ports:
      - 5432:5432
    volumes:
      - /var/lib/postgresql/data

You're finding solutions based on false assumptions, because you have not emerged yourself in the material. That's fine if you just want to have a setup that works and then understand it later. You're not the first person to use Docker for Django development, so look around:

There is what Docker has already done . It's not the only way to do it and certainly not the best way on several fronts.

If you really want an Nginx based setup, then Real Python has a really good example.

The short points of why your setup was not working and your fixes are not an improvement:

  • You use http protocol and WSGI is much better suited for this
  • Your solution assumed static files must be served by Django. They must not. Nginx is much better at it, but serving them with Nginx is in fact a bit of a slow down if you're in the early stage of a project where you might be adding a lot of new static files.
  • And so...you should read the document that virtually anyone seems to skip .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM