Обслуживание статических файлов с помощью Nginx и Django в Docker
Несмотря на то, что я видел много похожих проблем в других темах, я не смог настроить Nginx для обслуживания статических файлов из моего проекта Django.
Вот мои две статические переменные в моем settings.py
:
STATIC_URL = '/static/'
STATIC_ROOT='/opt/django/portfolio/collectstatic'
Вот мой dockerfile для сборки образа проекта:
FROM python:3.11-slim
WORKDIR opt/django/
COPY pyproject.toml .
RUN python -m pip install .
COPY ./portfolio/ ./portfolio/
WORKDIR portfolio/
RUN python manage.py collectstatic --noinput
RUN python manage.py makemigrations
RUN python manage.py migrate
EXPOSE 8000
CMD ["gunicorn", "portfolio.wsgi:application", "--bind", "0.0.0.0:8000"]
Вот docker-compose.yml
:
services:
web:
build:
context: .
dockerfile: ./docker/Dockerfile_django
container_name: webserver
volumes:
- static_data:/opt/django/portfolio/collectstatic
expose:
- "8000"
ports:
- "8000:8000"
depends_on:
- db
networks:
- docker_network
db:
image: postgres:15
container_name: db_postgres
expose:
- "5432"
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
networks:
- docker_network
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- static_data:/opt/django/portfolio/collectstatic
depends_on:
- web
networks:
- docker_network
volumes:
postgres_data:
static_data:
networks:
docker_network:
driver: bridge
name: docker_network
И, наконец, вот мой nginx.conf
:
events {}
http {
server {
listen 80;
server_name localhost;
location /static {
alias /opt/django/portfolio/collectstatic;
autoindex on;
}
# skip favicon.ico
location /favicon.ico {
access_log off;
return 204;
}
location / {
proxy_pass http://web:8000;
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-Forwarded-Proto $scheme;
}
}
}
Я не вижу ошибок в логах, и nginx сообщает о 200, когда я делаю GET к url в проекте. Когда я посещаю http://127.0.0.1/static/website/style.css
, я вижу css (и js файлы). Я очистил свой кэш. Когда я перехожу по адресу /opt/django/portfolio/collectstatic
в моем веб-контейнере, я вижу статические файлы. Структура моего проекта выглядит следующим образом:
- my_project/
- nginx/
- nginx.conf
- my_project/
- my_project/
- settings.py
...
- web/
- js/
- some_js.js
- some_other_js.js
- website/
- style.css
admin.py
apps.py
forms.py
models.py
tests.py
...
Что я упускаю? Буду признателен за любые рекомендации / отзывы о возможных неправильных конфигурациях, которые я, возможно, упускаю из виду.
Скорее всего, причина в том, что процесс nginx не имеет необходимых прав доступа к папке /opt/django/portfolio/collectstatic
.
Сначала добавьте несколько отладочных операторов в ваш nginx conf, например, так:
location /static {
alias /opt/django/portfolio/collectstatic;
autoindex on;
access_log /var/log/nginx/static_access.log;
error_log /var/log/nginx/static_error.log debug;
}
Очевидно, что затем нужно проверить журналы...
В качестве первой попытки вы можете запустить свой проект, затем войти в веб-контейнер и выполнить chmod -R 755 /opt/django/portfolio/collectstatic
. Это должно передать правильные права на папку. Проверьте, помогает ли это, если нет, снова проверьте журналы ошибок.
Это удобная команда для постоянного мониторинга журналов ошибок: docker-compose exec nginx tail -f /var/log/nginx/static_error.log
Не связанное с вашим вопросом замечание:
Очень необычно выполнять команду makemigrations
в режиме производства. Теоретически ваша dev-DB имеет ту же структуру, что и prod-DB. Тогда вы вносите изменения во время разработки. Здесь, на dev-DB вы запускаете makemigrations
, применяете их с помощью migrate
и тестируете. Когда все работает, вы фиксируете файлы миграции в вашем git-репо. Затем для prod-DB вы больше не запускаете makemigrations
. Для prod-DB вы применяете только миграции, полученные из вашей разработки/вашего git-репо.
TL/DR: Разработайте миграции на dev-DB с помощью makemigrations
и migrate
. Применяйте миграции к prod-DB только с помощью migrate
и не используйте makemigrations
снова.
Я смог решить эту проблему, добавив include mime.types;
в блок location /static
:
location /static {
alias /opt/django/portfolio/static;
autoindex on;
include mime.types;
}