如何在 docker 入口点之前透明地 运行 脚本?

How to transparently run a script before docker entrypoint?

我正在 cloudformation 模板的 docker 容器中自动部署 java 应用程序。我需要为 java 崩溃日志设置一个环境变量,但我需要保持每个容器的路径唯一。我无法修改 docker 图片或 docker 文件。

为此,我使用了来自 docker 容器的 $HOSTNAME,它非常独特。问题是我不能像往常一样使用它 docker 环境变量,因为它是在容器启动后设置的。解决方法是通过设置 env 变量并在之后启动原始入口点来更改入口点。

EntryPoint: 
            - /bin/sh
            - -c
            - export JAVA_OPTS="$JAVA_OPTS -XX:HeapDumpPath=/mnt/crashdumps/java_$HOSTNAME.hprof" 
&& ./entrypoint.sh

(这是 AWS::ECS::TaskDefinition 的 cloudformation YAML 模板,但同样的事情可以在 docker cli 中表达)

在 java 容器提供商更改入口点 shell 脚本的位置之前它工作正常。现在 shell 注入 在代码中看起来真的很脏,因为我需要检查文件是否存在并且需要更多维护(即以防入口点路径或文件名再次更改) .

有没有更好的方法:

  1. 使用不同于修改入口点的方法动态设置具有容器名称的路径;或
  2. 只注入一个 "export" 命令和 运行 原始入口点,无论名称和路径是什么?

如果您想为 java 崩溃日志动态生成路径,我建议在 docker 入口点脚本本身中动态生成唯一名称。

就像这个,我测试过,效果很好。

#!/bin/sh

# Create some random file in /tmp
filename=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '')
touch /tmp/$filename
cat /tmp/$filename
export filename=$filename

每次我 运行 这个脚本,一旦你生成这样的多个容器就会发生。它将在 /tmp 中生成具有随机名称的文件。

$ ls /tmp/
DzJXInMvJAgvN  f0rgIMIt115h7  sSgVDXj2zvRTh  x4dBEciezQnix

所以在这种情况下,入口点将在每次调用期间生成一个唯一的名称,因此在 docker entrypoint 之前不需要调用任何东西。

希望对您有所帮助。

更新

到目前为止,我了解到您想覆盖 java 崩溃日志的文件路径,而不编辑 docker 文件或入口点脚本。如果我是对的,JAVA_OPTS-XX:HeapDumpPath 选项。

你可以试试这个

$ docker run -itd --env JAVA_OPTS="$JAVA_OPTS -XX:HeapDumpPath=/mnt/crashdumps/java_$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '').hprof" alpine sh
$ docker exec -it 75f062ff8906 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=75f062ff8906
TERM=xterm
JAVA_OPTS= -XX:HeapDumpPath=/mnt/crashdumps/java_MyRZcSKxFtZaF.hprof
HOME=/root

如您所见,JAVA_OPTS 被适当的文件名覆盖。 希望这有帮助,让我知道。