gpt4 book ai didi

django - 通过 Nginx (Django/React/Nginx/Docker-Compose) 提供 Django 媒体文件

转载 作者:行者123 更新时间:2023-12-02 18:28:33 25 4
gpt4 key购买 nike

上下文

我有一个使用以下堆栈的单页网络应用程序:

  • React 前端
  • Django 作为后端
  • 用于网络服务器的 Nginx

Web 应用程序使用 docker-compose 进行 docker 化。我的 React 应用程序从 Django 服务器获取数据(django 使用 Django Rest Framework 构建为 api 端点)。

问题/问题

我在部署时遇到问题,无法通过 Nginx 提供我的媒体文件。

到目前为止我尝试了什么

我最初的想法是提供这个 stackoverflow 上显示的媒体文件 post - 这很简单。不过,由于 Nginx 在其自己的 docker 中运行(我的 django 服务器也是如此),我无法指向我的 django 媒体文件,因为它们位于不同的容器中。

理想情况下,我不想使用 webpack,而是让 Nginx 负责提供媒体文件。

如果您查看下面的 nginx Dockerfile,您会看到我正在将我的静态文件复制到 /usr/share/nginx/html/static/staticfiles 中,然后使用 nginx 为它们提供服务(请参阅位置 ^~/static/nginx.conf 中)。我尝试对我的媒体文件做同样的事情(作为测试)并且它有效 - 但是,由于复制是在我构建容器时发生的,因此无法访问我在站点启动后上传的所有文件。

文件结构

Root Dirc  
|__ docker-compose.yml
|__ backend
|__ root
|__ Project
|__ api
|__ models.py
|__ ...
|__ media
|__ teddycrepineau
|__ settings.py
|__ ...
|__ production
|__ Dockerfile
|__ nginx
|__ Dockerfile
|__ nginx.conf
|__ frontend
|__ ...

相关代码

docker-compose.yml

version: '3'

volumes:
postgres_data: {}
postgres_backup: {}

services:
postgres:
image: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
- postgres_backup:/backups
env_file: .env

nginx:
container_name: nginx
build:
context: .
dockerfile: ./nginx/Dockerfile
image: nginx
restart: always
depends_on:
- django
ports:
- "80:80"

django:
container_name: django
build:
context: backend
dockerfile: ./root/production/Dockerfile
hostname: django
ports:
- 8000:8000
volumes:
- ./backend:/app/
depends_on:
- postgres
command: >
bash -c '
python3 ./root/manage.py makemigrations &&
python3 ./root/manage.py migrate &&
python3 ./root/manage.py initadmin &&
gunicorn teddycrepineau.wsgi -b 0.0.0.0:8000 --chdir=./root/'

env_file: .env

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 app {
server django:8000;
}

server {
listen 80 default_server;
listen [::]:80 default_server;
server_name 0.0.0.0;
charset utf-80;

root /usr/share/nginx/html;
index index.html;

location / {
try_files $uri $uri/ @proxy_to_app;
}

location @proxy_to_app {
rewrite ^(.+)$ /index.html last;
}

location ^~ /static/ {
autoindex on;
alias /usr/share/nginx/html/static/;
}

location ~ ^/api {
proxy_pass http://django:8000;
}
location ~ ^/admin {
proxy_pass http://django:8000;
}
}
}

nginx Dockerfile

FROM nginx:latest
ADD ./nginx/nginx.conf /etc/nginx/nginx.conf
COPY ./frontend/build /usr/share/nginx/html
COPY ./backend/root/staticfiles /usr/share/nginx/html/static/staticfiles

Django Dockerfile

FROM python:3.7

ENV PYTHONUNBUFFERED 1

RUN export DEBIAN_FRONTEND=noninteractive

RUN mkdir /app

RUN pip install --upgrade pip
ADD /root/requirements.txt /app/

WORKDIR /app/
ADD . /app/

RUN pip install -r requirements.txt

EXPOSE 8000

Django settings.py

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
APPS_DIR = os.path.join(BASE_DIR, 'project')
....
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(APPS_DIR, 'media/')

Django urls.py

urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^api/', include('project.api.urls')),
path('summernote/', include('django_summernote.urls')),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


更新

当我安装一个共享卷并在我的 nginx.conf 中引用它时,当我尝试访问在 django 后端上传的图像时,我得到一个 404 页面未找到

docker-compose.yml

version: '3'

volumes:
postgres_data: {}
postgres_backup: {}

services:
postgres:
image: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
- postgres_backup:/backups
env_file: .env

nginx:
container_name: nginx
build:
context: .
dockerfile: ./nginx/Dockerfile
image: nginx
restart: always
depends_on:
- django
ports:
- "80:80"
volumes:
- ./static:/app/backend/root/staticfiles
- ./media:/app/backend/root/project/media

django:
container_name: django
build:
context: backend
dockerfile: ./root/production/Dockerfile
hostname: django
ports:
- 8000:8000
volumes:
- ./backend:/app/
- ./static:/app/backend/root/staticfiles
- ./media:/app/backend/root/project/media
depends_on:
- postgres
command: >
bash -c '
python3 ./root/manage.py collectstatic --no-input &&
python3 ./root/manage.py makemigrations &&
python3 ./root/manage.py migrate &&
python3 ./root/manage.py initadmin &&
gunicorn teddycrepineau.wsgi -b 0.0.0.0:8000 --chdir=./root/'

env_file: .env

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 app {
server django:8000;
}

server {
listen 80 default_server;
listen [::]:80 default_server;
server_name localhost;
charset utf-80;

root /usr/share/nginx/html;
index index.html;

location / {
try_files $uri $uri/ @proxy_to_app;
}

location @proxy_to_app {
rewrite ^(.+)$ /index.html last;
}

location ^~ /static/ {
autoindex on;
alias /usr/share/nginx/html/static/;
}

location ^~ /media/ {
autoindex on;
alias /app/backend/root/project/media/;
}

location ~ ^/api {
proxy_pass http://django:8000;
}
location ~ ^/admin {
proxy_pass http://django:8000;
}
}
}

最佳答案

问题出在我在 docker-compose.yml 中挂载我的卷的方式(这是我的错误理解)。

首先,我们创建一个主机挂载卷 (./backend/),引用我们的 django 服务中存在的 /app/ 文件夹。我们创建了这个文件夹,并将所有相关文件添加到位于后端文件夹中的 Dockerfile 中。这基本上会将 django Docker 镜像上存在的 /app/ 文件夹链接到主机上存在的 ./backend 文件夹 - 引用文件来自 OP 的结构。

一旦我们有了这个卷,无论何时对我们的 /app/ 文件夹进行更新(即上传新图像),它都会反射(reflect)在我们的主机安装卷(即 ./backend/) - 反之亦然。

我们最终创建了 2 组主机挂载卷(./backend/root/staticfiles/..../backend/root/project/media/) 我们将使用它来通过 Nginx 为我们的媒体和静态文件提供服务。我们在 nginxdjango 服务之间共享这些主机安装的卷。从版本 2 开始,docker-compose 自动在您的 Docker 镜像之间创建一个网络,允许您在服务之间共享卷。

最后,在我们的 nginx.conf 中,我们为 staticmedia url 引用了 docker-compose.yml 文件中的主机安装卷.

docker-compose.yml

version: '3'

volumes:
postgres_data: {}
postgres_backup: {}

services:
postgres:
image: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
- postgres_backup:/backups
env_file: .env

django:
container_name: django
build:
context: backend
dockerfile: ./root/production/Dockerfile
hostname: django
ports:
- 8000:8000
volumes:
- ./backend:/app/
- ./backend/root/staticfiles/admin:/usr/share/nginx/html/static/admin
- ./backend/root/staticfiles/rest_framework:/usr/share/nginx/html/static/rest_framework
- ./backend/root/staticfiles/summernote:/usr/share/nginx/html/static/summernote
- ./backend/root/project/media/:/usr/share/nginx/html/media/
depends_on:
- postgres
command: >
bash -c '
python3 ./root/manage.py collectstatic --no-input &&
python3 ./root/manage.py makemigrations &&
python3 ./root/manage.py migrate &&
python3 ./root/manage.py initadmin &&
gunicorn teddycrepineau.wsgi -b 0.0.0.0:8000 --chdir=./root/'
env_file: .env

nginx:
container_name: nginx
build:
context: .
dockerfile: ./nginx/Dockerfile
image: nginx
restart: always
depends_on:
- django
ports:
- "80:80"
volumes:
- ./backend/root/staticfiles/admin:/usr/share/nginx/html/static/admin
- ./backend/root/staticfiles/rest_framework:/usr/share/nginx/html/static/rest_framework
- ./backend/root/staticfiles/summernote:/usr/share/nginx/html/static/summernote
- ./backend/root/project/media/:/usr/share/nginx/html/media/

nginx.conf

....

server {
listen 80 default_server;
listen [::]:80 default_server;
server_name localhost;
charset utf-80;

root /usr/share/nginx/html;
index index.html;

location / {
try_files $uri $uri/ @proxy_to_app;
}

location @proxy_to_app {
rewrite ^(.+)$ /index.html last;
}

location ^~ /static/ {
autoindex on;
alias /usr/share/nginx/html/static/;
}

location ^~ /media/ {
autoindex on;
alias /usr/share/nginx/html/media/;
}

location ~ ^/api {
proxy_pass http://django:8000;
}
location ~ ^/admin {
proxy_pass http://django:8000;
}
}
}

关于django - 通过 Nginx (Django/React/Nginx/Docker-Compose) 提供 Django 媒体文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54911090/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com