Skip to content

How to run database migrations at deploy time in Django-based applications

Django has built-in support for managing database schema migrations via a migrate management command. Although automatic, the migrations need to be triggered by running the appropriate management command.

Previously we baked this command into the container image for the application; each time the application started, it would ensure that the database is using the latest schema version.

While simple, this approach had some drawbacks. Aside from adding additional startup latency to the application, it also was risky if Cloud Run started two containers at the same time since database migration code might end up running twice. The best scenario in this case would be for one of the migrations to fail, thereby causing one Cloud Run container to exit.

We no longer do this. We now run database migrations as a pre-deploy job.

This how-to covers how to add pre-deploy jobs to an existing deployment.

Check that the application needs a pre-deploy job

If the application has a docker-entrypoint.sh file which contains an explicit ./manage.py migrate command, you do not need to move to using a pre-deploy job but we strongly encourage you to do so. This can be done by a) forward-porting boilerplate changes to the application and b) updating the deployment as outlined in this how-to guide.

Move to version 8 of the Cloud Run terraform module or better

In webapp.tf, check that you are using version 8 or better of our Google Cloud Run terraform module. Pre-deployment job support was added in version 8.1.0.

Add the pre-deploy job configuration

Add one of the following configurations to the webapp.tf file depending on the version of the gcp-cloud-run-app module being used.

For gcp-cloud-run-app module versions >= 8.1.0 and < 9.0.0:

module "webapp" {
  source  = "gitlab.developers.cam.ac.uk/uis/gcp-cloud-run-app/devops"
  version = "~> 8.1"

  # ...

  enable_pre_deploy_job  = true
  pre_deploy_job_command = ["python3"]
  pre_deploy_job_args    = ["/usr/src/app/manage.py", "migrate"]
}

For gcp-cloud-run-app module versions >= 9.0.0:

module "webapp" {
  source  = "gitlab.developers.cam.ac.uk/uis/gcp-cloud-run-app/devops"
  version = "~> 9.0"

  # ...

  enable_pre_deploy_job = true
  pre_deploy_job_container = {
    image   = "image:tag", # need to specify image
    command = ["python3"],
    args    = ["/usr/src/app/manage.py", "migrate"]
  }
}

An example of this configuration can be found in the deployment of the Regent House Ballots application.

Summary

In this how-to, you learned how to add a pre-deploy job to a Cloud Run deployment in order to run database migrations.

Next steps