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/
Whichever you choose, once you have set up a volume to the folder where the data is stored in the container, if you do a docker-compose down , and then a docker-compose up , your data will not be erased and it will become persistent.
Stops containers and removes containers, networks, volumes, and images created by up .
Docker has an option to allow specific folders in a container to be mapped to the normal filesystem on the host. This allows us to have data in the container without making the data part of the Docker image, and without being bound to AUFS.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With