Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker Compose + Rails: best practice to migrate?

I just followed this article on Running a Rails Development Environment in Docker. Good article, works great. After setting everything up, I decided to go on and set up a production environment.

GOAL:

I want to rake db:create && rake db:migrate every time my docker image is run.

PROBLEM:

If I move the database creation and migrations steps...

docker-compose run app rake db:create docker-compose run app rake db:migrate 

...into the Dockerfile...

RUN rake db:create && rake db:migrate 

...that will throw an error...

could not translate host name "postgres" to address: Name or service not known 

...because the host in my database.yml...

default: &default   adapter: postgresql   encoding: unicode   pool: 5   timeout: 5000   username: postgres   host: postgres   port: 5432  development:   <<: *default   database: rails_five_development 

...is set to the postgres service name specified in my docker-compose.yml...

version: "2" services:   postgres:     image: postgres:9.5     ports:       - "5432"   app:     build: .     command: rails server -p 3000 -b '0.0.0.0'     volumes:       - .:/app     ports:       - "3000:3000"     links:       - postgres 

...since that is the recommended practice as pointed by the article.

QUESTION:

How can I automatically rake db:create && rake db:migrate every time my docker image is run?

I am trying to achieve the same thing as in this question

like image 708
João Souza Avatar asked Jun 29 '16 03:06

João Souza


People also ask

How do I run migration in Docker rails?

Luckily, you can use docker-compose run to execute one-off commands within a container. To run rake db:migrate in the Rails container, say docker-compose run web rake db:migrate . You'll see the migration running, and then you can continue on your merry way.

How do I migrate a specific migration in rails?

To run a specific migration up or down, use db:migrate:up or db:migrate:down . The version number in the above commands is the numeric prefix in the migration's filename. For example, to migrate to the migration 20160515085959_add_name_to_users. rb , you would use 20160515085959 as the version number.

Why do we need migration in rails?

A Rails migration is a tool for changing an application's database schema. Instead of managing SQL scripts, you define database changes in a domain-specific language (DSL). The code is database-independent, so you can easily move your app to a new platform.


2 Answers

From https://docs.docker.com/engine/reference/builder/#cmd:

If you would like your container to run the same executable every time, then you should consider using ENTRYPOINT in combination with CMD. See ENTRYPOINT

https://docs.docker.com/engine/reference/builder/#entrypoint

tl;dr

You could define an entrypoint under app and define a bash file there:

app:   entrypoint: [bin/entry]   .. 

bin/entry file example:

#!/bin/bash set -e  rake db:create rake db:migrate  exec "$@" 
like image 119
Ho Man Avatar answered Oct 03 '22 21:10

Ho Man


This approach creates the database if the migration is not able to succeed. It also avoids the issue of being unable to start the server because a pid file was left behind. Create the file as app/lib/docker-entrypoint.sh.

#!/bin/sh # https://stackoverflow.com/a/38732187/1935918 set -e  if [ -f /app/tmp/pids/server.pid ]; then   rm /app/tmp/pids/server.pid fi  bundle exec rake db:migrate 2>/dev/null || bundle exec rake db:setup  exec bundle exec "$@" 

The docker-compose.yml then includes:

entrypoint: ["/app/lib/docker-entrypoint.sh"] command: ["rails","server","-b","0.0.0.0","-p","3000"] 
like image 41
Dan Kohn Avatar answered Oct 03 '22 20:10

Dan Kohn