I'm working on deploying a Rails application to Elastic Beanstalk using docker and so far everything has worked out. I'm at the point where the application needs to run migrations and seeding of the database, and I'm having trouble figuring out exactly how I need to proceed. It appears that any commands in the /.ebextensions
folder run in the context of the host machine and not the docker container. Is that correct?
I'm fine with running a command to execute migrations inside of the docker container after startup, but how do I ensure that the migrations only run on a single instance? Is there an environment variable or some other way I can tell what machine is the leader from within the docker container?
Update: I posted a question in the Amazon Elastic Beanstalk forums asking how to run "commands from Docker host on the container" on the 6th/Aug/15'. You can follow the conversations there as well as they are useful.
I'm not sure the solution you have proposed is going to work. It appears that the current process for EB Docker deployment runs container commands before the new docker container is running, which means that you can't use docker exec
on it. I suspect that your commands will execute against the old container which is not yet taken out of service.
After much trial and error I got this working through using container commands with a shell script.
container_commands:
01_migrate_db:
command: ".ebextensions/scripts/migrate_db.sh"
leader_only: true
And the script:
if [ "${PROCESS}" = "WEB" ]; then
. /opt/elasticbeanstalk/hooks/common.sh
EB_SUPPORT_FILES=$(/opt/elasticbeanstalk/bin/get-config container -k support_files_dir)
EB_CONFIG_DOCKER_ENV_ARGS=()
while read -r ENV_VAR; do
EB_CONFIG_DOCKER_ENV_ARGS+=(--env "$ENV_VAR")
done < <($EB_SUPPORT_FILES/generate_env)
echo "Running migrations for aws_beanstalk/staging-app"
docker run --rm "${EB_CONFIG_DOCKER_ENV_ARGS[@]}" aws_beanstalk/staging-app bundle exec rake db:migrate || echo "The Migrations failed to run."
fi
true
I wrap the whole script in a check to ensure that migrations don't run on background workers.
I then build the ENV in exactly the same way that EB does when starting the new container so that the correct environment is in place for the migrations.
Finally I run the command against the new container which has been created but is not yet running - aws_beanstalk/staging-app
. It exits at the end of the migration and the --rm
removes the container automatically.
Use .ebextensions/01-environment.config:
container_commands:
01_write_leader_marker:
command: touch /tmp/is_leader
leader_only: true
Now add directory /tmp to volumes in Dockerfile / Dockerrun.aws.json.
Then check set all initialization commands like db migration in sh script that first check if file /tmp/is_leader exists and executes them only in this case.
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