Docker化一个应用程序,其构建过程取决于与另一个容器的通信 [英] Dockerizing an application whose build process depends on communication with another container

查看:84
本文介绍了Docker化一个应用程序,其构建过程取决于与另一个容器的通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Ruby on Rails应用程序,我想对其进行容器化,以便可以在Docker上部署它。

I have a Ruby on Rails app I'm trying to containerize so that I can deploy it with Docker:

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

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

As part of the existing build process for this application, there currently exists a script which starts up a test version of the application with a bunch of sample data and takes multiple screenshots of various features of the application to be used in help files. This script is integrated into Ruby on Rails' asset pipeline, so it runs as part of the normal asset precompile process (the Dockerfile below is somewhat simplified):

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服务器将无法正常运行。)

Now here's my problem: because this build step starts the web server in order to take screenshots of the UI, it needs to be able to connect to the database during the build. (The web server can't run properly without a database connection.)

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

In the old environment this wasn't an issue, as the production database was installed on the same server the application was so I could just have it connect to localhost. With Docker though, the database is running in a separate container managed by docker-compose. And unfortunately, Docker doesn't seem to want to let me talk to that container during the build:

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

我考虑过只是将预编译步骤延迟到部署;但这会大大减慢容器的部署过程,并要求我在生产容器中再包含50-100个依赖关系,否则这些依赖关系就不会使用。

I considered just delaying the precompile step until after the deploy; but that would slow down the deploy process for containers significantly and require me to include another 50-100 dependencies in my production container which aren't otherwise used.

在构建容器上安装数据库,但这似乎会使构建速度变慢,并且如果构建容器上的数据库与 postgres 图片提供。

I also considered installing a database on the build container, but that seems like it'd slow builds down a lot and might cause issues if the database on the build container doesn't exactly match the one the postgres image provides.

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

Is there a way to tell docker to start a container and set up the appropriate network connections during the build process? Or perhaps an alternative solution that doesn't have any of the downsides of the other solutions I already considered above?

推荐答案

您想要做的是使用 Docker的内置网络功能,以建立一个包含数据库容器的共享网络,然后在构建过程中将应用程序容器连接到该网络。

What you want to do is use Docker's built-in networking features to set up a shared network containing the database container, then attach your application container to that network during the build process.

在没有Docker Compose的情况下,这可以通过使用 docker network 子命令将其连接到docker网络,然后使用 docker构建应用程序容器build --network $ network_name_here。

Without Docker Compose, this would be accomplished by starting the database container, using the docker network subcommands to connect it to a docker network, then building the application container with docker build --network $network_name_here ..

使用Docker Compose,这可以通过为其应用程序的默认网络配置 name 属性,然后将未记录的 network 选项用于服务 build 参数告诉Compose在应用程序容器中使用该网络构建:

With Docker Compose, this can be accomplished by configuring a static name for your application's default network via its name attribute, then using the undocumented network option to the service build parameter to tell Compose to use that network for your application container during the build:

# 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不会在构建过程中启动容器的依赖关系。要解决此问题,您需要在运行构建之前手动启动数据库容器:

On its own though, even this isn't enough. That's because by default Docker Compose doesn't start your container's dependencies during the build. To fix this, you'll need to manually start the database container before you run the build:

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

将在构建Web服务时允许该Web服务连接到db服务。

This will allow the web service to connect to the db service while the web service is being built.

这篇关于Docker化一个应用程序,其构建过程取决于与另一个容器的通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆