How do I run Rails in Docker? PG::ConnectionBad could not translate host name "pg" to address: No address associated with hostname

12,191

Solution 1

Ok, I'll try to answer this:

Usually when this error appears, it probably means that running the db container returned some errors and it stopped.

I had the same issue and after some digging found that I had

LANG='en_US.UTF-8'
LANGUAGE='en_US:en'
LC_ALL='en_US.UTF-8'

set in my environment variable and that caused the db container to stop. Therefore as the container was not running, I had no db host.

Here is how my docker-compose.yml file looks like:

version: '3'

services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    env_file: .env
  app:
    build: .
    command: bundle exec puma -p 3000 -C config/puma.rb
    env_file: .env
    volumes:
      - .:/app
    ports:
      - "3031:3000"
    depends_on:
      - db

Here is config/database.yml

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  pool: 5
  username: <%= ENV['POSTGRES_USER'] %>
  password: <%= ENV['POSTGRES_PASSWORD'] %>

development:
  <<: *default
  database: driggl_dev

test:
  <<: *default
  database: driggl_test

production:
  <<: *default
  database: driggl_prod

...and the .env file for development:

POSTGRES_USER=driggl
POSTGRES_PASSWORD=driggl

As I had shared volumes for db data, I removed the tmp/db folder from the repository just to be sure.

rm -rf tmp/*

then I removed all containers and images

docker rm $(docker ps -q -a) -f
docker rmi $(docker images -q) -f

Finally I spin up containers again:

docker-compose up --build

and everything finally went right.

Summary

  1. Make sure there is nothing cached somewhere in the system
  2. Make sure your db container does not return errors while launching.

I hope that will help anyone who'll encounter that problem.

Solution 2

This setup works for me running rails on docker. Basically need to specify a URL so you'll use a .env file to specify the postgres url and you'll change between _development _test and _production using your config/database file just make you add the env. file to your web service docker-compose file:

/docker-compose.yml:

services:
  postgres:
    image: postgres:9.6
    restart: always
    environment:
      POSTGRES_USER: kunzig #DockerHub postgres docs state this is optional but must be used when password is set.  It will also create a db under the supplied username which you'll use to connect to in rails console such as: $docker-compose exec postgres psql -U YourUserNameHere
      POSTGRES_PASSWORD: 'whateverPWYouWant'
    ports:
      - '5432' #Was originally 5432:5432 with the Left hand side being port on host machine, right hand side is the port on the docker container.  However I let docker choose the port it will use by supplying because 5432 is running on my local for other projects.  
    volumes:
      - postgres:/var/lib/postgresql/data 



  web:
    build: . #Runs the docker build command on the current directory
    links: #Links the listed services to our application so containers can talk to eachother
      - postgres
      - redis
    restart: always
    volumes:
      - .:/kunzig #Left hand side is current directory of compose file, right hand side is container folder.  This needs to be same as Install_path folder in Dockerfile.
    ports:
      - '8000:8000' #Left is the local port and the right side is the container port
    env_file:
      - .YourProjectNameHere.env #This should be in your root project directory along side the Dockerfile and docker-compose file
    depends_on:
      - 'redis'
      - 'postgres'

/.projectname.env

DATABASE_URL=postgresql://PostgresUserNameHere:PasswordFromDockerCompose@postgres:5432/PostgresUsername?encoding=utf8&pool=5&timeout=5000

/config/database.yml

development:
  url: <%= ENV['DATABASE_URL'].gsub('?', '_development?' ) %>
test:
  url: <%= ENV['DATABASE_URL'].gsub('?', '_test?' ) %>
production:
  url: <%= ENV['DATABASE_URL'].gsub('?', '_production?' ) %>

Keep your web service linked with the pg service as you have it and you should be good to go just note I called my service postgres instead.

Solution 3

I had this same issue. For the life of me I could not figure out why it was happening. Debugged for quite a while, but could not figure out how to make the container_name for the db container resolve within my database.yml file. Even weirder was the fact that in a different computer the same configuration was working totally fine.

Eventually I found out that if you use host.docker.internal it is essentially the equivalent of localhost within Docker.

So I changed my database.yml file to be:

default: &default
  adapter: postgresql
  encoding: unicode
  host: host.docker.internal
  port: 5432
  username: <%= ENV['DATABASE_USERNAME'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>

And it all worked out. Mind you I have heard this does not work in Unix systems. I am using OS X and this works fine.

Share:
12,191
Chloe
Author by

Chloe

Updated on June 20, 2022

Comments

  • Chloe
    Chloe almost 2 years

    I tried to follow the guide here: https://docs.docker.com/compose/rails/

    docker-compose.yml
    version: '3'
    services:
      pg:                                     ######### LOOK HERE!
        image: postgres
        volumes:
          - ./tmp/db:/var/lib/postgresql/data
      web:
        build: .
        command: bundle exec rails server -p 3000 -b '0.0.0.0'
        volumes:
          - .:/app
        ports:
          - "3000:3000"
        depends_on:
          - pg
        links:
          - pg                                     ######### LOOK HERE!
      cms:
        image: joomla
        restart: always
        links:
          - mysql:joomladb
        ports:
          - 8080:80
        environment:
          JOOMLA_DB_HOST: mysql
          JOOMLA_DB_PASSWORD: example
      mysql:
        image: mysql:5.6
        restart: always
        environment:
          MYSQL_ROOT_PASSWORD: example
    
    config/database.yml
    # SQLite version 3.x
    #   gem install sqlite3
    #
    #   Ensure the SQLite 3 gem is defined in your Gemfile
    #   gem 'sqlite3'
    #
    default: &default
      adapter: postgresql
      encoding: unicode
      pool: 5
      timeout: 5000
      host: pg                                     ######### LOOK HERE!
      username: postgres
      password:
    
    development:
      <<: *default
      database: project
    
    # Warning: The database defined as "test" will be erased and
    # re-generated from your development database when you run "rake".
    # Do not set this db to the same as development or production.
    test:
      <<: *default
      database: project_test
    
    production:
      <<: *default
      database: project
    

    Console

    C:\Users\Chloe\workspace\project\src>docker-compose run web rake db:create
    Starting src_pg_1 ... done
    could not translate host name "pg" to address: No address associated with hostname
    Couldn't create database for {"adapter"=>"postgresql", "encoding"=>"unicode", "pool"=>5, "timeout"=>5000, "host"=>"pg", "username"=>"postgres", "password"=>nil, "database"=>"project"}
    rake aborted!
    PG::ConnectionBad: could not translate host name "pg" to address: No address associated with hostname
    

    docker-compose version 1.20.1, build 5d8c71b2, Docker version 18.03.0-ce, build 0520e24302

  • Chloe
    Chloe about 6 years
    But you still use the hostname @postgres:5432 so if it can't find the hostname now, how will it by using a URL containing the hostname?
  • JosephK
    JosephK almost 5 years
    There must be a way to do this without combining the containers in one compose file, and building them together. Docker has its own network - how to address to it in the database.yml file?
  • Toshihiro Yokota
    Toshihiro Yokota over 3 years
    This answer saved my day.