如何使Docker Compose服务构建依赖于另一服务?

时间:2018-10-13 00:25:26

标签: database postgresql docker docker-compose jooq

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

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

  1. 启动“数据库”服务(在我的情况下,使用postgres图像)。
  2. 在开发仓库中,使用SQL脚本初始化了数据库。
  3. 运行“ Web”服务的构建阶段,该阶段在同一存储库中使用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"

我将用更多细节对此加以充实,但希望我要问的很简单。

2 个答案:

答案 0 :(得分:0)

我遇到了同样的问题,并且以一种骇人听闻的方式解决了...

在我的情况下,Web服务是Haskell,它使用result命令构建,然后使用stack build执行。还有stack exec APP_NAME之类的缩写。

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

所以我这样更改了Dockerfile:

stack build --only-dependencies

因此最终版本仅在服务启动时运行。

我对Java的了解还不够,但是我想那里也必须有类似的选择。

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

答案 1 :(得分:0)

就我而言,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));
}