docker中不能读取带"."环境变量的问题

问题描述:

打包的docker镜像,启动时使用docker run -e 参数添加环境变量时,环境变量名称中包含".",有时能在环境变量里获取到,有时不能在环境变量里获取到;

由于linux设置环境变量的规范中,不允许带".",但公司老的内部java框架中使用了读取带"."的环境变量做配置,所以需要解决该问题;

复现方法:

先打包基础的docker镜像:

Dockerfile如下

FROM openjdk:8u151-jdk

MAINTAINER Ma Qian

RUN curl -sSL 'https://raw.githubusercontent.com/maqian/toolbox/master/debian/stretch/set-sources-cn' | sh \
  && curl -sSL 'https://raw.githubusercontent.com/maqian/toolbox/master/debian/set-timezone-cn' | sh \
  && curl -sSL 'https://raw.githubusercontent.com/maqian/toolbox/master/debian/set-locale-cn' | sh \
  && curl -sSL 'https://raw.githubusercontent.com/maqian/toolbox/master/sysfree/install-ejava' | sh \
  && apt-get install -y openjdk-8-dbg

ENV TIMEZONE=Asia/Shanghai TZ=Asia/Shanghai \
    LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8 LANGUAGE=zh_CN.UTF-8:zh:en_US:en

dockerfile目录下,执行docker build -t hub.wentjiang.com/base/java:openjdk-8u151 ./

执行完成后可以看到基础镜像创建成功

启动docker容器进行测试:

使用-e参数添加了两个环境变量

docker run --rm -it \
-e test.name=wentao.jiang \
-e test=wentao.jiang \
hub.wentjiang.com/base/java:openjdk-8u151 \
/bin/bash

执行后进入命令行,输入printenv打印当前容器内所有的环境变量:

docker中不能读取带

目前可以获取到test.name的环境变量

 

编写一个helloWorld程序,使用上述的基础镜像进行打包,模拟实际业务部署时的场景;

java代码如下:

/**
 * @author wentaojiang
 * @date 2019/5/30 11:46 PM
 * @description
 */
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("hello docker java");
        System.out.println(System.getenv("test.name"));
        System.out.println(System.getenv("test"));
    }
}

使用javac HelloWrold.java 得到HelloWorld.class文件

将HelloWorld.class打包到镜像中进行测试

Dockerfile如下:

FROM hub.wentjiang.com/base/java:openjdk-8u151

COPY HelloWorld.class /HelloWorld.class

ENTRYPOINT ["sh","-c","printenv;java HelloWorld"]

执行打包镜像命令:

docker build -t hub.wentjiang.com/java/helloworld:1.0.0 ./

可以看到镜像已经生成

使用docker run命令启动容器进行测试

docker run -it --rm \
-e test.name=wentao.jiang \
-e test=wentao.jiang \
hub.wentjiang.com/java/helloworld:1.0.0

这次启动之后,在环境变量里边添加的test.name环境变量已经不见了,在我们模拟的java进程中同样也获取不到test.name的环境变量;

docker中不能读取带

问题解决过程:

公司内有两种基础镜像,open-jdk版本的,和oracle-jdk版本的

open-jdk使用的打包基础镜像为openjdk:8u151-jdk,经过一层一层的向上查找,该镜像使用的是https://github.com/debuerreotype/docker-debian-artifacts/blob/fd138cb56a6a6a4fd9cb30c2acce9e8d9cccd28a/stretch/Dockerfile debian发行版;

oracle-jdk使用的是centos:7镜像;

使用oracle-jdk任何情况都能够读取到带"."的环境变量,使用open-jdk的镜像,在部分情况下会出现不能读取的情况,下边再进行操作分心;

使用测试的Dockerfile为:

FROM hub.wentjiang.com/base/java:openjdk-8u151

COPY HelloWorld.class /HelloWorld.class

#CMD ["java","HelloWorld"] #可以打印带"."环境变量 1.0.1
#ENTRYPOINT ["java","HelloWorld"] #可以打印带"."环境变量 1.0.2
#CMD ["sh","-c", "java HelloWorld;"] #不能打印带"."环境变量 1.0.3
#ENTRYPOINT ["sh","-c","java HelloWorld"] #不能打印带"."环境变量 1.0.4

分别打包了四个docker镜像并启动测试,前两个可以打印出来带"."环境变量,后两个不行;

至此可以判断是由于debian操作系统,在使用sh 命令执行后,不能获取带"."环境变量;

为了验证,我们直接使用上边注释掉执行命令的docker,打包docker build -t hub.wentjiang.com/java/helloworld:3.0.0 ./

使用命令进入容器中:

docker run -it --rm \
-e test.name=wentao.jiang \
-e test=wentao.jiang \
hub.wentjiang.com/java/helloworld:3.0.0 bash

docker中不能读取带

可以看到直接执行printenv能够输出带"."环境变量

使用sh -c printenv不能输出带"."环境变量

目前的推测是:sh命令新启了个shell进程,新的shell进程按照规范,忽略了带"."环境变量,导致该问题的发生;

你可能感兴趣的:(问题记录)