【问题标题】:how to make static files works using django docker nginx and postgresql since its not serving them如何使用 django docker nginx 和 postgresql 使静态文件工作,因为它不为它们提供服务
【发布时间】:2021-06-20 18:03:31
【问题描述】:

当我尝试访问 http://127.0.0.1:8000/admin 时,我明白了。

我的文件夹结构是:

django-react-nginx
|
|_ _ docker-compose.yml
|
  > backend
        |
        |_ Dockerfile
        |
        |_ entrypoint.sh

     > languages
          |
          |_ settings.py
     > media
     > static # This folder appears after running docker-compose -d --build
  > nginx
      |
      |_ default.conf
      |
      |_ Dockerfile

现在

这是文件

姜戈

settings.py

DEBUG = True

ALLOWED_HOSTS = ['*']

STATIC_URL = '/static/'

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

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

MEDIA_URL = '/media/'

Docker 文件

FROM python:3.8

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

WORKDIR /backend

COPY  requirements.txt /backend/

RUN pip install -r requirements.txt && \
    pip install --upgrade pip

COPY ./entrypoint.sh /

ENTRYPOINT ["sh", "/entrypoint.sh"]

入口点.sh

#!/bin/sh

python manage.py migrate --no-input

python manage.py collectstatic --no-input

gunicorn languages.wsgi:application --bind 0.0.0.0:8000

Nginx

default.conf

upstream django {
    server backend:8000;
}

server {
    listen 80;

    location / {
        proxy_pass http://django;
    }

    location /static/ {
        autoindex on;
        alias /backend/static;
    }

    location /media/ {
        autoindex on;
        alias /backend/static;
    }

}

Dockerfile

FROM nginx:1.19.8-alpine

COPY ./default.conf  /etc/nginx/conf.d/default.conf

根文件夹

Docker-compose

version: "3.7"

services:
  backend:
    build: ./backend/languages
    stdin_open: true # interactive
    tty: true        # interactive
    restart: "on-failure"
    env_file:
      .env
    volumes:
      - ./backend/languages:/backend
      - ./backend/languages/static:/backend/static
    ports:
      - 8000:8000
    networks:
      - nginx_network
      - db_network
    depends_on:
      - db
  db:
    image: postgres:11
    restart: "on-failure"
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    networks:
      - db_network
  
  nginx:
    build: ./nginx
    restart: always
    volumes:
      - ./backend/languages:/backend
      - ./backend/languages/static:/static
    ports:
      - 80:80
    networks:
      - nginx_network
    depends_on:
      - backend

networks:
  nginx_network:
    driver: bridge
  db_network:
    driver: bridge

volumes:
  postgres_data:

如上所述,我不确定如何使静态文件工作,它们被复制到上面提到的文件夹中,因为当我可以看到创建的文件夹并且当我检查日志时,我得到了这个165 static files copied to '/backend/static'.

【问题讨论】:

    标签: django docker docker-compose django-staticfiles


    【解决方案1】:

    Nginx 配置

    Nginx 配置看起来不错。容器通过/static 映射到/backend/languages/static,别名指向容器内的同一个文件夹-/static

    nginx.conf

    location /static/ {
            autoindex on;
            alias /static;
        }
    

    upd 检测到问题:别名必须具有相同的结尾斜杠才能正常工作。所以它必须是alias /static/

    撰写中的 nginx

      nginx:
        ...
        volumes:
          - ./backend/languages:/backend
          - ./backend/languages/static:/static
    

    Django 配置

    但是 Django 配置看起来已经损坏了。在这里,您已配置为将静态收集到static 文件夹 BASE_DIR

    settings.py

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

    这正是collectstatic 向您报告的内容:

    165 static files copied to '/backend/static'

    文件位于/backend/static,而不是/static。但是容器被配置为根文件夹/static:

    django 在撰写中

      backend
        ...
        volumes:
          - ./backend/languages:/backend
          - ./backend/languages/static:/static
    

    看起来问题可以通过指向来解决

        volumes:
          - ./backend/languages/static:/backend/static
    

    尽管如此,还有一些工作要做:媒体文件也不应该由 Django 提供,因此建议配置 Nginx 也提供媒体文件。

    Django Dockerfile

    我相信映射 ./backend/languages:/backend 有效,但 dockerizing 有什么意义呢?此 docker 映像中没有应用程序,只有依赖项。在镜像中包含源“更好”,因此最终部署只需要更新镜像和重启容器。

    所以,作为旁注,我建议(至少尝试):

    • 更新配置以使用 Nginx 提供媒体文件
    • 在您的 docker 镜像中包含 django 应用程序源代码
    • 构建过程中收集静态文件,不要将它们包含到 docker 映像中
    • entrypoint 中删除collectstatic
    • 提供静态文件并将它们视为单独的产品,如果您要将它们交付到 CDN 或单独的主机,请考虑它们 - 这是一种非常常见的解决方案
    • 虽然它们仍在同一主机上,但仍像现在一样将它们映射到容器,但以“相反”的方式:将静态文件传递到主机文件夹,从 ro 模式

    【讨论】:

    • 非常感谢 Ivan 的详细回复。我对 Docker 非常陌生,因此即使在阅读了所有这些关于 Docker 的书籍之后,我也不是 100% 我在做的事情。你介意告诉我上面最后两个要点是什么意思吗?在这一点上,我不确定自己该怎么做。我已经更新了上面的代码以在 nginx 中提供媒体文件再次感谢您
    • 目前您在容器内执行collectstatic 并从容器内部生成静态文件到主机。我的建议是在 build 阶段收集静态文件并将静态文件视为 build artifacts 之一。之后将它们部署到目标文件夹(可能远离项目源)并将 docker 容器卷映射到该文件夹​​。 ro 是只读的。有一天,您可能会考虑将静态文件存储在 CDN 服务/不同的主机上并从容器 每次启动运行 collectstatic 将成为一个奇怪且无用的操作。
    • 但这仍然是一个建议,可能的方法之一,不是必需的。
    • 如果您对路径求解器的原始问题,请将答案标记为已接受。
    • 并非如此。在 prod 和/或使用 Debug=False 时,Django 不应该既不提供静态文件也不提供媒体文件。这些 url 模式仅在 Debug=True 时有效,对产品没有好处。
    【解决方案2】:

    您可以通过在设置文件中配置来使用白噪声。 Set up Whitenoise with Django here

    【讨论】:

    猜你喜欢
    • 2019-02-22
    • 2023-03-05
    • 2017-11-19
    • 2016-01-28
    • 1970-01-01
    • 2020-09-15
    • 2013-11-28
    • 1970-01-01
    • 2014-10-05
    相关资源
    最近更新 更多