在Docker Compose文件中定义任务

6

我已经将一个老系统docker化了,我有一个docker-compose文件引用了一个基于postgres构建的镜像和一个基于tomcat构建的镜像。这个compose文件可以很好地启动和停止应用程序的测试版本。

Compose文件

services:
  db:
    image: mypostgres
    container_name: db
    networks:
      - mynetwork
  tomcat:
    image: mytomcat
    container_name: tomcat
    networks:
      - mynetwork
    environment:
      - myhost=localhost
    volumes:
      - "mydata:/mydata"
    depends_on:
      - db

在一个容器中运行任务

我有一些额外的命令行任务想要在系统上执行。其中一些任务需要大量计算资源。这些任务操作的是mydata卷中的文件。

目前,我使用以下命令在tomcat容器内运行此任务。

docker exec tomcat /bin/my-script.sh param

这些任务可以用docker-compose定义吗?

我认为,创建一个单独的容器来运行此任务是有意义的。如果我将其定义为服务,它将如下所示。

  mycli:
    image: mytomcat
    networks:
      - mynetwork
    environment:
      - myhost=tomcat
    volumes:
      - "mydata:/mydata"
    depends_on:
      - db
      - mycli
    entrypoint: /bin/myscript.sh
    command:
      - param

对于这种配置,最佳实践是什么?

将此添加到compose文件中的好处

  • 长时间运行的任务在单独的容器中运行。
  • 任务的可用性得到了很好的定义。
  • 这可能是执行数据初始化任务的不错方式。

将此添加到compose文件中的不足之处

  • 当服务启动时,必须执行某些操作。一旦该操作完成,容器就处于停止状态。
  • 如果我使用docker-compose run来运行任务,则似乎已退出的任务会在执行后挂起。
1个回答

4
这些任务能用docker-compose定义吗?
不行。docker-compose.yml文件只能定义长时间运行的“服务”容器。无法定义一个额外的docker exec类型任务来在已经启动的容器上运行。你可以原则上定义执行完工作后立即退出的附加“服务”,但每次运行docker-compose up都会要求重新运行它们。
数据初始化任务
如果您有需要在首次启动时运行(如预加载数据)或每次启动时运行(可能是数据库迁移)的内容,可以结构化容器使其在主应用程序启动之前运行。我倾向于在入口脚本中执行此类操作;它将容器命令作为命令行参数,因此有机会根据正在运行的命令做出决策、执行所需的设置,然后实际启动该命令。
#!/bin/sh
if [ "$1" = "theapp" ]; then
  # Hypothetically: if we're starting theapp, run its migrations
  # first before running the service itself
  theapp migrate
fi
# Now do whatever the command is
exec "$@"

这种模式的一个特别复杂的例子就是mysql镜像的入口点:如果正在启动数据库,而数据目录还不存在,则它将执行所有第一次设置并启动一个临时数据库服务器。

我想执行其他一些任务

您可以尝试添加网络调用以触发它们,可以在受保护的“管理”URL路径上或未公开发布的单独端口上进行。这将避免需要获取root shell来执行常规维护任务的问题。

如果无法实现,编写一个shell脚本来自动化任务及其参数至少可以节省一些打字和记忆。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接