我正在为 Docker 项目启用多架构构建,当我尝试通过基于架构的条件更改环境变量时,我遇到了问题。
在dockerfile中有一个地方,在最后设置了环境变量:
ENV GROBID_SERVICE_OPTS "-Djava.library.path=grobid-home/lib/lin-64:grobid-home/lib/lin-64/jep --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED"
当架构为 ARM64 时,我想将
-Djdk.lang.Process.launchMechanism=vfork
添加到此环境变量。
我尝试检查
TARGETARCH
:
ARG TARGETARCH
ARG PROCESS_MECHANISM
RUN if [ "$TARGETARCH" = "arm64" ]; then \
PROCESS_MECHANISM="-Djdk.lang.Process.launchMechanism=vfork "; \
else \
PROCESS_MECHANISM=""; \
fi
RUN echo "Selected process spawning mechanism: $PROCESS_MECHANISM"
ENV GROBID_SERVICE_OPTS "$PROCESS_MECHANISM-Djava.library.path=grobid-home/lib/lin-64:grobid-home/lib/lin-64/jep --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED"
但是环境变量在此过程中丢失了。
确切的点是这里,这将包括完整的 Dockerfile。
您不能在 Dockerfile 中设置这样的变量。 (另请参阅 Dockerfile 中的条件 ENV。)您可以做的就是填写环境变量作为容器启动序列的一部分。
在您的 Dockerfile 中,不要尝试此条件检查。 将环境变量设置为不含计算部分的值。 您还需要复制入口点包装器脚本,我们将很快讨论该脚本。
ENV GROBID_SERVICE_OPTS=-Djava.library.path=grobid-home/lib/lin-64:grobid-home/lib/lin-64/jep --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/sun.nio.ch=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED
...
COPY entrypoint.sh ./
ENTRYPOINT ["./entrypoint.sh"] # must be JSON-array syntax
CMD ... # same as you have now
每次容器启动时,环境变量都会被重新计算和设置,但这是一个相当便宜的操作(特别是与 JVM 启动相比)。 通过这个配方,您可以使用调试命令仔细检查正在生成的内容,例如
docker run --rm your-image sh -c 'echo $GROBID_SERVICE_OPTS'
这将启动一个临时容器并运行该备用命令(请注意单引号,因此变量由容器 shell 而不是主机 shell 扩展)。 其他调试命令(如 docker inspect
和
docker exec
)不会通过此入口点包装器运行,因此不会看到环境变量设置,但这通常不是问题。 入口点脚本检查处理器架构,可能扩展环境变量,然后运行主容器命令。
#!/bin/sh
# Set the environment variable based on the CPU architecture
if [ "$(uname -m") = arm64 ]; then
PROCESS_MECHANISM="-Djdk.lang.Process.launchMechanism=vfork "
fi
echo "Selected process spawning mechanism: $PROCESS_MECHANISM"
GROBID_SERVICE_OPTS="$PROCESS_MECHANISM$GROBID_SERVICE_OPTS"
# Run the main container command
exec "$@"