- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个使用以下堆栈的单页网络应用程序:
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 为我们的媒体和静态文件提供服务。我们在 nginx
和 django
服务之间共享这些主机安装的卷。从版本 2 开始,docker-compose
自动在您的 Docker 镜像之间创建一个网络,允许您在服务之间共享卷。
最后,在我们的 nginx.conf 中,我们为 static
和 media
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/
我对 Python-Django 和 web 开发还很陌生,我被困在这个使用 POST 创建新资源的特殊问题上。 我正在为 REST API 使用 Django REST 框架,我正在尝试创建一个新资
我已经使用 Django-storages 成功地将 Word 文档存储到 S3。 class Document(TitleSlugDescriptionModel, TimeStampedModel
我有 2 个关于模型代理的问题, 如何从模型对象创建代理对象? 如何从模型查询集创建代理查询集? 例如,假设我们定义了: from django.contrib.auth.models import
我想编写一个直接执行 HTTP 请求的单元测试(而不是使用 django.test.client.Client)。 如果您好奇为什么 - 那是因为我想测试我从 Django 应用程序公开的 Thrif
我为我的个人网站启动了一个 django 项目来学习 django。到目前为止,我已经将我的开发环境设置为我需要的一切,并遵循 this很棒的教程来创建一些基本的数据结构和模板。现在我想开始使用我之前
我已经阅读了很多关于如何在使用 Django 注册时添加额外字段的信息,例如 here 、 here 和 here 。代码片段是: forms.py(来自注册应用程序) class Registrat
我正在编写小型社交应用程序。功能之一是在网站标题中写入用户名。因此,例如,如果我登录并且我的名字是Oleg(用户名),那么我应该看到: Hello, Oleg | Click to edit prof
我有一个使用 Django 和 Django Rest 框架开发的应用程序。我想将 django-reversion 功能添加到我的应用程序中。 我已经尝试过http://django-reversi
我有一个简单的 HTML 表单,我没有使用 Django 表单,但现在我想添加一个选择。 选择最容易创建为 Django ChoiceField (与通过循环等手动创建选择相反),但是,如果没有在 D
我不明白为什么人们以两种方式编写外键,这样做的目的是什么?它们是相同还是不同? 我注意到有些人这样写: author = models.ForeignKey(Author, on_delete=mod
我想在我的 Django 应用程序中获取评论最多的十个帖子,但我做不到,因为我想不出合适的方法。 我目前正在使用 django 评论框架,并且我已经看到使用 aggregate or annotate
这对于 Django 1.2 仍然有效吗? Custom Filter in Django Admin on Django 1.3 or below 我已经尝试过,但管理类中的 list_filter
问题在于,当 django-compressor 编译为 .js 文件的 CoffeeScript 文件中引用 {{ STATIC_URL }} 时,它无法正确加载。 在我的 django 模板中,我
我正在尝试将一些字段从一个 django 模型移动到一个新模型。假设我有一个书籍模型: class Book(models.Model): title = models.CharField(max
我想在我的 Django 应用程序中获取评论最多的十个帖子,但我做不到,因为我想不出合适的方法。 我目前正在使用 django 评论框架,并且我已经看到使用 aggregate or annotate
目前我正在寻找在 Django 中实现访问控制。我已经阅读了有关内置权限的内容,但它并不关心每个对象的基础。例如,我想要“只有创建者可以删除自己的项目”之类的权限。所以我读到了 django-guar
嗨,我正在将我的 Django 模型的一个字段的值设置为其他模型的另一个字段的值。这个值应该是动态变化的。 这是我的第一个模型 class MainModel(AbstractBaseUser, Pe
我正在尝试为我的模型创建一个编辑表单。我没有使用模型表单,因为根据模型类型,用户可以使用不同的表单。 (例如,其中一个表单有 Tinymce 小部件,而另一个没有。) 有没有什么方法可以使用模型设置表
Django 模板中的搜索字段 如何在类似于此图像的 Django 模板中创建搜索字段 http://asciicasts.com/system/photos/1204/original/E354I0
根据 Django documentation ,如果 Django 安装激活了 AuthenticationMiddleware,HttpRequest 对象有一个“user”属性代表当前登录的用户
我是一名优秀的程序员,十分优秀!