Serving static files with Ngnix, Django and Docker

时间:2018-09-18 20:11:49

标签: django docker nginx

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, f.e. at localhost:8000/admin, I receive warnings for missing css files (base.css, login.css, ..).

2 个答案:

答案 0 :(得分:1)

更新: 对于任何想知道的人,我必须在docker-compose文件中将nginx port 更改为8000,以便从客户端到localhost:8000的请求将由nginx处理,而不是由服务器直接处理。考虑到这一点,我还将docker-compose文件中的服务器端口更改为 expose ,以便只能在内部访问它。但是,这也将阻止您访问django的admin部分。

这是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;
    }
  }
}

这是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

答案 1 :(得分:1)

您正在寻找基于错误假设的解决方案,因为您尚未出现在材料中。如果您只是想拥有一个可以正常使用的设置,然后在以后理解它,那很好。您不是第一个使用Docker进行Django开发的人,所以请环顾四周:

what Docker has already done。这不是唯一的方法,当然也不是在多个方面的最佳方法。

如果您真的想要基于Nginx的设置,那么Real Python就是一个很好的例子。

为什么您的设置无法正常工作以及您的修复程序没有改善的地方:

  • 您使用http协议,而WSGI更适合于此
  • 您的解决方案假定静态文件必须由Django提供。他们一定不能。 Nginx的性能要好得多,但是如果您处于项目的早期,可能要添加很多新的静态文件,那么与Nginx一起使用它们实际上会有点慢。
  • 所以...您应该阅读virtually anyone seems to skip的文档。