我正在创建具有类似以下docker项目的问题的映像:
FROM alpine:3.9.3 COPY ./env.sh /env.sh RUN source /env.sh CMD env
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客户机的源程序提供一个较长的复杂脚本,该脚本还设置了环境变量。如何在不阅读整个安装过程并ENV在dockerfile中设置所有变量的情况下实现它?
ENV
编辑:在实际项目中,文件env.sh是在安装过程中创建的,并且不能从容器外部使用。根据在其上执行的系统来设置环境变量。如果我在主机上运行它将在来宾中设置错误的变量。
env.sh
真实脚本的一部分是
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,因此不会设置变量。
每个Dockerfile RUN步骤都运行一个新的容器和一个新的shell。如果尝试在一个shell中设置环境变量,则以后将看不到该变量。例如,您可以尝试以下Dockerfile:
RUN
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 "
有三个好的解决方案。从最容易/最好到最难/最复杂:
完全避免使用环境变量。 将软件安装到“系统”位置,例如/usr; 无论如何,它将被隔离在Docker映像中。(不要使用其他隔离工具(例如Python虚拟环境)或版本管理器(例如nvm或rvm;),只需安装所需的特定工具即可。)
/usr
nvm
rvm
使用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
ENTRYPOINT
CMD
FROM busybox WORKDIR /app COPY entrypoint.sh . COPY more_stuff . ENTRYPOINT ["/app/entrypoint.sh"] CMD ["/app/more_stuff/my_app"]
如果你关心这样的事情,环境变量,你通过这种方式设置将不可见docker inspect或docker exec调试环境; 但是,如果您dockerrun-it...sh将它们可见。这是一个有用且足够重要的模式,CMD除非我专门尝试进行此类初次设置,否则我几乎总是在Dockerfile中使用它。
docker inspect
docker exec
dockerrun-it...sh