【问题标题】:Docker-compose, deploy war to Tomcat, run oracle servicedocker-compose,将war部署到Tomcat,运行oracle服务
【发布时间】:2017-01-18 10:05:47
【问题描述】:

鉴于我有以下情况:

我想将 web 应用程序部署到 Tomcat,它连接到 oracle 数据库并向用户显示数据

我需要的是以下内容:

  • Docker 编写 yml

  • Tomcat docker 镜像 - 此处部署战争

  • Oracle docker 镜像

  • fatdb jar 部署 - 我有更新打包为 fatdb jar 的 db 架构的 liquibase 脚本

解决方案可能是:

version: '2'
services:
  web-tomcat:
    image: tomcat:jre8
    depends_on:
      - db-oracle
  db-oracle:
    image: wnameless/oracle-xe-11g

但是,需要解决多个问题:

  1. 等待 oracle 服务准备就绪 - 按照 docker 文档中的建议使用等待包装器解决:wait-for-it
  2. 等待创建用户 - 通过等待循环解决,该循环尝试在创建用户的情况下连接到 oracle db
  3. 等待 liquibase fatdb 部署准备的数据库模式,然后将战争部署到 tomcat
  4. 不会以我启动单独的容器来进行 fatdb 部署的情况结束,之后它只会停留在 Exited (0) 状态,因为 fatdb 部署是一次性的,而不是服务

我最终创建了 entrypoint.sh 脚本,以便在部署战前准备好数据库:

java -jar fatdb.jar update
catalina.sh run

并在 tomcat 图像中覆盖入口点

是否有更好的解决方案如何在 docker-compose 中部署战争前准备数据库架构?

【问题讨论】:

    标签: tomcat docker deployment docker-compose


    【解决方案1】:

    我不知道它是否比您目前拥有的“更好”,但我总是通过认为我有两个部署来完成我的应用程序来解决这个问题。我有:

    1. 数据库部署(包括使用 Liquibase 之类的工具将架构更新到最新版本)
    2. 应用程序部署(包括部署我的 WAR 存档的最新版本或已打包)

    当然,第二次部署取决于第一次部署是否完整且成功。

    那么我该如何使用 docker-compose 进行建模呢?为了清楚起见,我创建了两个文件:

    1. docker-compose.database
    2. docker-compose.application

    然后我有一个两步部署过程:

    第 1 步:

    docker-compose -p application-name -f docker-compose.database up -d database
    docker-compose -p application-name -f docker-compose.database run --rm database-migration
    

    首先我们使用docker-compose up 启动数据库。其次,我们运行我们的数据库迁移。

    正如您在问题中指出的那样,在docker-compose up 返回后,数据库实际上“准备就绪”会有延迟,因此数据库迁移逻辑被包装在一个数据库检查函数中,该函数仅在我们运行一次迁移时运行。很高兴数据库可用。您会注意到我使用--rm 选项调用我的数据库迁移容器,这意味着容器在完成执行后会自动删除。一旦这个容器完成了它的工作,就没有必要让它到处闲逛了。

    在这里使用 docker-compose 提供的-p 选项也很重要。这为部署指定了project name,并确保所有容器都在同一个docker network 上创建,这意味着通过服务名称进行容器间通信不是问题。

    第 2 步:

    docker-compose -p application-name -f docker-compose.database -f docker-compose.application up -d application
    

    Docker Compose 允许您在命令行上指定多个 compose 文件,这就是我在这里所做的。在我的docker-compose.application 文件中,我会有这样的内容:

    version: 2
    services:
     application:
      image: my-tomcat-image
      depends_on: database
    

    数据库服务在docker-compose.database 文件中定义,我知道它现在已经在运行(因为部署步骤1 完全成功)。因此,我可以立即启动 Tomcat 服务,而无需等待任何事情。这很有帮助,因为我只有一次“等待数据库准备好逻辑”,即数据库迁移。 Tomcat 服务本身希望数据库存在,如果不存在,则会快速失败。

    围绕步骤包装

    这种方法的明显缺点是运行部署时突然需要多个命令。每当您尝试在服务之间存在依赖关系的情况下进行任何形式的基础架构编排时,总是会遇到这样的挑战。

    同样,您可以通过编写一个简单的 shell 脚本来包装 docker-compose 命令来保持简单。我喜欢能够对任何包装脚本进行单元测试,所以我倾向于使用 ruby​​ 来做类似的事情。然后你可以想象这样的事情:

    ruby deploy.rb
    

    deploy.rb 脚本当然包含了您的多个 docker-compose 命令。

    其他好的方法是使用 Jenkins 或任何其他 CI/CD 管道工具为您执行此操作(感谢您可能希望在本地计算机上执行此操作)。

    您还可以开始查看 Terraform 之类的工具,它们提供了一种“标准化”方法来执行此类操作,但是当一个简单的包装脚本可以让您启动并运行时,这可能超出您的需要.

    【讨论】:

    • 嗨,罗伯。感谢您的见解!我根据您的回答重构了解决方案,我喜欢它(即使解决方案对 docker-compose 的使用更重)。我还将它包装到 shell 脚本中,并且通常从 Teamcity 对 Azure 基础设施执行它。我会看看 Terraform,谢谢。您还介意提供有关 ruby​​ 单元测试的小更新吗?测试结果如何?
    猜你喜欢
    • 1970-01-01
    • 2018-07-25
    • 1970-01-01
    • 2012-08-10
    • 2017-12-08
    • 1970-01-01
    • 2015-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多