首页 > 解决方案 > Nginx 无法在数字海洋上提供 django 静态或媒体文件

问题描述

当我将 dockerised django 应用程序部署到数字海洋时,我在提供静态文件和媒体文件时遇到问题。我在这里读过很多类似的问题,但到目前为止,没有一个答案对我有用。

大致遵循本指南https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/#nginx,我现在处于可以使用本地启动 docker 容器的状态以下命令并让 nginx 完美地服务静态/媒体文件:

sudo docker-compose -f docker-compose-prod.yml down -v
sudo docker-compose -f docker-compose-prod.yml up -d --build
sudo docker-compose -f docker-compose-prod.yml exec web python manage.py collectstatic --no-input --clear

我现在正试图在数字海滴上进行同样的工作。在远程服务器上,我运行与上面完全相同的命令来启动服务。然后,除了访问任何静态或媒体文件的能力之外,一切都按预期工作。例如,每当我访问 {my digital ocean ip}/static/admin/css/nav_sidebar.css 时,都会遇到 404 错误。每当我看到 chrome 试图获取我的自定义 css 时,请求只会显示为“已取消”(然后,如果我访问已取消请求的 URL 路径,我会看到相同的 404)。

我的代码可以在这里看到:https ://github.com/PaulGilmartin/personal_website 可能与本次讨论相关的部分:

nginx.conf

upstream personal_website {
    server web:8000;
}

server {

    listen 80;

    location / {
        proxy_pass http://personal_website;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }

    location /static/ {
        alias /var/www/personal_website/static/;
    }

    location /media/ {
        alias /var/www/personal_website/media/;
    }

}

设置.py

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

我特别困惑的是完全相同的命令在本地完美运行。这让我认为远程服务器上的 404 是基于权限的症状,但我不明白在我的 Dockerfile.prod 中是如何发生这种情况的,我小心地将所有内容都分配给非 root 用户。

任何帮助将不胜感激,因为我对问题可能的想法知之甚少!

编辑:这是我的 docker-compose 文件:

version: '3.7'


services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.prod
    command: gunicorn personal_website.wsgi:application --bind 0.0.0.0:8000 --timeout 120
    volumes:
      - static_volume:/var/www/personal_website/static
      - media_volume:/var/www/personal_website/media
    env_file:
      - ./.env.prod
    expose:
      - 8000
    ports:
      - "80:8000"
    depends_on:
      - db
  db:
    image: postgres:11
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    env_file:
      - ./.env.prod.db
  nginx:
    build: ./nginx
    volumes:
      - static_volume:/var/www/personal_website/static
      - media_volume:/var/www/personal_website/media
    ports:
      - 1337:80
    depends_on:
      - web

volumes:
  postgres_data:
  static_volume:
  media_volume:

标签: djangonginxdocker-composedigital-oceandjango-staticfiles

解决方案


我感觉问题出在这里:

STATIC_ROOT = os.path.join(BASE_DIR, 'static')

该路径实际上应该与 nginx 期望的相同:

/var/www/personal_website/static/

因此,您可以尝试以下操作:

  1. 尝试在 Django 设置中硬编码静态根:

    STATIC_ROOT = '/var/www/personal_website/static/'

  2. 对运行 Django 的容器执行 bash:docker exec -it <container_name> /bin/bash- 在那里运行 collectstatic 并检查静态文件是否已复制到您期望的文件夹中。如果不是 - 那么您可能想要找到文件被复制的确切位置。

  3. 如果它也看到带有静态文件的正确卷,还要检查 nginx 容器内部

我有完全相同的问题,静态和媒体的硬编码路径解决了这个问题

更新: 我已经克隆了这个项目,对我来说,它没有获取静态文件。所以我在docker-compose-prod.yml中做了以下更改,它开始工作:

  1. 从服务中删除端口-网络

    ports:
       - "80:8000"
    

它不是必需的,因为不应从外部访问 web (Django)。仅在 Docker 内部的公开端口 8000 上

  1. 设置nginx的开放端口为80:

    ports:
       - 80:80
    

我不知道 DigitalOcean 使用哪个端口来托管站点,但默认值为 80。


推荐阅读