ruby-on-rails - 对构建过程依赖于与另一个容器通信的应用程序进行 Docker 化

标签 ruby-on-rails docker docker-compose

我有一个 Ruby on Rails 应用程序,我正在尝试将其容器化,以便我可以使用 Docker 部署它:

version: '3.4'
services:
  db:
    image: postgres
  web:
    container_name: my_rails_app
    build: .
    ports:
      - "3000:3000"
    depends_on:
      - db

作为此应用程序现有构建过程的一部分,当前存在一个脚本,它使用大量示例数据启动应用程序的测试版本,并截取应用程序各种功能的多个屏幕截图以用于帮助文件.此脚本已集成到 Ruby on Rails 的 Assets 管道中,因此它作为正常 Assets 预编译过程的一部分运行(下面的 Dockerfile 有所简化):

FROM ruby:2.2.10 AS build

COPY . /opt/my_rails_app
RUN bundle install

# Generates static assets, including screenshots
RUN bundle exec rake assets:precompile

RUN bundle install --deployment --without development test assets


FROM ruby:2.2.10 AS production

ENV RAILS_ENV=production

COPY . /opt/my_rails_app
COPY --from=build vendor/bundle vendor/bundle
COPY --from=build public/assets public/assets

CMD ["bundle", "exec", "rails", "server"]
EXPOSE 3000

现在这是我的问题:因为此构建步骤启动 Web 服务器以获取 UI 的屏幕截图,它需要能够在构建期间连接到数据库。 (如果没有数据库连接,Web 服务器将无法正常运行。)

在旧环境中,这不是问题,因为生产数据库安装在应用程序所在的同一台服务器上,所以我可以让它连接到本地主机。但是,使用 Docker 时,数据库在由 docker-compose 管理的单独容器中运行。不幸的是,Docker 似乎不想让我在构建期间与那个容器对话:

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

我考虑过将预编译步骤推迟到部署之后;但这会显着减慢容器的部署过程,并且需要我在我的生产容器中包含另外 50-100 个没有以其他方式使用的依赖项。

我还考虑过在构建容器上安装数据库,但这似乎会降低构建速度,如果构建容器上的数据库与 postgres 图片提供。

有没有办法告诉 docker 在构建过程中启动容器并设置适当的网络连接?或者可能是没有我上面已经考虑过的其他解决方案的任何缺点的替代解决方案?

最佳答案

这是可以做到的,但目前 Docker Compose 对它的支持不是很好。

你想要做的是使用 Docker's built-in networking features设置包含数据库容器的共享网络,然后在构建过程中将您的应用程序容器附加到该网络。

如果没有 Docker Compose,这将通过使用 docker network 启动数据库容器来完成。子命令将其连接到 docker 网络,然后使用 docker build --network $network_name_here . 构建应用程序容器。

使用 Docker Compose,这可以通过其 name 为应用程序的默认网络配置静态名称来实现。属性,然后对服务使用未记录的 network 选项 build参数告诉 Compose 在构建期间为您的应用程序容器使用该网络:

# Setting network names is only available in version 3.5+
version: '3.5'
services:
  db:
    image: postgres
  web:
    container_name: my_rails_app
    build:
      context: .
      # This isn't listed in the official Docker documentation, but it lets you
      # specify which network to connect the container to during the build
      # process.
      network: myapp_default
    ports:
      - "3000:3000"
    depends_on:
      - db

networks:
  default:
    # Set the name of the default network. If you don't do this the name could
    # change based on your app's ["project name"][1], which would break your
    # build.
    #
    # [1]: https://docs.docker.com/compose/reference/envvars/#compose_project_name
    name: myapp_default

但就其本身而言,这还不够。这是因为默认情况下,Docker Compose 不会在构建期间启动容器的依赖项。要解决此问题,您需要在运行构建之前手动启动数据库容器:

docker-compose up --detach db # Start the database container
docker-compose build # Now run the build

这将允许 Web 服务在构建 Web 服务时连接到数据库服务。

关于ruby-on-rails - 对构建过程依赖于与另一个容器通信的应用程序进行 Docker 化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51333035/

相关文章:

ruby-on-rails - 尝试验证密码时出现 "BCrypt::Errors::InvalidHash: invalid hash"

ruby-on-rails - Bundler 找不到 gem "activemodel"的兼容版本

python - 针对 Web 和移动客户端的 Web 服务技术的建议

linux - Docker Machine 默认 VM 上的包管理器?

Azure 和 Docker Compose : assigning a Resource Group

docker-compose无法启动

mongodb - MongoDB集群-CSRS无法启动

ruby-on-rails - 更新关联而不保存它

docker - asp.net-core 2.0 Docker部署

docker - 如何在 alpine 容器内安装 Docker?