You just have to log into your running docker container and run your commands.
- Build your stack :
docker-compose build -f path/to/docker-compose.yml - Launch your stack :
docker-compose up -f path/to/docker-compose.yml - Display docker running containers :
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3fcc49196a84 ex_nginx "nginx -g 'daemon off" 3 days ago Up 32 seconds 0.0.0.0:80->80/tcp, 443/tcp ex_nginx_1
66175bfd6ae6 ex_webapp "/docker-entrypoint.s" 3 days ago Up 32 seconds 0.0.0.0:32768->8000/tcp ex_webapp_1
# postgres docker container ...
- Get the CONTAINER ID of you django app and log into :
docker exec -t -i 66175bfd6ae6 bash
Now you are logged into, then go to the right folder :
cd path/to/django_appAnd now, each time you edit your models, run in your container :
python manage.py makemigrationsandpython manage.py migrate
I also recommend you to use a docker-entrypoint for your django docker container file to run automatically :
- collecstatic
- migrate
- runserver or start it with gunicorn or uWSGI
Here is an example (docker-entrypoint.sh) :
#!/bin/bash
# Collect static files
echo "Collect static files"
python manage.py collectstatic --noinput
# Apply database migrations
echo "Apply database migrations"
python manage.py migrate
# Start server
echo "Starting server"
python manage.py runserver 0.0.0.0:8000
Answer from Louis Barranqueiro on Stack OverflowYou just have to log into your running docker container and run your commands.
- Build your stack :
docker-compose build -f path/to/docker-compose.yml - Launch your stack :
docker-compose up -f path/to/docker-compose.yml - Display docker running containers :
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3fcc49196a84 ex_nginx "nginx -g 'daemon off" 3 days ago Up 32 seconds 0.0.0.0:80->80/tcp, 443/tcp ex_nginx_1
66175bfd6ae6 ex_webapp "/docker-entrypoint.s" 3 days ago Up 32 seconds 0.0.0.0:32768->8000/tcp ex_webapp_1
# postgres docker container ...
- Get the CONTAINER ID of you django app and log into :
docker exec -t -i 66175bfd6ae6 bash
Now you are logged into, then go to the right folder :
cd path/to/django_appAnd now, each time you edit your models, run in your container :
python manage.py makemigrationsandpython manage.py migrate
I also recommend you to use a docker-entrypoint for your django docker container file to run automatically :
- collecstatic
- migrate
- runserver or start it with gunicorn or uWSGI
Here is an example (docker-entrypoint.sh) :
#!/bin/bash
# Collect static files
echo "Collect static files"
python manage.py collectstatic --noinput
# Apply database migrations
echo "Apply database migrations"
python manage.py migrate
# Start server
echo "Starting server"
python manage.py runserver 0.0.0.0:8000
I use this method:
services:
web:
build: .
image: uzman
command: python manage.py runserver 0.0.0.0:8000
ports:
- "3000:3000"
- "8000:8000"
volumes:
- .:/code
depends_on:
- migration
- db
migration:
image: uzman
command: python manage.py migrate --noinput
volumes:
- .:/code
depends_on:
- db
Using docker hierarchy we made, the service migration runs after setting up the database and before running the main service. Now when you run your service docker will run migrations before running the server; look that the migration server is applied over the same image as the web server, it means that all migrations will be taken from your project, avoiding problems.
You avoid making entry points or whatever other thing this way.
makemigration and migrate doesn't work docker production
Migration files created outside project directory (Docker container)
Running DB migrate within dockerfile
Running Django makemigrations Docker container - Stack Overflow
Videos
Hey everyone,
I have been trying to setup a django app using this guide:
https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/
And it was a great resource to get everything up and running. However i have problem now when it comes to migrations. Say i add a model, add data into my db, and later i change the model. Now i can run makemigrations using the exec method on the container, but when i shut down my migrations are not stored in my local files i save to my git project, instead they are lost as i spin down the container.
Does anyone know how to solve this, how do you makemigrations is such a setup where you run two dockerized django/postgres dev/prod environments?
I asked a question few weeks ago regarding how when using an external DB I am fine using dockerfile to just run the web server image and not worry about the DB image. I'm writing the dockerfile for the same and I was wondering where I should put the migrate command I understand that there can only be one CMD command within a dockerfile So my thoughts immediately went to
Having one RUN command to migrate the DB and the CMD command to run the server.
Using the && operator within the CMD command in shell form and run both.
I've also seen an entry point script being used sometimes.
What are the tradeoffs between these options and if I'm just running a migrate command do I bother with an entry point file or is it necessary.
Would love to get some help on the same.
docker-compose run creates new containers
You have already noticed the problem. When you use docker-compose run, a new container is created.
When you ran the first command (makemigrations), a new container was created, makemigrations ran, and the migration files were written to the (new) container's filesystem.
When you ran the second command (migrate), another new container was created. The migration ran, but it had nothing to do. That's because the migration files were not available - they were written in a different container than this new one.
You can solve this in a couple of ways.
Using docker-compose exec
First, you can do what you already did, but use docker-compose exec instead of run.
docker-compose exec web python manage.py makemigrations
docker-compose exec web python manage.py migrate
exec will use the already-running container, rather than creating new containers.
Using an entrypoint script
Another option is to use an entrypoint script and run the migration there, before the server is started. This is the way to go if you'd prefer things to be more automatic.
Dockerfile:
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
entrypoint.sh:
#!/bin/sh
python manage.py makemigrations
python manage.py migrate
exec "$@"
docker-compose.yml (under 'web'):
entrypoint: /entrypoint.sh
In this scenario, when the container starts, the entrypoint script will run, handle your migration, then hand off to the command (which in this case is Django runserver).
The new containers loop forever
As you noticed, the new containers stay running. That is normally unexpected, because you overrode the command with one that should exit (rather than stay running). However, in docker-compose.yml, you specified restart: always. So they will run the migration commands over and over, restarting each time the command exits.
Dan Lowe gave a very nice answer, but the entrypoint script was not working for me. The problem is that some "makemigrations" expect your input, for instance "yes"/"no".
You can complement Dan Lowe answer with:
python manage.py makemigrations --noinput
instead of
python manage.py makemigrations
(This works at least for simple "yes"/"no" questions)
There are many ways how to achieve this.
1) Run ./manage.py migrate before you start your app (uwsgi, runserver,...) in bash script
Dockerfile
FROM debian:latest
...
# entrypoint, must be executable file chmod +x entrypoint.sh
COPY entrypoint.sh /home/docker/entrypoint.sh
# what happens when I start the container
CMD ["/home/docker/entrypoint.sh"]
entrypoint.sh
#!/bin/bash
./manage.py collectstatic --noinput
# i commit my migration files to git so i dont need to run it on server
# ./manage.py makemigrations app_name
./manage.py migrate
# here it start nginx and the uwsgi
supervisord -c /etc/supervisor/supervisord.conf -n
2) If you have a lot of migration files and you dont want any downtime, you could run the migrate command from seperate docker-compose service
docker-compose.yml
version: '3.3'
services:
# starts the supervisor (uwsgi + nginx)
web:
build: .
ports: ["80:80"]
# this service will use same image, and once the migration is done it will be stopped
web_migrations:
build: .
command: ./manage.py migrate
I solved this by doing:
docker-compose exec web /usr/local/bin/python manage.py makemigrations todo
and then :
docker-compose exec web /usr/local/bin/python manage.py migrate
I got it from this issue.