I am working on a Django app, and I would like my Database migrations to be run when deploying on Heroku.
So far we have simply put the following command in the Procfile:
python manage.py migrate
When deploying the migrations are indeed run, but they seem to be run once for each dyno (and we use several dynos). As a consequence, data migrations (as opposed to pure schema migrations) are run several times, and data is duplicated.
Running heroku run python manage.py migrate
after the deployment is not satisfactory since we want the database to be in sync with the code at all times.
What is the correct way to do this in Heroku?
Thanks.
migrate executes those SQL commands in the database file. So after executing migrate all the tables of your installed apps are created in your database file. You can confirm this by installing SQLite browser and opening db.
Deployment requires access to heroku-cli in order to run migrations. This can prove problematic when doing continous deployment from a CI server. If migrations fail your application might be left in a non-functional state until the migration is fixed.
We use Heroku for running some of our customers applications. Deploying by a simple git push is great, but running migrations as part of the process have always been a sore point - until now. The initial approach we took was to run migrations by hand after deploy: You have to remember to run them.
This means that when you disconnect from the dyno the files created by the makemigrations command will be destroyed. Commit your migration files to Github (or your source control system) and then run the migrate command on the Heroku shell - recommended Create the migration files and then run the migration on the heroku bash shell.
Another solution is to use custom buildpacks to handle running your migrations. Herokus existing ruby-buildpack runs rails assets:precompile and other tasks on deploy for us. Unfortunately, rails db:migrate hasn’t made the cut. It is possible to fork the buildpack and run your own, or add a buildpack that handles migrations for you.
Heroku releases can run concurrently, which can be a problem if the release phase is executing a database migration. Many popular relational databases, such as Postgres and MySQL, offer advisory lock functionality, which can be used to prevent concurrent migrations.
This is my Procfile and it is working exactly as you describe:
release: python manage.py migrate web: run-program waitress-serve --port=$PORT settings.wsgi:application
See Heroku docs on defining a release process: https://devcenter.heroku.com/articles/release-phase#defining-a-release-command
The release command is run immediately after a release is created, but before the release is deployed to the app’s dyno formation. That means it will be run after an event that creates a new release:
- An app build
- A pipeline promotion
- A config var change
- A rollback
- A release via the platform API
The app dynos will not boot on a new release until the release command finishes successfully.
If the release command exits with a non-zero exit status, or if it’s shut down by the dyno manager, the release will be discarded and will not be deployed to the app’s formation.
Be aware, however, this feature is still in beta.
When you have migrations that remove models and content types, Django requires a confirmation in the console
The following content types are stale and need to be deleted:
...
Any objects related to these content types by a foreign key will also be deleted. Are you sure you want to delete these content types? If you're unsure, answer 'no'. Type 'yes' to continue, or 'no' to cancel:
The migrate command in your Procfile does not respond and the release command fails. In this scenario, remove the migrate line, push live, run the migrate command manually, then add it back for future deploys.
The migrate does automatically runs on Heroku, but for now you can safely do it once your dyno is deployed with heroku run python manage.py migrate
.
If production, you can put your app in maintenance first with heroku maintenance:on --app=<app name here>
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