2

I am trying to pass a variable which fetches an IP address with the following code:

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

I have tried setting an entrypoint shell script such as:

#!/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

And my dockerfile looking like:

#############
### 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"]

I need this variable to show up when echoing ECS_INSTANCE_IP_ADDRESS so that it can be loaded by a .properties file which $ECS_INSTANCE_IP_ADDRESS. Whenever I get into /bin/sh of the container and echo the variable it shows up blank. If I do an export on that shell I do get the echo response.

Any ideas? I've tried a bunch of things and can't get the variable to be available on the container.

Lucas Gomez
  • 145
  • 1
  • 3
  • 12
  • Anything you do in the `ENTRYPOINT` will only be visible to that process and its children (_e.g._, your `java` process); it won't be accessible in `docker exec` emergency-debugging shells. That's normal behavior and usually isn't a problem. – David Maze Dec 03 '19 at 18:36
  • I believe it was doing what it was meant to, although the metadata URL was wrong. – Lucas Gomez Dec 03 '19 at 23:21

2 Answers2

1

The standard way to set Environment variables in Docker is Dockerfile or Task definition in case of AWS-ECS.

The current docker-entrypoint will set env for that session only, that is why you got empty value when do ssh, but you can verify it has been in that session but this is not recommended approach in Docker.

You can verify

#!/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

You will be able to see this value but it will not be available in another session.

Another example,

Dockerfile

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

entrypoint

#!/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)"

You will see the node process is able to process the environment, but if you run a command inside the container it will show undefined.

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

Two Option to deal with ENV,

Pass the IP ENV if you already know the IP, as instance always launches before container, for example

enter image description here

The second option is passing environment variable to a java class in command line or How to pass system properties to a jar file if that seems to work for then you entrypoint will be

java -DECS_INSTANCE_IP_ADDRESS=$(wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4) -jar myjar.jar 
Adiii
  • 54,482
  • 7
  • 145
  • 148
  • Tried passing the environment variable to a java class via command line but it still shows as blank. The line executed is: `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"]` – Lucas Gomez Dec 03 '19 at 19:45
  • Also passing the ENV variables via task definition does not allow to input a variable that needs to be fetched, only static variables. – Lucas Gomez Dec 03 '19 at 19:47
  • yes task definition allows only static, while the entrypoint one approch i test it out using nodejs, and it should work with java too. or try with `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`, better to use entrypoint script then entrypoint. – Adiii Dec 03 '19 at 20:03
1

This is how I fixed it, I believe there was also an error on the metadata URL and that could have been the culprit.

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"]

entrypoint.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 (not full file):

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

Eureka is printing a template error on the Eureka status page but microservices do connect and respond to actuator health and swagger-ui from Spring Boot.

Lucas Gomez
  • 145
  • 1
  • 3
  • 12