Django - collectstatic from deploy release_command success but staticfile folder not found

Hello,

I deployed a django app using a Dockerfile, with collectstatic in the deploy release_command.

When I deploy, it is mentioned that static files are copied to /app/staticfiles as expected:

2356 static files copied to '/app/staticfiles', 6920 post-processed.

but they are not available to django:

2022-09-06T07:26:05Z app[08b1ad0c] cdg [info]  File "/usr/local/lib/python3.9/site-packages/django/contrib/staticfiles/storage.py", line 472, in stored_name
2022-09-06T07:26:05Z app[08b1ad0c] cdg [info]    raise ValueError(
2022-09-06T07:26:05Z app[08b1ad0c] cdg [info]ValueError: Missing staticfiles manifest entry for 'contrib/bootstrap/bootstrap.min.css'

when I ssh the node, there is no staticfiles in app folder.

If I run manually python manage.py collectstatic from ssh console and restart gunicorn then it works

Any idea of what I am missing?

Some extracts of my settings.py related to whitenoise (DEBUG is False):

...
STATIC_ROOT = os.path.abspath(os.path.join(BASE_DIR, 'staticfiles'))
...
if not DEBUG:
   MIDDLEWARE.insert(1,'whitenoise.middleware.WhiteNoiseMiddleware')
   STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
...

fly.toml:

app = "XXXXX"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []

[env]

[deploy]
  release_command = "bash -c \"python manage.py migrate && python manage.py collectstatic --noinput\""

[experimental]
  allowed_public_ports = []
  auto_rollback = true

[[services]]
  http_checks = []
  internal_port = 8080
  processes = ["app"]
  protocol = "tcp"
  script_checks = []
  [services.concurrency]
    hard_limit = 25
    soft_limit = 20
    type = "connections"

  [[services.ports]]
    force_https = true
    handlers = ["http"]
    port = 80

  [[services.ports]]
    handlers = ["tls", "http"]
    port = 443

  [[services.tcp_checks]]
    grace_period = "1s"
    interval = "15s"
    restart_limit = 0
    timeout = "2s"

Dockerfile:

ARG PYTHON_VERSION=3.9

FROM python:${PYTHON_VERSION}

RUN apt-get update && apt-get install -y \
    python3-pip \
    python3-venv \
    python3-dev \
    python3-setuptools \
    python3-wheel

RUN mkdir -p /app
WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

EXPOSE 8080

CMD ["gunicorn", "--bind", ":8080", "--workers", "1", "stones.wsgi"]

Thanks!

Ok, I found the issue by reading the docs a bit more carefully. The answer may be useful to others.

Durnig deploy release_command, " Changes made to the filesystem on the temporary VM will not be retained or deployed. If you need to modify persistent volumes or configure your application, consider making use of CMD or ENTRYPOINT in your Dockerfile.".

Hence, the call to collectstatic should not be done as deploy release_command but rather in the Dockerfile. We cannot easily call collectstatic using RUN as there is no access to database (by default, secret environment variable is not set during build), so I ended up modifying the CMD:

CMD ["/bin/bash", "-c", "python manage.py collectstatic --noinput; gunicorn --bind :8080 --workers 1 stones.wsgi"]

And this works.

2 Likes

Thank you for this solution! It helped me out, but with migrate instead of collectstatic. It was tricky figuring out how to get everything working with a SQLite database on a persistent volume.

Deployed my site built on Django but static and media files are not showing. Tried a bunch of options, but still the fly does not display them. I created these static files with the help of python manage.py collectstatic , before I started deploying the project, and in the Docker file I wrote that fly should copy everything, but it still didn’t help.