如何在Docker构建过程中使用环境变量来获取脚本? [英] How to source a script with environment variables in a docker build process?

查看:202
本文介绍了如何在Docker构建过程中使用环境变量来获取脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建具有类似以下docker项目的类似问题的映像:

I'm creating an image that has a similar problem like the following docker project:

FROM alpine:3.9.3

COPY ./env.sh /env.sh
RUN source /env.sh
CMD env



env.sh



env.sh

TEST=test123

我用

docker build -t sandbox .

并使用

docker run --rm sandbox

输出为

HOSTNAME=72405c43801b
SHLVL=1
HOME=/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/

我的环境变量丢失。

在真实项目中,我必须为IBM DB2客户机安装一个较长的复杂脚本来进行安装。设置环境变量。如何在不读取整个安装过程并在dockerfile中使用 ENV 设置所有变量的情况下实现它?

In the real project I have to source a longer complex script for the installation for IBM DB2 client that also sets environment variables. How can I achieve it without reading the whole installation process and setting all variables with ENV in the dockerfile?

EDIT :
在实际项目中,文件 env.sh 是在安装过程中创建的,无法从容器外部获得。根据在其上执行的系统来设置环境变量。如果我在主机上运行它,则会在来宾中设置错误的变量。

In the real project the file env.sh is created as part of the installation process and it is not available from outside of the container. The environment variables are set depending on the system it is executed on. If I run it on the host it will set wrong variables in the guest.

真实脚本的一部分是

if [ -f ${INST_DIR?}/tools/clpplus.jar ]; then
    AddRemoveString CLASSPATH ${INST_DIR?}/tools/clpplus.jar a
fi

if [ -f ${INST_DIR?}/tools/antlr-3.2.jar ]; then
    AddRemoveString CLASSPATH ${INST_DIR?}/tools/antlr-3.2.jar a
fi

if [ -f ${INST_DIR?}/tools/jline-0.9.93.jar ]; then
    AddRemoveString CLASSPATH ${INST_DIR?}/tools/jline-0.9.93.jar a
fi

if [ -f ${INST_DIR?}/java/db2jcc.jar ]; then
    AddRemoveString CLASSPATH ${INST_DIR?}/java/db2jcc.jar a
fi

if [ -f ${INST_DIR?}/java/db2jcc_license_cisuz.jar ]; then
    AddRemoveString CLASSPATH ${INST_DIR?}/java/db2jcc_license_cisuz.jar a
fi

它检查安装并根据此设置变量。由于在主机上没有安装DB2,因此不会设置变量。

It checks the installation and sets the variables depending on this. Since on the host is no DB2 installation the variables wouldn't be set.

推荐答案

每个Dockerfile RUN 步骤运行一个新的容器和一个新的外壳。如果尝试在一个外壳中设置环境变量,则以后将看不到该变量。例如,您可以尝试以下Dockerfile:

Each Dockerfile RUN step runs a new container and a new shell. If you try to set an environment variable in one shell, it will not be visible later on. For example, you might experiment with this Dockerfile:

FROM busybox
ENV FOO=foo1
RUN export FOO=foo2
RUN export BAR=bar
CMD echo FOO is $FOO, BAR is $BAR
# Prints "FOO is foo1, BAR is "

有三个很好的解决方案。从最容易/最好到最困难/最复杂:

There are three good solutions to this. In order from easiest/best to hardest/most complex:


  1. 完全避免使用环境变量。将软件安装到系统位置,例如 / usr ;无论如何,它将被隔离在Docker映像中。 (不要使用其他隔离工具(如Python虚拟环境)或版本管理器(如 nvm rvm

  1. Avoid needing the environment variables at all. Install software into "system" locations like /usr; it will be isolated inside the Docker image anyways. (Don’t use an additional isolation tool like Python virtual environments, or a version manager like nvm or rvm; just install the specific thing you need.)

使用 ENV 起作用:

FROM busybox
ENV FOO=foo2
ENV BAR=bar
CMD echo FOO is $FOO, BAR is $BAR
# Prints "FOO is foo2, BAR is bar"


  • 使用入口点脚本。通常如下所示:

    #!/bin/sh
    # Read in the file of environment settings
    . /opt/wherever/env
    # Then run the CMD
    exec "$@"
    

    COPY 将此脚本放入您的Dockerfile中。使其成为 ENTRYPOINT ;使 CMD 成为您实际正在运行的东西。

    COPY this script into your Dockerfile. Make it be the ENTRYPOINT; make the CMD be the thing you’re actually running.

    FROM busybox
    WORKDIR /app
    COPY entrypoint.sh .
    COPY more_stuff .
    ENTRYPOINT ["/app/entrypoint.sh"]
    CMD ["/app/more_stuff/my_app"]
    

    如果您关心这些事情,通过此方法设置的环境变量将不会在 docker inspect docker exec 调试外壳;但是如果您 docker run -it ... sh ,它们将可见。这是一个有用且足够重要的模式,除非我专门尝试进行此类的首次设置,否则我几乎总是在Dockerfile中使用 CMD

    If you care about such things, environment variables you set via this approach won’t be visible in docker inspect or a docker exec debug shell; but if you docker run -it ... sh they will be visible. This is a useful and important enough pattern that I almost always use CMD in my Dockerfiles unless I’m specifically trying to do first-time setup like this.

    这篇关于如何在Docker构建过程中使用环境变量来获取脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆