如何在 CMD 中运行 2 个命令,其中一个需要使用 ENTRYPOINT?

huangapple go评论64阅读模式
英文:

Docker: How to run 2 commands in CMD if one of them requires ENTRYPOINT?

问题

我正在尝试为arangodb镜像启用cron:

https://github.com/arangodb/arangodb-docker/blob/a33b50b8a5c9a60f8c812016899485cc9cd78de3/alpine/3.10.3/Dockerfile

传递两个命令,但只有其中一个(arangod)需要ENTRYPOINT的正确方法是什么?

我正在尝试类似以下的方式:

FROM arangodb:3.10.3
ENTRYPOINT ["/entrypoint.sh"]

# 标准端口
EXPOSE 8529
CMD ["arangod", "/usr/sbin/crond -f"]

但这个设置失败了(如果我不使用"/usr/sbin/crond -f",一切正常)。

英文:

I am trying to enable cron for arangodb image:

https://github.com/arangodb/arangodb-docker/blob/a33b50b8a5c9a60f8c812016899485cc9cd78de3/alpine/3.10.3/Dockerfile

What is the correct way to pass 2 commands, but only one of them (arangod) requires ENTRYPOINT?

I am trying something like:

FROM arangodb:3.10.3
ENTRYPOINT ["/entrypoint.sh"]

# standard port
EXPOSE 8529
CMD ["arangod", "/usr/sbin/crond -f"]

but this setup fails (If I am using it without "/usr/sbin/crond -f" - everything is fine).

答案1

得分: 1

什么是传递两个命令的正确方式

几乎总是在两个单独的容器中。对于这个特定的镜像,你不能仅仅使用 CMD 来在同一个容器中同时运行数据库和定时任务守护进程,但这通常不是最佳实践。

对于这个问题,通常数据库被设计为通过网络连接调用,所以通常可以从另一个容器中运行管理工具。例如,你可以给定一个 arangodump --server.endpoint 选项,从另一个容器中获取数据库备份;它不需要从同一个容器内运行。

这意味着你可能需要一个未修改的 ArangoDB 容器,以及一个单独运行定时任务守护进程的第二个容器。对于这个需求,扩展 ArangoDB 镜像是合理的,因为它已经包含你需要的工具;查看一下它的 Dockerfile可能会有所帮助,观察到 (a) 它是从 alpine 构建的(这影响了 crond 的语法;参见 BusyBox 命令参考)和 (b) 正如你指出的,它有一个内置的 ENTRYPOINT,你可能需要重新设置。

FROM arangodb:3.10.3
COPY crontab /
RUN crontab -u root /crontab \
 && rm -f /crontab
ENTRYPOINT []
CMD ["crond", "-f"]

(另一种选择是使用 Alpine、Ubuntu 或 Debian 基础镜像,然后根据 ArangoDB 的安装说明进行操作。这将有一个不泄漏匿名卷的优势,但构建起来可能会稍微困难一些。)

一个示例的 Docker Compose 设置,可以运行这两个容器:

version: '3.8'
services:
  db:
    image: arangodb:3.10.3
    environment:
      ARANGO_ROOT_PASSWORD: passw0rd
    volumes:
      - db:/var/lib/arangodb3
  cron:
    build: ./cron
    environment:
      ARANGO_HOST: db
      ARANGO_ROOT_PASSWORD: passw0rd
volumes:
  db: # intentionally empty

还有一个有用的是浏览实际的入口脚本。这是一个典型的入口点包装脚本:它进行首次设置,然后使用 exec "$@" 运行 CMD 中的任何内容。所以你实际上不需要在这里重新设置 ENTRYPOINT

值得注意的是,如果 CMD 的第一个单词恰好是 arangod,那么有趣的首次设置只会发生如果 CMD 的第一个单词恰好是 arangod。有一些技巧可以尝试打破 Docker 的标准模式并在容器中运行多个进程(如何在 Docker 容器中运行定时任务?将为你找到几个这样的方法);但如果你尝试使用一个 shell 进行任何操作,CMD 的第一个单词将不是 arangod,数据库初始化将不会发生。

你可以通过访问Docker Hub arangodb 镜像页面来找到一些引用的脚本;点击其中一个"supported tags and respective Dockerfile links"将带你到 GitHub 上的 Dockerfile;然后你通常可以在同一个目录中探索到入口点脚本等内容。

英文:

> What is the correct way to pass 2 commands

Almost always in two separate containers. With this particular image, you can't use CMD on its own to run both the database and a cron daemon in the same container, but this isn't usually a best practice.

For to this question in particular, databases are generally designed to be called via a network connection, and so it's generally possible to run administrative tools from another container. For example, you could give an arangodump --server.endpoint option to take a database dump from another container; it does not need to run from inside the same container.

This means that you probably need the unmodified ArangoDB container, plus a second container that separately runs the cron daemon. Extending the ArangoDB image for this is reasonable, since it will already contain the tools you need; it's helpful to look at its Dockerfile to observe that (a) it is build FROM alpine (which affects the crond syntax; see the BusyBox command reference) and (b) as you note it has an embedded ENTRYPOINT you might need to reset.

FROM arangodb:3.10.3
COPY crontab /
RUN crontab -u root /crontab \
 && rm -f /crontab
ENTRYPOINT []
CMD ["crond", "-f"]

(Another option is to use an Alpine, Ubuntu, or Debian base image and then go through ArangoDB's installation instructions from there. This will have an advantage of not leaking anonymous volumes, but a disadvantage of being a little harder to construct.)

A sample Docker Compose setup that could run both containers:

version: '3.8'
services:
  db:
    image: arangodb:3.10.3
    environment:
      ARANGO_ROOT_PASSWORD: passw0rd
    volumes:
      - db:/var/lib/arangodb3
  cron:
    build: ./cron
    environment:
      ARANGO_HOST: db
      ARANGO_ROOT_PASSWORD: passw0rd
volumes:
  db: # intentionally empty

It's also helpful to glance through the actual entrypoint script. This is implemented as a typical entrypoint wrapper script: it does its first-time setup and then uses exec "$@" to run whatever the CMD was. So you don't actually have to reset the ENTRYPOINT here.

Of note, the interesting first-time setup only happens if the first word of CMD is exactly arangod. There are some tricks you can try to use to break Docker's standard pattern and run multiple processes in a container (How to run a cron job inside a docker container? will find you several of these); but if you try to use a shell for anything, the first word of CMD will not be arangod and the database initialization will not happen.

You can find some of the referenced scripts by going to the Docker Hub arangodb image page; clicking on one of the "supported tags and respective Dockerfile links" will take you to the Dockerfile in GitHub; and from there you can generally explore the same directory to find things like entrypoint scripts.

答案2

得分: 0

CMD可以以三种形式使用,使用"shell形式"可以依次执行多个命令。

FROM arangodb:3.10.3
ENTRYPOINT ["/entrypoint.sh"]

# 标准端口
EXPOSE 8529
CMD /usr/sbin/crond -f && arangod

另一种选择是创建一个start.sh脚本,将您的命令放在其中,然后从CMD中执行它。

英文:

CMD can be used in three forms, using "shell form" you can execute multiple commands in sequence.

FROM arangodb:3.10.3
ENTRYPOINT ["/entrypoint.sh"]

# standard port
EXPOSE 8529
CMD /usr/sbin/crond -f && arangod

Another option would be to make a start.sh script and place your commands in there and execute it from CMD.

huangapple
  • 本文由 发表于 2023年5月28日 22:33:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76352003.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定