首页 > 解决方案 > 在 Docker 撰写文件中定义任务

问题描述

我已经对我正在使用的旧系统进行了 docker 化。我有一个 docker compose 文件,它引用了一个基于 postgres 构建的图像和一个基于 tomcat 构建的图像。此撰写文件适用于启动和停止应用程序的测试版本。

编写文件

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

这种配置的最佳实践是什么?

将其添加到撰写文件中似乎有什么好处

将其添加到撰写文件似乎不好

标签: dockerdocker-compose

解决方案


这些任务可以用 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 映像的入口点:如果它正在启动数据库,并且数据目录不存在,那么它会执行所有首次设置,同时启动一个临时数据库服务器。

我想执行的其他 [...] 任务

You might see whether you can add network calls that trigger them, either on a protected "admin" URL path or on a separate port that's not published externally. That would avoid the problem of needing to get a root shell to do routine maintenance tasks.

Failing that, a shell script to automate the task and its arguments will at least save you some typing and memorization.


推荐阅读