如何通过脚本在 Dockerfile 中动态设置环境变量?

How to set environment variables dynamically by script in Dockerfile?

我通过 Dockerfile 构建我的项目。该项目需要安装 Openvino。 Openvino 需要通过依赖架构的脚本动态设置一些环境变量。脚本是:script to set environment variables

据我了解,Dockerfile 无法将环境变量设置为来自脚本的映像。

如何按照方法解决问题?

我需要设置变量,因为稍后我会继续安装查看环境变量的 opencv。

我认为如果我把脚本放到 ~/.bashrc 文件中以在连接到 bash 时设置变量,如果我有什么技巧可以启动 bash一秒钟,它可以解决我的问题。

其次,我认为构建 openvino 图像,从中创建容器,连接它并在容器中通过 运行 脚本手动初始化变量。之后,将容器转换为图像。创建新的 Dockerfile 并通过将此图像用于正在进行的步骤来继续构建步骤。

Openvino Dockerfile exp and line that run the script

我的 Dockerfile:

FROM ubuntu:18.04

ARG DOWNLOAD_LINK=http://registrationcenter-download.intel.com/akdlm/irc_nas/16612/l_openvino_toolkit_p_2020.2.120.tgz

ENV INSTALLDIR /opt/intel/openvino

# openvino download
RUN curl -LOJ "${DOWNLOAD_LINK}"

# opencv download
RUN wget -O opencv.zip https://github.com/opencv/opencv/archive/4.3.0.zip && \
    wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.3.0.zip

RUN apt-get -y install sudo

# openvino installation
RUN tar -xvzf ./*.tgz && \
    cd l_openvino_toolkit_p_2020.2.120 && \
    sed -i 's/decline/accept/g' silent.cfg && \
    ./install.sh -s silent.cfg && \
    # rm -rf /tmp/* && \
    sudo -E $INSTALLDIR/install_dependencies/install_openvino_dependencies.sh

WORKDIR /home/sa

RUN /bin/bash -c "source /opt/intel/openvino/bin/setupvars.sh" && \
    echo "source /opt/intel/openvino/bin/setupvars.sh" >> /home/sa/.bashrc && \
    echo "source /opt/intel/openvino/bin/setupvars.sh" >> ~/.bashrc && \
    $INSTALLDIR/deployment_tools/model_optimizer/install_prerequisites/install_prerequisites.sh && \
    $INSTALLDIR/deployment_tools/demo/demo_squeezenet_download_convert_run.sh

RUN bash

# opencv installation

RUN unzip opencv.zip && \
    unzip opencv_contrib.zip && \
    # rm opencv.zip opencv_contrib.zip && \
    mv opencv-4.3.0 opencv && \
    mv opencv_contrib-4.3.0 opencv_contrib && \
    cd ./opencv && \
    mkdir build && \
    cd build && \
    cmake -D CMAKE_BUILD_TYPE=RELEASE -D WITH_INF_ENGINE=ON -D ENABLE_CXX11=ON -D CMAKE_INSTALL_PREFIX=/usr/local -D INSTALL_PYTHON_EXAMPLES=OFF -D INSTALL_C_EXAMPLES=OFF -D ENABLE_PRECOMPILED_HEADERS=OFF -D OPENCV_ENABLE_NONFREE=ON -D OPENCV_EXTRA_MODULES_PATH=/home/sa/opencv_contrib/modules -D PYTHON_EXECUTABLE=/usr/bin/python3 -D WIDTH_GTK=ON -D BUILD_TESTS=OFF -D BUILD_DOCS=OFF -D WITH_GSTREAMER=OFF -D WITH_FFMPEG=ON -D BUILD_EXAMPLES=OFF .. && \
    make && \
    make install && \
    ldconfig

您需要让 shell 在您使用它的每个 RUN 命令中以及在容器启动时加载该文件。

对于启动时间,您可以使用入口点包装器脚本:

#!/bin/sh
# Load the script of environment variables
. /opt/intel/openvino/bin/setupvars.sh
# Run the main container command
exec "$@"

然后在Docker文件中,需要在RUN命令中包含环境变量脚本,并使这个脚本成为镜像的ENTRYPOINT.

RUN . /opt/intel/openvino/bin/setupvars.sh && \
    /opt/intel/openvino/deployment_tools/model_optimizer/install_prerequisites/install_prerequisites.sh && \
    /opt/intel/openvino/deployment_tools/demo/demo_squeezenet_download_convert_run.sh

RUN ... && \
    . /opt/intel/openvino/bin/setupvars.sh && \
    cmake ... && \
    make && \
    ...

 COPY entrypoint.sh .
 ENTRYPOINT ["./entrypoint.sh"]
 CMD same as the command you set in the original image

如果您 docker exec 在容器中调试 shell,它们将看不到这些环境变量,您需要手动 re-read 环境变量脚本。如果你使用docker inspect查看容器的low-level细节,它也不会显示环境变量。


看起来该脚本只是设置了几个环境变量(尤其是 $LD_LIBRARY_PATH$PYTHONPATH),如果设置为 long-winded 值,您可以使用 ENV 语句在 Docker 文件中。

如果您查看 docker build 输出,在每个构建步骤之后都有类似 ---> 0123456789ab 的行;这些是您可以 docker run 的有效图像 ID。你可以 运行

docker run --rm 0123456789ab \
  env \
  | sort > env-a
docker run --rm 0123456789ab \
  sh -c '. /opt/intel/openvino/bin/setupvars.sh && env' \
  | sort > env-b

这将为您提供两个包含环境变量的本地文件,其中包含和不包含此安装脚本运行。找出差异(例如,使用 comm(1)),在每一行之前放置 ENV,并将其添加到您的 Docker 文件中。


你不能在 Docker 中真正使用 .bashrc。许多常见路径不调用其 startup files:在该文档的语言中,Dockerfile RUN 命令和 docker run 指令都不是“交互式 shell" 所以那些不读取点文件,通常 docker run ... command 根本不会调用 shell。

您也不需要 sudo(您已经 运行 root 身份,交互式密码提示将失败); RUN sh -c 是多余的(Docker 自己插入); source 不是标准的 shell 命令(更喜欢标准的 .,它甚至可以在没有 shell 扩展名的 Alpine-based 图像上工作) .