Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deploy-time commands inside Docker on Elastic Beanstalk

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.

Things I've already looked at

  • 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

Hacky options I've identified so far

  • 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.

    • This is the least awful thing I've identified so far, and what I'm about to do as a stopgap measure.
    • This means "try to apply migrations every time I start an instance" which does not leave me comfortable and happy.

Ideas very much welcomed please!

like image 701
Kristian Glass Avatar asked May 19 '15 09:05

Kristian Glass


People also ask

Can Elastic Beanstalk deploy Docker?

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.


1 Answers

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.

like image 113
A. J. Parr Avatar answered Sep 28 '22 10:09

A. J. Parr