【问题标题】:Docker, Rails, Postgres - db service not found errorDocker、Rails、Postgres - 找不到数据库服务错误
【发布时间】:2019-11-15 03:04:07
【问题描述】:

Dockerfile

FROM ruby:2.6.3
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
RUN mkdir /paper_scammer_docker
WORKDIR /paper_scammer_docker
COPY Gemfile /paper_scammer_docker/Gemfile
COPY Gemfile.lock /paper_scammer_docker/Gemfile.lock
RUN bundle install
COPY . /paper_scammer_docker

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]

docker-compose.yml

version: '3'
services:
  db:
    image: postgres:10
    ports:
      - "5432:5432"
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/paper_scammer_docker
    ports:
      - "3000:3000"
    links:
      - "db:db"
    depends_on:
      - db

我可以使用以下命令成功构建映像

docker-compose build

如果我在项目根目录中执行docker-compose up,我的应用程序运行良好,当我执行docker container ls 时,我可以看到两个容器,一个用于我的rails 应用程序,另一个用于postgres。我观察到 postgres 图像是从库中加载的。

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: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000
  host: db
  username: postgres
  password:
  # user: gnpsllco_papaer
  # password: sharma@123

development:
  <<: *default
  database: paper_scammer_development
  # user: postgres
  # password: sharma@123

# 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: paper_scammer_test
  # user: postgres
  # password: sharma@123

production:
  <<: *default
  database: gnpsllco_paper_scammer

问题

我运行以下命令从我的 rails 应用程序的映像启动 docker 容器。

sudo docker run -p 3000:3000 paperscammer_web

postgres 容器未运行或丢失。

我想了解这个 dockerfile-compose 是如何处理这个问题的,当我旋转 rails 应用程序的图像时,它说它依赖于 postgres 服务,它不应该也旋转一个 postgres 容器并将“db”设置为连接主机。

或者是否需要为 postgres 手动旋转。

运行http://localhost:3000时出现以下错误

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

我可以看到 postgres 容器没有运行。

谢谢

【问题讨论】:

  • 您是否尝试过在 database.yml 文件中指定端口? port: 5432
  • You can see postgres container is not running,为什么不docker logs your_postgres_container 来查找日志?

标签: ruby-on-rails docker docker-compose dockerfile


【解决方案1】:

sudo docker run -p 3000:3000 paperscammer_web 将只启动 Web 服务器,您需要运行 docker-compose

sudo docker-compose up -d --build

第二个选项:

 sudo docker run --name db -p 5432:5432 -v ./tmp/db:/var/lib/postgresql/data postgres:10
 sudo docker run -p 3000:3000 --link db:db -v .:/paper_scammer_docker paperscammer_web

【讨论】:

  • 是的,但是在生产中部署时如何扩展,docker-compose up 会查找 docker 文件,如果您遵循此docs.docker.com/get-started/part3。 docker-compose 文件中定义的服务应该把所有的服务作为容器
  • 使用 compose 可以正常工作,但是当我运行 docker run -p 3000:3000 papercammer_web 时,rails 应用程序映像无法正常工作。您必须知道 docker compose 将创建图像然后启动。但对于 docker compose build 生成的生产部署输出,会生成一个用于旋转容器的图像。
  • 是的,我的应用程序现在可以连接到数据库服务,但是这次没有创建数据库错误
  • 致命:数据库“paper_scammer_development”不存在,docker run 命令未运行 buundle exec rake db:create 如 docker 文件中所述
  • 我认为遵循这应该有助于docs.docker.com/engine/examples/postgresql_service。如果数据库已经存在,我必须添加创建数据库命令并跳过它。你怎么建议?拥有自己的 dockerfile 来创建 postgres 图像。
【解决方案2】:

解决方案

./Dockerfile

ROM ruby:2.6.3-alpine

ENV BUNDLER_VERSION=2.0.2

RUN apk add --update --no-cache \
      binutils-gold \
      build-base \
      curl \
      file \
      g++ \
      gcc \
      git \
      less \
      libstdc++ \
      libffi-dev \
      libc-dev \ 
      linux-headers \
      libxml2-dev \
      libxslt-dev \
      libgcrypt-dev \
      make \
      netcat-openbsd \
      nodejs \
      openssl \
      pkgconfig \
      postgresql-dev \
      python \
      tzdata \
      yarn 

RUN mkdir -p /app
WORKDIR /app

COPY Gemfile* ./
RUN gem install bundler
RUN bundle config build.nokogiri --use-system-libraries
RUN bundle check || bundle install 

COPY package.json yarn.lock ./
RUN yarn install --check-files

COPY . ./

COPY ./sh/entrypoints/docker-entrypoint.sh /usr/bin/entrypoint.sh
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

./.env

APP_NAME=api
APP_PORT=3100

DATABASE_NAME=rails_db
DATABASE_USER=batman
DATABASE_PASSWORD=super_pass_123
DATABASE_PORT=5342
DATABASE_HOST=api_db # must be equal to the name of the postgres service in docker-compose.yml

./docker-compose.yml

version: '3.7'
services:
  api: 
    build:
      context: .
      dockerfile: Dockerfile
    container_name: ${APP_NAME}
    depends_on:     
      - api_db
    ports: 
      - "${APP_PORT}:${APP_PORT}"
    volumes:
      - .:/app
      - gem_cache:/usr/local/bundle/gems
      - node_modules:/app/node_modules
    env_file: .env
    environment:
      RAILS_ENV: development

  api_db: # must be equal to `DATABASE_HOST ` in ./.env
    image: postgres
    command: postgres -c logging_collector=on -c log_destination=stderr -c log_directory=/logs -p ${DATABASE_PORT}
    ports:
      - "${DATABASE_PORT}:${DATABASE_PORT}"
    volumes:
      - db_data:/var/lib/postgresql/data
      - ./log/db:/logs
    environment:
      - POSTGRES_USER=${DATABASE_USER}
      - POSTGRES_PASSWORD=${DATABASE_PASSWORD}
      - POSTGRES_DB=${DATABASE_NAME}

volumes:
  gem_cache:
  db_data:
  node_modules:  

./sh/entrypoints/docker-entrypoint.sh

https://stackoverflow.com/a/59047028/4488252

DB_INITED=0
if db_version=$(bundle exec rake db:version 2>/dev/null)
then
    if [ "$db_version" = "Current version: 0" ]
    then
        echo "DB is empty"
    else
        echo "DB exists"
        DB_INITED=1
    fi
    bundle exec rake db:migrate 
else
    echo "DB does not exist"
    bundle exec rake db:setup
fi

if [ $DB_INITED == 0 ]
then
    echo "Performing initial configuration"
    # init some plugins, updated db if need, add initial data
fi

./config/database.yml

default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  database: <%= ENV['DATABASE_NAME'] %>
  username: <%= ENV['DATABASE_USER'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>
  port: <%= ENV['DATABASE_PORT'] || '5432' %>
  host: <%= ENV['DATABASE_HOST'] %>

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default

./.dockerignore

https://gist.github.com/neckhair/ace5d1679dd896b71403fda4bc217b9e

.git
.gitignore
README.md

#
# OS X
#
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

#
# Rails
#
.env
.env.sample
*.rbc
capybara-*.html
log
tmp
db/*.sqlite3
db/*.sqlite3-journal
public/system
coverage/
spec/tmp
**.orig

.bundle

.ruby-version
.ruby-gemset

.rvmrc

# if using bower-rails ignore default bower_components path bower.json files
vendor/assets/bower_components
*.bowerrc
bower.json

用法

https://docs.docker.com/compose/reference/down/

构建并运行:docker-compose up --build -d

https://docs.docker.com/compose/reference/down/

停止:docker-compose down

停止 + 删除图像和卷:docker-compose down --rmi all --volumes

【讨论】:

    【解决方案3】:

    docker-compose updocker run 是不同的命令。使用后者不会使用 compose 文件,只会使用传递给命令的参数。

    当你使用docker run 时,你必须指定你想具体运行哪些容器,如果你想同时运行dbweb 你应该使用这个命令两次。

    另一方面,当您使用docker-compose up 时,您将运行docker-compose.yml 中指定的所有容器及其所有选项。

    另外,depends_on 属性只是指定容器web 将在容器db 成功启动后启动。

    最后,如果您希望您的容器能够相互通信,您应该在 compose 文件中添加一个网络:

    version: '3'
    services:
      db:
        image: postgres:10
        container_name: db
        ports:
          - "5432:5432"
        volumes:
          - ./tmp/db:/var/lib/postgresql/data
        networks:
          - my-network-name
    
      web:
        build: .
        container_name: web
        command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
        volumes:
          - .:/paper_scammer_docker
        ports:
          - "3000:3000"
        links:
          - "db:db"
        depends_on:
          - db
        networks:
          - my-network-name
    
    networks:
      my-network-name:
        driver: bridge
    

    添加container_name 以引用它们也是一个好习惯。

    有了这些选项,容器现在可以使用它们的名称作为 IP/主机名进行通信:

    http://<container_name>:<port>
    

    例如,容器web 将能够像这样连接到db 容器中的数据库:

    http://db:5432/gnpsllco_paper_scammer
    

    请注意,IP/主机名现在是容器的名称。

    正如@LinSel 指出的那样,您可以使用命令构建和运行所有容器(不需要sudo):

    docker-compose up -d --build
    

    【讨论】:

    • 但是我仍然使用源代码来构建图像,我想找到共享图像的解决方案。
    • 抱歉您的问题不清楚,您所说的“共享图像”是什么意思?在 Docker Hub 中发布的图像?
    • 在构建镜像之后,这个镜像将被注册到 dockerhub 并且很少有工具可以从 dockerhub 中选择镜像并旋转 AWS ECS
    • 正如你提到的我必须运行docker run 两次,这对我来说很好。我现在不知道如何运行数据库迁移,因为 'docker run papercammer bundle exec rake db:migrate` 只运行迁移并退出而不启动容器
    猜你喜欢
    • 1970-01-01
    • 2014-10-24
    • 2022-07-13
    • 1970-01-01
    • 2014-10-08
    • 1970-01-01
    • 2020-05-14
    • 1970-01-01
    • 2021-03-04
    相关资源
    最近更新 更多