5
votes

I have a web application (Django based) that is utilising multiple containers:

  1. Web Application (Django + Gunicorn)
  2. Traefik (acting as the reverse proxy and SSL termination)
  3. Database which is used with the Web application
  4. Redis which is used with the Web application

According to some of the documentation I have read, I should be serving my static content using something like NGINX. But I don't have any idea on how I would do that. Would I install NGINX on my Web Application container or as a seperate NGINX container. How do I pass the request from Traefik? As far as I am aware you cannot server static content with Traefik.

This is what my docker-compose.yml looks like:

 traefik:
    image: traefik
    ports:
      - 80:80
      - 8080:8080
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik/traefik.toml:/etc/traefik/traefik.toml:ro
      - ./traefik/acme:/etc/traefik/acme

  web:
    build: .
    restart: always
    depends_on:
        - db
        - redis
        - traefik
    command: python3 /var/www/html/applications/py-saleor/manage.py makemigrations --noinput
    command: python3 /var/www/html/applications/py-saleor/manage.py migrate --noinput
    command: python3 /var/www/html/applications/py-saleor/manage.py collectstatic --noinput
    command: bash -c "cd /var/www/html/applications/py-saleor/ && gunicorn saleor.wsgi -w 2 -b 0.0.0.0:8000"
    volumes:
      - .:/app
    ports:
      - 127.0.0.1:8000:8000
    labels:
      - "traefik.enable=true"
      - "traefik.backend=web"
      - "traefik.frontend.rule=${TRAEFIK_FRONTEND_RULE}"
    environment:
      - SECRET_KEY=changemeinprod

  redis:
    image: redis

  db:
    image: postgres:latest
    restart: always
    environment:
      POSTGRES_USER: saleoradmin
      POSTGRES_PASSWORD: **
      POSTGRES_DB: **
      PGDATA: /var/lib/postgresql/data/pgdata
    volumes:
      - ~/py-saleor/database:/app
2
Also consider Caddy for serving static. Might be technically slower than nginx though but configs, etc are super simple. Another option would be to use S3 and equivalents to store static content.Dean Kayton
would you mind providiing your traefik.toml file?Mehran

2 Answers

12
votes

If anybody else needs an answer to this, the answer lies in creating a seperate NGINX service and then directing the front end rules to the static location (xyz.com/static), e.g. see below (part of docker-compose.yml):

  nginx:
       image: nginx:alpine
       container_name: nginx_static_files
       restart: always
       volumes:
           - ./default.conf:/etc/nginx/conf.d/default.conf
           - ./saleor/static/:/static
       labels:
           - "traefik.enable=true"
           - "traefik.backend=nginx"
           - "traefik.frontend.rule=Host:xyz.co;PathPrefix:/static"
           - "traefik.port=80"

You also need to ensure that your Nginx config file (default.conf) is appropriately configured:

server {
   listen                      80;
   server_name                 _;
   client_max_body_size        200M;
   set                         $cache_uri $request_uri;

   location                    = /favicon.ico { log_not_found off; access_log off; }
   location                    = /robots.txt  { log_not_found off; access_log off; }
   ignore_invalid_headers      on;
   add_header                  Access-Control-Allow_Origin *;

   location /static {
       autoindex on;
       alias /static;
   }

   location /media {
       autoindex on;
       alias /media;
   }

   access_log                  /var/log/nginx/access.log;
   error_log                   /var/log/nginx/error.log;
}

All credit goes to Pedro Rigotti on the Traefik slack channel for helping me arrive at the solution.

0
votes

I don't have much idea about Traefik and Docker.

But I can tell you how you can install nginx and use it to serve static files(which is always recommended in order to not choke the django server by serving static files)

Install nginx and follow the steps mentioned to setup nginx .

sudo apt-get install nginx

The site-available file should look something like this:

server {
        listen 80;
        listen [::]:80;

        server_name xyz.com;
        client_max_body_size 20M;

        # xyz.com/media/any_static_asset_file.jpg 
        # when anyone hits the above url then the request comes to this part.
        location /media/ {

                # do make sure that the autoindex is off so that your assets are only accessed when you have proper path

                autoindex off; 

                # this is the folder where your asset files are present.

                alias /var/www/services/media/; 
        }

        # whenever any request comes to xyz.com then this part would handle the request
        location / {
                proxy_pass http://unix:/var/www/services/xyz/django_server.sock;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
        }
}