skip to Main Content

I’m trying to load static files using nginx and gunicorn, it works when i go to http://0.0.0.0/static/css/base.css
static hosted via nginx, but doesn’t when i add django port http://0.0.0.0:8000/static/css/base.css
static not found using django server

these are the errors i get in my nginx container

nginx_1  | 172.22.0.1 - - [04/Oct/2023:04:59:33 +0000] "GET /static/css/base.css HTTP/1.1" 304 0 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36" "-"
nginx_1  | 2023/10/04 04:59:34 [error] 8#8: *2 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.22.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "localhost", referrer: "http://localhost/static/css/base.css"
nginx_1  | 172.22.0.1 - - [04/Oct/2023:04:59:34 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://localhost/static/css/base.css" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36" "-"

This is all what I’ve tried, in conf.d i put container name as server_name and tried to add types to determine css files, but it didnt work
settings.py

STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'static'

Dockerfile

FROM python:3.10

ENV PYTHONDONTWRITEBYTECODE=1 
    PYTHONBUFFERED=1 
    POETRY_VERSION=1.4.2 
    POETRY_VIRTUALENVS_CREATE="false"

RUN pip install "poetry==$POETRY_VERSION"

WORKDIR /education_platform

COPY pyproject.toml poetry.lock docker-entrypoint.sh ./

RUN poetry install --no-interaction --no-ansi --no-dev

COPY . /education_platform

EXPOSE 8000
RUN chmod +x wait-for-it.sh

docker-compose.yaml

version: '3'

services:
  db:
    image: postgres:13.1-alpine
    restart: unless-stopped
    env_file:
      - ./.env
    volumes:
      - ./data/db:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres

  cache:
    image: redis:7.0.4
    restart: unless-stopped
    volumes:
      - .data/cache:/data

  web:
    restart: unless-stopped
    build:
      context: .
      dockerfile: Dockerfile
    command: [ "/education_platform/wait-for-it.sh", "db:5432", "--",
               "gunicorn", "education_platform.wsgi:application", "-b", "0.0.0.0:8000"]
    env_file:
      - ./.env
    volumes:
      - .:/education_platform
      - ./static:/education_platform/static
    ports:
      - "8000:8000"
    environment:
      - DJANGO_SETTINGS_MODULE=education_platform.settings.prod
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    depends_on:
      - db
      - cache

  nginx:
    image: nginx:1.23.1
    restart: unless-stopped
    volumes:
      - ./config/nginx/conf.d:/etc/config/nginx/conf.d/default.conf
      - ./static:/usr/share/nginx/html/static
    ports:
      - "80:80"
    command: ["/bin/sh", "-c", "nginx -g 'daemon off;'"]
    depends_on:
      - web

conf.d

server {
    listen 80;
    server_name education_platform_web_1;
    error_log stderr warn;
    access_log /dev/stdout main;

    location / {
        proxy_pass http://education_platform_web_1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
    }

    location /static/ {
        alias /usr/share/nginx/html/static/;

    }

    location /media/ {
        alias /education_platform/media/;
    }

    types {
            text/javascript js;
            application/javascript js;
            text/css css;
        }
}

2

Answers


  1. Chosen as BEST ANSWER

    Renaming conf.d to nginx.conf,listening to Joris Jansen advices and changing nginx container ports to "1336:80" and achieving after that website by localhost:1336 solved my problem


  2. There are a couple of things missing for as far as I could see:

    1. A volume in your Dockerfile that mounts the static files
    2. Collectstatic

    In order to prevent an extensive command in your docker-compose file I would like to suggest to following in your Dockerfile itself:

    from this (docker-compose):

    command: [ "/education_platform/wait-for-it.sh", "db:5432", "--",
               "gunicorn", "education_platform.wsgi:application", "-b", "0.0.0.0:8000"]
    

    to something like this (at the end of your Dockerfile):

    ENTRYPOINT ["/entrypoint.sh"]
    
    VOLUME ["/education_platform/static"]
    
    EXPOSE 8000
    
    CMD ["gunicorn", "education_platform.wsgi:application", "-b", "0.0.0.0:8000"]
    

    Now you might be wondering, where did my wait-for-it.sh script went to? And what is entrypoint.sh doing.

    Here is the entrypoint.sh file:

    #!/bin/bash
    
    # wait for Postgres
    /wait-for-it.sh $POSTGRES_HOST:$POSTGRES_PORT -t 60
    
    # run migrations, collect media, start the server
    python manage.py migrate
    echo "yes" | python manage.py collectstatic --noinput
    
    
    exec $@
    

    And, one more thing, I see two ways of specifying environment variables. Both the env_file and environment entries are being used in your docker-compose file. Now, there might be a valid reason in your case, but if not, it might be better to use one or the other:

      web:
        restart: unless-stopped
        build:
          context: .
          dockerfile: Dockerfile
        env_file:                       <---- HERE
          - ./.env
        volumes:
          - .:/education_platform
          - ./static:/education_platform/static
        ports:
          - "8000:8000"
        environment:                    <---- HERE
          - DJANGO_SETTINGS_MODULE=education_platform.settings.prod
          - POSTGRES_DB=postgres
          - POSTGRES_USER=postgres
          - POSTGRES_PASSWORD=postgres
        depends_on:
          - db
          - cache
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search