【问题标题】:Setting environment variable during Docker container start (on AWS)在 Docker 容器启动期间设置环境变量(在 AWS 上)
【发布时间】:2020-03-28 10:42:08
【问题描述】:

我正在尝试使用以下代码传递一个获取 IP 地址的变量:

${wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4}

我尝试设置一个入口点 shell 脚本,例如:

#!/bin/sh

export ECS_INSTANCE_IP_ADDRESS=$(wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4)
java -jar user-service-0.0.1-SNAPSHOT.jar

我的 dockerfile 看起来像:

#############
### build ###
#############

# base image
FROM maven:3.6.2-ibmjava-8-alpine as build

# set working directory
WORKDIR /app


# install and cache app dependencies
COPY . /app
RUN mvn clean package


############
### prod ###
############

# base image
FROM openjdk:8-alpine

# set working directory
WORKDIR /app

# copy entrypoint from the 'build environment'
COPY --from=build /app/entrypoint.sh /app/entrypoint.sh

# copy artifact build from the 'build environment'
COPY --from=build /app/target/user-service-0.0.1-SNAPSHOT.jar /app/user-service-0.0.1-SNAPSHOT.jar

# expose port 8081
EXPOSE 8081

# run entrypoint and set variables
ENTRYPOINT ["/bin/sh", "./entrypoint.sh"]

我需要在回显 ECS_INSTANCE_IP_ADDRESS 时显示此变量,以便它可以由 $ECS_INSTANCE_IP_ADDRESS 的 .properties 文件加载。每当我进入容器的 /bin/sh 并回显变量时,它就会显示为空白。如果我在那个 shell 上进行导出,我会得到回显响应。

有什么想法吗?我已经尝试了很多东西,但无法让变量在容器上可用。

【问题讨论】:

  • 您在ENTRYPOINT 中所做的任何事情都只会对该进程及其子进程可见(例如,您的java 进程);在 docker exec 紧急调试 shell 中将无法访问它。这是正常行为,通常不是问题。
  • 我相信它正在做它应该做的事情,尽管元数据 URL 是错误的。

标签: docker environment-variables docker-entrypoint


【解决方案1】:

这就是我修复它的方法,我相信元数据 URL 也有错误,这可能是罪魁祸首。

Dockerfile:

#############
### build ###
#############

# base image
FROM maven:3.6.2-ibmjava-8-alpine as build

# set working directory
WORKDIR /app


# install and cache app dependencies
COPY . /app
RUN mvn clean package


############
### prod ###
############

# base image
FROM openjdk:8-alpine

RUN apk add jq

# set working directory
WORKDIR /app

# copy entrypoint from the 'build environment'
COPY --from=build /app/entrypoint.sh /app/entrypoint.sh

# copy artifact build from the 'build environment'
COPY --from=build /app/target/user-service-0.0.1-SNAPSHOT.jar /app/user-service-0.0.1-SNAPSHOT.jar

# expose port 8081
EXPOSE 8081

# run entrypoint
ENTRYPOINT ["/bin/sh", "./entrypoint.sh"]

入口点.sh

#!/bin/sh
export FARGATE_IP=$(wget -q -O - http://169.254.170.2/v2/metadata | jq -r .Containers[0].Networks[0].IPv4Addresses[0])
echo $FARGATE_IP
java -jar user-service-0.0.1-SNAPSHOT.jar

application-aws.properties(不是完整文件):

eureka.instance.ip-address=${FARGATE_IP}

Eureka 正在 Eureka 状态页面上打印一个模板错误,但微服务确实连接并响应来自 Spring Boot 的执行器健康和 swagger-ui。

【讨论】:

    【解决方案2】:

    在 Docker 中set Environment variables 的标准方式是 Dockerfile 或 Task definition 在 AWS-ECS 的情况下。

    当前的 docker-entrypoint 只会为该会话设置 env,这就是为什么你在执行 ssh 时得到空值的原因,但你可以验证它是否已在该会话中,但在 Docker 中不推荐这种方法。

    你可以验证

    #!/bin/sh
    
    export ECS_INSTANCE_IP_ADDRESS=$(wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4)
    echo "instance IP is ${ECS_INSTANCE_IP_ADDRESS}" 
    java -jar user-service-0.0.1-SNAPSHOT.jar
    

    您将能够看到此值,但在另一个会话中将不可用。

    另一个例子,

    Dockerfile

    FROM node:alpine
    WORKDIR /app
    COPY run.sh run.sh
    RUN chmod +X run.sh
    ENTRYPOINT ["./run.sh"]
    
    

    入口点

    #!/bin/sh
    
    export ECS_INSTANCE_IP_ADDRESS=$(wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4)
    node -e "console.log(process.env.ECS_INSTANCE_IP_ADDRESS)"
    

    您将看到节点进程能够处理环境,但如果您在容器内运行命令,它将显示undefined

    docker exec -it <container_id> ash -c 'node -e "console.log(process.env.ECS_INSTANCE_IP_ADDRESS)"'
    

    两个选项来处理ENV,

    如果您已经知道 IP,则传递 IP ENV,因为实例总是在容器之前启动,例如

    第二个选项是passing environment variable to a java class in command lineHow to pass system properties to a jar file,如果这似乎适用,那么您的入口点将是

    java -DECS_INSTANCE_IP_ADDRESS=$(wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4) -jar myjar.jar 
    

    【讨论】:

    • 尝试通过命令行将环境变量传递给 java 类,但它仍然显示为空白。执行的行是:ENTRYPOINT ["java", "-DECS_INSTANCE_IP_ADDRESS=$(wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4)", "-jar", "user-service-0.0.1-SNAPSHOT.jar"]
    • 同样通过任务定义传递ENV变量不允许输入需要获取的变量,只能输入静态变量。
    • 是的任务定义只允许静态,而入口点一种方法我使用 nodejs 对其进行测试,它也应该与 java 一起使用。或尝试使用ECS_INSTANCE_IP_ADDRESS=$(wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4) echo "instance IP is ${ECS_INSTANCE_IP_ADDRESS}" java -jar user-service-0.0.1-SNAPSHOT.jar,最好使用入口点脚本然后入口点。
    猜你喜欢
    • 2019-10-31
    • 1970-01-01
    • 2018-07-08
    • 2017-05-11
    • 2015-02-07
    • 2017-01-28
    • 2017-12-30
    • 2020-10-22
    • 1970-01-01
    相关资源
    最近更新 更多