I have a Django service running inside Docker that I deploy to AWS Elastic Beanstalk.
I would like to run my database migrations at deploy-time
If I were deploying to EB as "a Python project", I could have the following in my .ebextensions:
$ cat .ebextensions/01run.config 
container_commands:
    01migrate:
        command: "python manage.py migrate --noinput"
        leader_only: true
However, container_commands are for the EC2 instances - and it's inside the Docker container that I have my code etc.
I can't just add it to my Dockerfile, because applying migrations is all about operating on the attached RDS instance (supplied by the environment) - not really "part of building the Docker image"
There doesn't seem to be anything useful I can add to Dockerrun.aws.json
I could perhaps identify the Docker image name inside my container_commands and then do docker run -ti $container-name python manage.py migrate etc., but no idea how and it feels awfully hacky
I could run the migrations by hand
I could replace CMD gunicorn $etc with CMD $script, where $script applies migrations and then starts gunicorn.
Ideas very much welcomed please!
This platform branch offers both single-container and multi-container support. Elastic Beanstalk deploys a Docker image and source code to EC2 instances on this platform branch. Use the Docker Compose tool on the Docker platform to simplify your application configuration, testing, and deployment.
You could add a post deploy script in your .ebextensions like so:
files:
  "/opt/elasticbeanstalk/hooks/appdeploy/post/10_migrate.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash
      if [ -f /tmp/leader_only ]; then
        echo "Running Migrations"
        container_id=`docker ps -q --no-trunc --filter label="com.amazonaws.ecs.container-name=MY_CONTAINER_NAME" | head -n 1`
        docker inspect $container_id
        docker exec $container_id /entrypoint.sh python manage.py migrate --noinput
      fi
  "/opt/elasticbeanstalk/hooks/appdeploy/post/90_rm_leader_only.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/usr/bin/env bash
      if [ -f /tmp/leader_only ]; then
        echo "Deleting leader_only file"
        rm /tmp/leader_only
      fi
container_commands:
  01_touch_the_leader:
    command: |
      #!/usr/bin/env bash
      touch /tmp/leader_only
    leader_only: true
I have included the leader only bit in case you might be using a load balanced environment, it won't run migrations on multiple servers at once.  This can also be used for the collectstatic command.
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