Nginx не загружает файл через django admin
Подскажите в чем может быть проблема, есть связка с Django + Nginx + PostgreSQL В Django есть строка
image = models.ImageField(upload_to='%Y/%m/%d/', verbose_name='Изображение')
позволяющая загружать изображения и размещать их в корне
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Если запускать приложение Django путём python3 manage.py runserver,
а режим DEBUG = False и не помещать в контейнер Docker, то приложение отработает и загрузит в /media/<year>/<m>/<d>/image.jpg - файл.
Проблемы начинаются после размещения приложения в docker и запуска его в контейнере, nginx, попытка загрузки через поле, в логах показывает успешную загрузку
POST /admin/app/prod/2/change/ HTTP/1.1" 302 0 "http://192.168.xx.xx/admin/app/prod/2/change/
и как прежде папки с датами не создаются.
Но стоит вручную добавить этот файл создав папки /media/\<year>/\<m>/\<d>\/image.jpg
nginx успешно отрабатывает и показывает загруженный файл на странице.
Конфигурация nginx
server {
listen 80;
location / {
proxy_pass http://web:8000;
client_body_buffer_size 10m;
}
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
alias /static/;
}
location /media/ {
autoindex on;
alias /media/;
}
}
А docker-compose выглядит так
version: "3"
services:
web:
build:
context: ./
dockerfile: Dockerfile
volumes:
- ./:/usr/src/app
- ./static_dev/:/static_dev
- ./media/:/media
- ./static/:/static
expose:
- 8000
depends_on:
- postgresdb
nginx:
build:
context: ./docker/nginx
dockerfile: Dockerfile
depends_on:
- postgresdb
- web
ports:
- 80:80
volumes:
- ./static_dev/:/static_dev
- ./media/:/media
- ./static/:/static
- ./log/nginx:/var/log/nginx
Dockerfile
FROM python:3
WORKDIR /usr/scr/app
COPY requirements.txt .
COPY entrypoint.sh .
RUN python3 -m pip install --upgrade pip
RUN pip install -r requirements.txt
RUN chmod -x /usr/scr/app/entrypoint.sh
COPY . .
settings.py
import os
from dotenv import load_dotenv
load_dotenv('.env')
SECRET_KEY = os.getenv('SECRET_KEY')
DEBUG = False
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
ALLOWED_HOSTS = ['*']
AUTHENTICATION_BACKENDS = [
'mainapp.auth.EmailAuthBackend',
]
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'debug_toolbar',
'mainapp.apps.MainappConfig',
'specs',
'crispy_forms',
'crispy_bootstrap5',
'psycopg2',
'captcha',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware',
]
ROOT_URLCONF = 'shop.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'shop.wsgi.application'
DATABASES = {
"default": {
"ENGINE": os.getenv('ENGINE_DB'),
"NAME": os.getenv('NAME_DB'),
"USER": os.getenv('USER_DB'),
"PASSWORD": os.getenv('PASSWORD_DB'),
"HOST": os.getenv('HOST_DB'),
"PORT": os.getenv('PORT_DB'),
}
}
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
USE_I18N = True
USE_L10N = True
USE_TZ = True
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static_dev'),
)
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
CRISPY_TEMPLATE_PACK = "bootstrap5"
INTERNAL_IPS = [
'127.0.0.1',
]
Dockerfile nginx
FROM nginx
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d
Всё сработало! Спасибо за подсказку andreymal В настройках settings.py сменил:
MEDIA_URL = '/usr/scr/app/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Это путь в самом контейнере docker.