5

I have a Django environment that I create with Docker Compose, and I'm trying to use manage.py collectstatic to copy my site's static files to a directory in the container. This directory (/usr/src/app/static) is also a Docker Volume.

After building my docker containers (docker-compose build), I run docker-compose run web python manage.py collectstatic, which works as expected, but my web server (Nginx) is not finding the files, nor are there any files when I run docker-compose run web ls -la /usr/src/app/static.

Any ideas on what I'm doing wrong?

(Note: I don't have manage.py collectstatic in my Dockerfile because my setup needs my ".env" file loaded, and I didn't see a way to load this in the Dockerfile. In either case, I would like to know why Docker Compose doesn't work as I'm expecting it to.)

Here are my config files:

## docker-compose.yml:
web:
  restart: always
  build: .
  expose:
    - "8000"
  links:
    - postgres:postgres
  volumes:
    - /usr/src/app/static
    - .:/code
  env_file: .env
  command: /usr/local/bin/gunicorn myapp.wsgi:application -w 2 -b :8000 --reload

nginx:
  restart: always
  build: ./config/nginx
  ports:
    - "80:80"
  volumes:
    - /www/static
  volumes_from:
    - web
  links:
    - web:web

postgres:
  restart: always
  image: postgres:latest
  volumes:
    - /var/lib/postgresql
  ports:
    - "5432:5432"


## Dockerfile:
FROM python:3.4.3
RUN mkdir /code
WORKDIR /code
ADD . /requirements/ /code/requirements/
RUN pip install -r /code/requirements/docker.txt
ADD . /code/
Dolan Antenucci
  • 15,432
  • 17
  • 74
  • 100
  • For those looking to use Compose with Django, I have an updated example in a related SO post: http://stackoverflow.com/a/36726663/318870 – Dolan Antenucci Apr 19 '16 at 18:42

2 Answers2

7

Running docker-compose run ... starts a new container and executes the command in there. then when you run docker-compose up it creates ANOTHER new container... which doesn't have the changes from your previous command.

What you want to do is start up a data container to hold your static files. Add another container to your compose file like this...

web-static:
  build: .
  volumes:
    - /usr/src/app/static
  env_file: .env
  command: manage.py collectstatic

and add web-static to the 'volumes-from' list on your nginx container

Paul Becotte
  • 9,767
  • 3
  • 34
  • 42
4

There are a couple of other ways to do this in addition to Paul Becotte's method:

A. With the release of docker-compose v 1.6 (not available at the time of Paul's answer) you can now use docker-compose file version 2 for specifying volumes

version: '2'
volumes:
  django-static:
    driver: local

django:
  ...
  volumes:
    - django-static:/usr/src/app/static

then you can collect static files in a separate container and they will persist

docker-compose run django ./manage.py collectstatic

Using this method should involve less system overhead then Pauls' method because you are running one less container.

B. Slight hack - you can collect static files in the container command

django:
  command: bash -c "./manage.py collectstatic --noinput;
  /usr/local/bin/gunicorn myapp.wsgi:application -w 2 -b :8000 --reload"

Downside of this is that it's inflexible if you are calling a different command from docker-compose command line then collectstatic will not get run. Also you are running collectstatic files at times when you probably don't need to.

lukeaus
  • 11,465
  • 7
  • 50
  • 60