Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker Compose: Rails won't respect the DATABASE_URL to connect to Postgres

I'm trying to containerize my Ruby on Rails 5.1.0 application, but I'm having some trouble with it not picking up DATABASE_URL from the environment. In docker-compose.yml, I have the following service:

app:
  build: .
  command: bundle exec rails s -p 3000 -b '0.0.0.0'
  volumes:
    - .:/myapp
  environment:
    DATABASE_URL: postgres://postgres:pw@db:5432/myapp_development

The environment gets picked up just fine if I run docker-compose run app rails c:

$ docker-compose run app rails c
Running via Spring preloader in process 25
Loading development environment (Rails 5.1.0)
irb(main):001:0> ENV['DATABASE_URL']
=> "postgres://postgres:pw@db:5432/myapp_development"

But then if I run docker-compose run app rake db:create, I get an error about not being able to connect to localhost:

$ docker-compose run app rake db:create
Database 'myapp_development' already exists
could not connect to server: Connection refused
    Is the server running on host "localhost" (::1) and accepting
    TCP/IP connections on port 5432?
could not connect to server: Connection refused
    Is the server running on host "localhost" (127.0.0.1) and accepting
    TCP/IP connections on port 5432?
Couldn't create database for {"adapter"=>"postgresql", "host"=>"localhost", "pool"=>10, "timeout"=>5000, "database"=>"myapp_test"}
rake aborted!

Any idea what I'm doing wrong here?

Edit: Here's what database.yml looks like:

common: &common
  adapter: postgresql
  pool: 10
  timeout: 5000

development:
  <<: *common
  database: myapp_development

test:
  <<: *common
  database: myapp_test

production:
  <<: *common
  database: myapp_production
like image 843
Sam Starling Avatar asked May 19 '17 12:05

Sam Starling


2 Answers

I also had a similar issue, the causes of which were multi-fold.

TL;DR, make sure that:

  1. Your app container is correctly linked to and dependent on your postgres container
  2. Your DATABASE_URL references the correct hostname of your postgres container
  3. The RAILS_ENV ENV variable is explicitly set within your app container

First off, I had to make sure my app container in docker_compose.yml was linked to and depended on the postgres container:

version: '3'
    services:
      app:
        container_name: 'app'
        depends_on:
          - postgres
        links:
          - postgres

Second, the DATABASE_URL ENV variable I was providing database.yml did not reference the correct hostname of the postgres container. Originally, mine looked like:

'postgres://postgres:@localhost:5432/my_app_development'

I changed it to:

'postgres://postgres:@postgres:5432/my_app_development'

Not an apparent issue in your case, but worth noting for others.

Third, I wasn't explicitly specifying the RAILS_ENV environment. I set that ENV variable to development in docker_compose.yml so that the correct database.yml configuration was used.

The end result of my database.yml file:

development: &default
  adapter: postgresql
  encoding: unicode
  database: my_app_development
  username: postgres
  pool: 5
  timeout: 5000
  url: <%= ENV['DATABASE_URL'] %>

test:
  <<: *default
  database: my_app_test
  pool: 5
  url: <%= ENV['DATABASE_URL'] %>

production:
  <<: *default
  url: <%= ENV['DATABASE_URL'] %>

The end result of my docker_compose.yml file:

version: '3'
services:
  app:
    container_name: 'app'
    environment:
      DATABASE_URL: 'postgres://postgres:@postgres:5432/my_app_development'
      RAILS_ENV: 'development'
    build: .
    ports:
      - '3000:3000'
    volumes:
      - ./:/dev
    depends_on:
      - postgres
    links:
      - postgres
    tty: true

  postgres:
    container_name: 'postgres'
    image: postgres:9.5
    ports:
      - '5432:5432'
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD:

After that, all bundle exec rake db: commands worked just fine.

Hope that helps!

like image 144
user3006381 Avatar answered Sep 23 '22 06:09

user3006381


The problem is in the rake task, it is trying to create the test database, I assume your database.yml has a test environment with localhost host.

From the description of rake db:create

Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create all databases in the config). Without RAILS_ENV it defaults to creating the development and test databases

You should pass the env evidently or it could create a test database by default.

I suggest you to change the test database credentionals in the database.yml.

Connection Preference

like image 33
Philidor Avatar answered Sep 22 '22 06:09

Philidor