2

One thing that I can't figure out is how to set up a database host in case when we dockerize a Rail app ? For example, a Postgres DB is supposed to run on localhost on a dev machine. But in a the docker-compose file the database service has its own name, - it's on that host that the database will be accessible for other containers, foe example:

version: '3'

services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/usr/src/app
    env_file:
      - .env/development/database
      - .env/development/web
  redis:
    image: redis
  database:
    image: postgres
    env_file:
      - .env/development/database
    volumes:
      - db-data:/var/lib/postgresql/data
volumes:
  db-data:

Most examples suppose to execute all the commands related the development Rails (creating models, migrations, etc.) from inside the container, e.g.

docker-compose exec web rails g scaffold User first_name:string last_name:string

And to run the above migration I'd have to run

docker-compose exec web rails db:migrate

This way it works. But why do I need to run Docker for my dev locally to be able to access the app ?

So I come back to my original essential question: when the app was generated, database.yml had the below settings (for Postgres):

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: rails5-ember_development

This way, everybody could clone the project and continue to develop when having Postgres DB running on localhost. Now when dockerizing the app, how to change/adapt the host value, - localhost:5432 being by default so that the application could run both in a Docker container ?

So, to resume my question is:

To be able to simulate the same behaviour in a dockerized Rails app, is the only solution would be to run it in a special environment other than development? In this case, I'd add it to database.yml and set the same DB values as in docker-compose.yml file (username, host, etc.).

Thank you.

5
  • 1
    Can you please modulate your questions? It's a bit difficult to understand what exactly the problem is! Commented Jun 18, 2018 at 15:05
  • 1
    I've updated the question, see the last paragraph. Thank you. Commented Jun 19, 2018 at 7:07
  • I still don't understand what are you trying to achieve. Commented Jun 19, 2018 at 7:19
  • @emix: I'd like to be able: to dockerize a Rails app and have it to run the same way: in a Docker container and locally, i.e. to be able to develop the app in a classic way without a need to run Rails generators command without prefixing them with docker-compose exec .... Commented Jun 19, 2018 at 7:25
  • You can tell docker-compose to use specific entrypoint in which you would instantiate your container, if I understand correctly. You can do that in a separate docker-compose file. Commented Jun 19, 2018 at 7:26

1 Answer 1

1

Here is the solution I came to.

  1. Create a Dockerfile as follows in the Rails app:

F

FROM ruby:2.5.1
LABEL maintainer="Serguei CAMBOUR <[email protected]>"
RUN apt-get update -yqq
RUN apt-get install -yqq --no-install-recommends nodejs
COPY Gemfile* /usr/src/app/
WORKDIR /usr/src/app
RUN bundle install
COPY . /usr/src/app/
CMD ["rails", "s", "-b", "0.0.0.0"]
  1. Create docker-compose.yml as follows:

v

version: '3'

services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/usr/src/app
    env_file:
      - .env/development/database
      - .env/development/web
  redis:
    image: redis
  database:
    image: postgres
    env_file:
      - .env/development/database
    volumes:
      - db-data:/var/lib/postgresql/data
volumes:
  db-data:
  1. Create .env/development/database file as follows:

P

POSTGRES_USER=postgres
POSTGRES_DB=myapp_development
  1. Create .env/development/web file as follows:

DATABASE_HOST=database

  1. Change the settings in database.yml as follows to be able to read env variable values:

d

default: &default
  adapter: postgresql
  encoding: unicode
  host: <%= ENV['DATABASE_HOST'] %>
  username: <%= ENV['POSTGRES_USER'] %>
  database: <%= ENV['POSTGRES_DB'] %>
  pool: 5
  variables:
    statement_timeout: 5000

development:
  <<: *default

test:
  <<: *default
  database: myapp_test

production:
  <<: *default

Now, you can run your rails app as usual with rails s and it will work. The same is for running all the Rails generators, migrations etc, - it will work and communicate with your Postgresql DB in local.

To run your code in a docker container:

  1. Run docker-compose build web (where web is the name of my service declared in docker-compose.yml before).
  2. Or just start and build it with docker-compose up --build.
  3. Navigate to one of your routes to check if it works.
  4. Create the database if it does not exist yet: docker-compose run --rm web rails db:create.
  5. Run some pending migrations if there are some: docker-compose exec web rails db:migrate.
  6. You can combine the both: docker-compose exec web rails db:create db:migrate.

Hope this helps.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.