I followed a Docker + Django tutorial which was great, in that I could successfully build and run the website following the instructions. However, I can't for the life of me figure out how to successfully run a database migration after changing a model.
Here are the steps I've taken:
- Clone the associated git repo
Set up a virtual machine called
dev
- with
docker-machine create -d virtualbox dev
- and point to it with
eval $(docker-machine env dev)
- with
Built and started it up with:
docker-compose build
- and
docker-compose up -d
Run initial migration (the only time I'm able to run a migration that appears successful):
docker-compose run web python manage.py migrate
Checked that the website works by navigating to the IP address returned by:
docker-machine ip dev
Make a change to a model. I just added this to the
Item
model in web/docker_django/apps/todo/models.py file.:name = models.CharField(default='Unnamed', max_length=50, null=False)
Update the image and restart the containers with:
docker-compose down --volumes
- then
docker-compose build
- then
docker-compose up --force-recreate -d
Migration attempt number 1:
I used:
docker-compose run web python manage.py makemigrations todo
Then:
docker-compose run web python manage.py migrate
After the makemigrations
command, it said:
Migrations for 'todo':
0001_initial.py:
- Create model Item
When I ran the migrate
command, it gave the following message:
Operations to perform:
Synchronize unmigrated apps: messages, todo, staticfiles
Apply all migrations: contenttypes, admin, auth, sessions
Synchronizing apps without migrations:
Creating tables...
Running deferred SQL...
Installing custom SQL...
Running migrations:
No migrations to apply.
So that didn't work.
Migration attempt number 2:
This time I tried running migrations from directly inside the running web container. This looked like this:
(macbook)$ docker exec -it dockerizingdjango_web_1 bash
root@38f9381f179b:/usr/src/app# ls
Dockerfile docker_django manage.py requirements.txt static tests
root@38f9381f179b:/usr/src/app# python manage.py makemigrations todo
Migrations for 'todo':
0001_initial.py:
- Create model Item
root@38f9381f179b:/usr/src/app# python manage.py migrate
Operations to perform:
Synchronize unmigrated apps: staticfiles, messages
Apply all migrations: contenttypes, todo, admin, auth, sessions
Synchronizing apps without migrations:
Creating tables...
Running deferred SQL...
Installing custom SQL...
Running migrations:
Rendering model states... DONE
Applying todo.0001_initial...Traceback (most recent call last):
File "/usr/local/lib/python3.5/site-packages/django/db/backends/utils.py", line 62, in execute
return self.cursor.execute(sql)
psycopg2.ProgrammingError: relation "todo_item" already exists
Moreover, I couldn't find any migrations
folders in that container.
I clearly have very little idea what's happening under the hood here, so if someone could show me how to successfully change models and run database migrations I would much appreciate it. Bonus points if you can help me conceptualize what's happening where when I run these commands that have to get the web and postgres images to work together.
EDIT: What worked for me
@MazelTov's suggestions will all be helpful for automating the process as I get more used to developing with Docker, but the thing I was missing, that @MazelTov filled me in on in a very helpful discussion, was mounting so that migrations show up in my local machine.
So basically, my Migration Attempt 1 would have worked just fine if instead of, for example:
docker-compose run web python manage.py makemigrations todo
...I used:
docker-compose run --service-ports -v $(pwd)/web:/usr/src/app web python manage.py makemigrations todo