【问题标题】:ValueError: Missing staticfiles manifest entry on Heroku with Docker, django-pipeline, whitenoiseValueError:使用 Docker、django-pipeline、whitenoise 在 Heroku 上缺少静态文件清单条目
【发布时间】:2021-06-06 13:36:24
【问题描述】:

我正在尝试使用 Docker、django-pipeline 和 whitenoise 在 Heroku 上部署 Django 项目。容器构建成功,我看到collectstaticcontainer-name/static 中生成了预期的文件。但是,在访问任何页面时,我都会收到以下 500 错误:

ValueError: Missing staticfiles manifest entry for 'pages/images/favicons/apple-touch-icon-57x57.png'

下面是我的settings.pyDockerfileheroku.yml。由于我也在使用 django-pipeline,我不确定的一件事是 STATICFILES_STORAGE 使用什么设置?我试过了

STATICFILES_STORAGE = 'pipeline.storage.PipelineStorage'

但这会导致文件路径 404ing。

感谢任何建议。谢谢。

#settings.py
...
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env.bool("DJANGO_DEBUG", default=False)

ALLOWED_HOSTS = ['.herokuapp.com', 'localhost', '127.0.0.1']

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.admindocs",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "django.contrib.sites",
    # Third-party
    "allauth",
    "allauth.account",
    "debug_toolbar",
    "django_extensions",
    "pipeline",
    "rest_framework",
    "whitenoise.runserver_nostatic",
    "widget_tweaks",
    # Local
    ...
]
MIDDLEWARE = [
    "debug_toolbar.middleware.DebugToolbarMiddleware",
    "django.middleware.security.SecurityMiddleware",
    "whitenoise.middleware.WhiteNoiseMiddleware",
    ...
]

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/

STATIC_URL = "/static/"
# STATICFILES_DIRS = [str(BASE_DIR.joinpath("code/static"))]
STATIC_ROOT = str(BASE_DIR.joinpath("static"))

MEDIA_URL = "/media/"

MEDIA_ROOT = str(BASE_DIR.joinpath("media"))

# django-pipeline config
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
DEBUG_PROPAGATE_EXCEPTIONS = True
STATICFILES_FINDERS = (
    "django.contrib.staticfiles.finders.FileSystemFinder",
    "django.contrib.staticfiles.finders.AppDirectoriesFinder",
    "pipeline.finders.PipelineFinder",
)
...
# Dockerfile
# Pull base image
FROM python:3.8

# Set environment variables and build arguments
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt-get install -y nodejs build-essential

# Set working directory
WORKDIR /code
COPY . /code/
RUN npm install sass --dev
RUN npm install yuglify --dev
RUN npm install
RUN mkdir static
RUN mkdir staticfiles

# Install dependencies
COPY Pipfile Pipfile.lock /code/
# Figure out conditional installation of dev dependencies
# Will need to remove --dev flag for production
RUN pip install pipenv && pipenv install --system --dev
# heroku.yml
setup:
  addons:
  - plan: heroku-postgresql
build:
  docker:
    web: Dockerfile
release:
  image: web
  command:
    - python manage.py collectstatic --noinput
run:
  web: gunicorn config.wsgi

更新

根据 ENDEESA 对this similar SO post 的回复,我将我的设置更新为以下内容,因为我的静态文件存储在pages/static/pages 中:

STATIC_URL = "/static/"
STATICFILES_DIRS = [str(BASE_DIR.joinpath("pages/static"))]
STATIC_ROOT = str(BASE_DIR.joinpath("static"))

我还注意到我的顶级 urls.py 文件包含以下行:

urlpatterns += staticfiles_urlpatterns()

据我了解,这对于在开发中提供静态文件很有用,但不应该在生产中使用,因此我将其移至仅在 DEBUG 为 True 时添加。但是很遗憾,错误仍然存​​在。

更神秘的是,当我跑步时

python manage.py findstatic <file-path> --verbosity 2

找到文件:

Found 'images/favicons/apple-touch-icon-57x57.png' here:
  /code/pages/static/images/favicons/apple-touch-icon-57x57.png
  /code/pages/static/images/favicons/apple-touch-icon-57x57.png
Looking in the following locations:
  /code/pages/static
  /code/static
  /usr/local/lib/python3.8/site-packages/django/contrib/admin/static
  /usr/local/lib/python3.8/site-packages/debug_toolbar/static
  /usr/local/lib/python3.8/site-packages/django_extensions/static
  /usr/local/lib/python3.8/site-packages/rest_framework/static

那么为什么我仍然收到ValueError: Missing staticfiles manifest entry

【问题讨论】:

    标签: django docker heroku django-pipeline whitenoise


    【解决方案1】:

    已解决

    终于,我得出了以下解决方案。我的主要问题是:

    • 在发布命令期间似乎收集了静态文件,但实际的STATIC_ROOT 目录在我的容器中是空的。我不确定为什么。我的解决方案是不在heroku.yml 中将collectstatic 作为发布命令运行,而是在Dockerfile 中运行。
    • 注意:为了在我的Dockerfile 中设置collectstatic,我需要为所有环境变量设置默认值,包括SECRET_KEY,后者我使用django.core.management.utils 中的get_random_secret_key()。感谢Ryan Knightillustrating this here
    • 除了我的settings.py 需要默认密钥之外,我的最终静态文件设置如下所示。
    • 由于我使用的是django-pipeline,我的js 文件无法通过whitenoise 存储选项正确加载。我最终改用pipeline.storage.PipelineStorage
    • 原来我根本不需要设置STATICFILES_DIRS。以前我将其设置为:
    STATICFILES_DIRS = [
        str(BASE_DIR.joinpath("pages/static")),
        str(BASE_DIR.joinpath("staticfiles")),]
    

    两者都是不必要的,因为app_name/static/app_name 已经是default place Django will look for static files,而且我实际上并没有在root/staticfiles 中存储额外的非应用特定文件。所以我删除了这个设置。

    • heroku.yml 中,我删除了collectstatic 的释放命令。
    • 在我的 Heroku 应用管理员的设置页面上,我为 DISABLE_COLLECTSTATIC 添加了一个配置变量,设置为 1
    # Dockerfile
    # Pull base image
    FROM python:3.8
    
    # Set environment variables and build arguments
    ENV PYTHONDONTWRITEBYTECODE 1
    ENV PYTHONUNBUFFERED 1
    
    RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
    RUN apt-get install -y nodejs build-essential
    
    # Set working directory
    WORKDIR /code
    COPY . /code/
    RUN npm install sass --dev
    RUN npm install yuglify --dev
    RUN npm install
    
    # Install dependencies
    COPY Pipfile Pipfile.lock /code/
    RUN pip install pipenv && pipenv install --system
    
    # Collect static files here instead of in heroku.yml so they end up in /code/static, as expected in the app
    RUN python manage.py collectstatic --noinput
    
    # settings.py
    ...
    from django.core.management.utils import get_random_secret_key
    SECRET_KEY = env("DJANGO_SECRET_KEY", default=get_random_secret_key())
    ...
    STATIC_URL = "/static/"
    STATIC_ROOT = str(BASE_DIR.joinpath("static"))
    STATICFILES_STORAGE = 'pipeline.storage.PipelineStorage'
    DEBUG_PROPAGATE_EXCEPTIONS = True
    STATICFILES_FINDERS = (
        "django.contrib.staticfiles.finders.FileSystemFinder",
        "django.contrib.staticfiles.finders.AppDirectoriesFinder",
        "pipeline.finders.PipelineFinder",
    )
    ...
    
    # heroku.yml
    setup:
      addons:
      - plan: heroku-postgresql
    build:
      docker:
        web: Dockerfile
    release:
      image: web
    run:
      web: gunicorn config.wsgi
    

    项目结构,如果有帮助的话:

    config
      settings.py
      ...
    pages
      static
        pages
          scss
          js
          images
    static
    Dockerfile
    heroku.yml
    docker-compose.yml
    ...
    

    祝其他与部署之神作战的人好运。愿机会永远对你有利,不要放弃!

    【讨论】:

      猜你喜欢
      • 2018-10-05
      • 2020-11-19
      • 2017-10-24
      • 2017-12-29
      • 2020-01-15
      • 2023-03-06
      • 1970-01-01
      • 2020-02-01
      • 2020-09-17
      相关资源
      最近更新 更多