【问题标题】:How can one make a Docker Compose service build depend on another service?如何让 Docker Compose 服务构建依赖于另一个服务?
【发布时间】:2019-03-18 05:06:55
【问题描述】:

这就是我的意思。如何编写 docker-compose.yaml 文件,以便在“构建”其中一个服务时,它首先运行另一个服务?

我会尝试更具体。我正在尝试使用数据库库 JOOQ 构建 Java 应用程序,它希望在构建时连接到数据库以生成与数据库表对应的 Java 类。我想要 Dockerfile(s) 和 docker-compose.yaml 文件的某种组合,以便以下大致按以下顺序发生。

  1. “数据库”服务已启动(在我的例子中,使用 postgres 映像)。
  2. 在我的开发存储库中使用 SQL 脚本初始化数据库。
  3. 我的“web”服务的构建阶段运行,它使用同一个 repo 中的 Dockerfile,它调用 Gradle 构建,它告诉 JOOQ 连接到在步骤 1 中启动的数据库服务。这会生成 Java 文件,编译它们,并为构建容器做所有其他事情。
  4. “web”服务已启动,连接到在步骤 1 中启动的数据库服务。

这是我正在使用的 docker-compose.yaml 文件

version: '3.7' 
services:
  postgres:
    image: postgres:10.5-alpine
    restart: always
    ports:
      - "6432:5432"
    environment:
      POSTGRES_DB: flashtools
      POSTGRES_USER: flashtools
      POSTGRES_PASSWORD: flashtools
    volumes:
      - ./src/main/scripts/01_init.sql:/docker-entrypoint- 
initdb.d/01_init.sql
  web:
    build: .
    network_mode: host
    depends_on:
      - postgres
    ports:
      - "8080:8080"

我会用更多细节来充实这一点,但希望我的要求非常简单。

【问题讨论】:

  • 您的撰写文件有任何问题吗?
  • 这就是我们有depends_on的原因。如果服务A 依赖于B,则首先运行B
  • 没有。这不是我们有depends_on 的原因。是的,如果服务A 依赖于B,那么BA 运行(启动容器)之前运行(启动容器),但这并没有说明Docker 何时为A 构建映像.我的撰写文件的问题是,无论 running 服务的 depends_on 是什么,Abuilding_of A 都发生在 B 的 _running 之前。如果构建A 需要首先运行B,那将是一个问题。我怀疑在 Docker Compose 中没有办法做到这一点。
  • 正如我所说,我怀疑是not possible。我将把这个问题保持一段时间,然后如果没有人提出更好的答案,我会自己关闭它。
  • @DavidVentimiglia 嘿,你最后是怎么解决你的问题的?

标签: database postgresql docker docker-compose jooq


【解决方案1】:

我遇到了同样的问题并以一种 hacky 的方式解决了它......

在我的例子中,Web 服务是 Haskell,它使用 stack build 命令构建,然后使用 stack exec APP_NAME 执行。还有像stack build --exec APP_NAME 这样的简写。

还有一个选项可以仅使用 stack build --only-dependencies 构建依赖项,因此 Docker 构建会缓存它们。

所以我像这样更改了我的 Dockerfile:

COPY ./package.yaml /app/package.yaml        # Copying the package file
RUN stack build --only-dependencies          # Build dependencies only

COPY . /app                                  # Copying the rest of the files

EXPOSE 3000

CMD ["stack", "build", "--exec", "APP_NAME"] # Build the application itself

所以最终构建仅在服务启动时运行。

我对Java的了解不够,但我想那里也应该有类似的选择。

还需要对 depends_on 部分进行一些修改: https://docs.docker.com/compose/startup-order/

【讨论】:

    【解决方案2】:

    在我的例子中,Web 服务入口点是一个类似node server.js 的命令。

    如果数据库在调用时已经可用,它会正常工作,但使用 docker-compose 时情况并非如此。

    一种解决方法是在您的server.js 中编写代码,以便在数据库准备好之前重试。

    在我的server.js

    connectDB()
    .then(db => {
        /* Use db here...*/
    
        app.listen(3000);
    });
    
    async function connectDB() {
        var retry = 5;
        while (retry-- > 0 && !(dbReady()) {
            await sleep(1000);
        }
        return useDB();
    }
    
    function dbReady() {
        /* returns true iff DB available */
    }
    
    async function useDB() {
        /* returns DB instance */
    }
    
    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    

    【讨论】:

      猜你喜欢
      • 2017-10-31
      • 2019-10-19
      • 1970-01-01
      • 2020-07-09
      • 1970-01-01
      • 2017-12-17
      • 1970-01-01
      • 1970-01-01
      • 2017-07-27
      相关资源
      最近更新 更多