docker 容器启动后运行自定义脚本

Posted

技术标签:

【中文标题】docker 容器启动后运行自定义脚本【英文标题】:Run custom script after docker container startup 【发布时间】:2021-12-13 19:35:59 【问题描述】:

我有以下 nodejs dockerfile:

# pull image
FROM node:13.12.0-alpine

# set working directory
WORKDIR /app

# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH

# install app dependencies
COPY package.json ./
COPY package-lock.json ./
RUN npm install

# add app
COPY . ./

# start app
CMD node server dev

我需要在启动后在容器内动态运行自定义 js 脚本。我怎样才能做到这一点?

--更新 尝试在 CMD 后添加以下入口点,但 CMD 和 ENTRYPOINT 均未执行:

ENTRYPOINT node customScript.js

添加了一个包装外壳脚本 (startup.sh) 以包含这两个命令:

#!/bin/sh

nohup node server dev > startup.log && node data/scripts/custom.js > custom.log

将 CMD 替换为:

CMD ["./startup.sh"]

这只会执行 shell 中的第一个命令,而不是第二个。我也没有看到容器中正在创建输出重定向日志文件。

【问题讨论】:

你能举个例子吗?例如,您可以在应用程序的 main 函数中编写任何您想要的代码;那是进行所需设置的好地方吗?或者您可以启动一个单独的容器,或者从主机进行 HTTP 管理调用,或者使用入口点包装脚本?有很多选择。 只需在脚本末尾添加入口点和脚本名称,例如 ENTRYPOINT[“sh”, Abc.sh] @DavidMaze,查看我的更新。我无法在单独的容器中运行脚本,因为它需要节点容器中的大量代码。 所有代码都应该在图片中,不是吗?你应该可以docker run the-same-image some other command(如果你使用ENTRYPOINT)。 @sotn 看起来好像您只想让 docker 启动两个无休止的进程而不是一个。那是对的吗?如果是这样,请参阅:docs.docker.com/config/containers/multi-service_container 【参考方案1】:

您应该使用主管在单个容器中运行多个进程。他们将/可能还会再次自动重启死亡进程。如果没有主管,您的流程可能会一团糟。

例如:

就我而言,我在项目alpine-s6-nginx-php 中使用s6 在单个容器中运行进程。该项目有一个类似 OOP 的继承模型:

基础图像 alpine-s6-basealpine-s6-nginxalpine-s6-nginx-php

基础镜像准备s6设置,nginx镜像添加nginx进程,最终alpine-s6-nginx-php镜像添加php-fpm7进程。你可以查看这些 repos 和 s6 supervisor。 不需要为每个进程分离层,所有进程都可以添加到单个 Dockerfile 中。您也可以使用 s6 替代品,例如系统等。

TLDR;您可以使用s6-overlay 轻松构建 s6 监督容器镜像。

【讨论】:

【参考方案2】:

理想情况下,您应该在后台运行 nohup 进程

CMDENTRYPOINT

没有问题
#!/bin/sh

nohup node server dev > startup.log && node data/scripts/custom.js > custom.log

在你的 nohup 命令最后使用 & 来启动进程进入后台模式

nohup ./yourscript &

nohup command &

之后你可以运行node命令

sh示例

nohup nice "$0" "calling_myself" "$@" > $nohup_out &
node index.js
sleep 1
tail -f $nohup_out

【讨论】:

【参考方案3】:

如果你需要在 docker 启动时运行两条命令,一条是非阻塞的,另一条可以是阻塞调用的。

如果两个调用都阻塞,那么您需要在单独的线程/进程中启动一个命令,然后运行另一个命令。

这可以在一个父脚本(sh)中实现,它可以为一个命令启动一个进程并调用当前进程中的最后一个命令。

https://www.linuxtopia.org/online_books/advanced_bash_scripting_guide/internal.html https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_01_04.html

【讨论】:

这似乎不是仅链接,也不是其他任何值得删除的内容。这是解决方案的纯文本描述,完全有效。它也是独立的,所以我要继续并取消删除它。您可能需要澄清您的答案,以防止将来出现此错误【参考方案4】:

您可以在脚本末尾添加入口点关键字和脚本名称,例如 ENTRYPOINT[“sh”, “Abc.sh”]

【讨论】:

查看我对 OP 的更新。

以上是关于docker 容器启动后运行自定义脚本的主要内容,如果未能解决你的问题,请参考以下文章

Zabbix自定义key监控docker

如何使用docker构建我自己的自定义Ubuntu ISO

zabbix通过自定义脚本监控docker服务docker nginx容器,图文详细

问题解决Docker容器内服务自启动解决方案

对docker容器的增加或减少进行报警

docker 容器内服务自启动