为什么 dockerized Rails 应用程序会提高"PG::ConnectionBad"?



我正在尝试"dockerize"现有的Rails开发应用程序。这是我第一次尝试 Docker。

在网上搜索和阅读了大量信息后,我终于设法启动并运行了一个包含多种服务的容器:app、postgres、redis、sidekiq 和 guard。

但是我在连接到数据库时遇到问题。

Starting postgres ... done
Starting redis    ... done
rails aborted!
PG::ConnectionBad: 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?
could not connect to server: Address not available
    Is the server running on host "localhost" (::1) and accepting
    TCP/IP connections on port 5432? 

毫无疑问,我忽略了一个简单的配置,但我无法弄清楚是什么或找到合适的指南。

我确实注意到 IP 地址似乎不匹配。

$ docker-compose ps
Name                  State   Ports
------------------------------------------------------
postgres              Up      0.0.0.0:5432->5432/tcp

顶部错误表明 postgres 应该在 127.0.0.1。这可能是原因吗?

谁能指出我正确的方向?

Dockerfile

# Dockerfile
FROM ruby:2.4-alpine
# Install runtime dependencies
RUN apk add --update --virtual runtime-deps postgresql-client nodejs libffi-dev readline-dev yarn git
RUN apk add --virtual build-deps build-base postgresql-dev libc-dev linux-headers libxml2-dev libxslt-dev readline-dev git 
# Copy the app's code into the container
ENV APP_HOME /app
COPY . $APP_HOME
WORKDIR $APP_HOME
# Budnle gems
RUN bundle install --jobs 4
# Install Yarn packages
RUN yarn install
RUN yarn upgrade
# Configure production environment variables
ENV RAILS_ENV=production 
    RACK_ENV=production
# Expose port 3000 from the container
EXPOSE 3000
# Run puma server
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]

docker-compose.yml

version: '3'
services:
  postgres:
    container_name: postgres
    ports:
      - "5432:5432"
    volumes:
      - $HOME/postgres-data:/var/lib/postgresql
    image: postgres:9.6.9
  redis:
    container_name: redis
    ports:
      - "6379:6379"
    links:
      - postgres
    image: redis:5.0-rc
  web:
    container_name: web
    build: .
    ports:
      - "3000:3000"
    command: /bin/sh -c "rails s -b 0.0.0.0 -p 3000"
    env_file:
      - .env
    links:
      - postgres
      - redis
  
  guard:
    build: .
    env_file:
      - .env
    command: bundle exec guard --no-bundler-warning --no-interactions
  sidekiq:
    build: .
    command: bundle exec sidekiq -C config/sidekiq.yml
    links:
      - postgres
      - redis
    env_file:
      - .env
volumes:
  redis:
  postgres:
  sidekiq:
  guard:

由于您使用的是官方的 postgres docker 容器,因此官方文档包含一些相关信息:

The PostgreSQL image sets up trust authentication locally so you may 
notice a password is not required when connecting from localhost 
(inside the same container). However, a password will be required 
if connecting from a different host/container.

由于您不在同一个容器内,因此看起来您可能需要使用 POSTGRES_USERPOSTGRES_PASSWORD .我使用您的docker-compose.ymlDockerfile在本地使用示例应用程序对此进行了测试,我需要:

  • POSTGRES_USERPOSTGRES_PASSWORD添加到相应env/environmentwebpostgres部分(您需要将它们添加到要包含的.env文件中)
  • username键和password键添加到相关部分中的database.yml中,以拉入我上面设置的环境变量

database.yml

default: &default
  adapter: postgresql
  encoding: unicode
  host: postgres
  pool: 5
  timeout: 5000
  username: <%= ENV["POSTGRES_USER"] %>
  password: <%= ENV["POSTGRES_PASSWORD"] %>

通过这些更改,我能够从 Web 容器连接到 postgres 容器/数据库。

我的docker-compose ps显示与您的相似:

   Name                      Command                State             Ports
----------------------------------------------------------------------------------------
hello_app_sidekiq_1   bundle exec sidekiq -C con ...   Exit 127
postgres              docker-entrypoint.sh postgres    Up         0.0.0.0:5432->5432/tcp
redis                 docker-entrypoint.sh redis ...   Up         0.0.0.0:6379->6379/tcp
web                   /bin/sh -c bundle exec rai ...   Up         0.0.0.0:3000->3000/tcp

我能够运行docker-compose run --rm web /bin/ash并放入rails console,运行rails db:migrate等,而上述更改没有问题。