Unable to pass the env variable to container - docker

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine
ENV CORECLR_ENABLE_PROFILING=1 \
CORECLR_PROFILER={846F5F1C-F9AE-4B07-969E-05C26BC060D8} \
CORECLR_PROFILER_PATH=/opt/datadog/Datadog.Trace.ClrProfiler.Native.so \
DD_INTEGRATIONS=/opt/datadog/integrations.json \
DD_DOTNET_TRACER_HOME=/opt/datadog
WORKDIR /app
RUN apk --no-cache update \
&& apk add bash make curl
ARG TRACER_VERSION=1.19.1
RUN mkdir -p /opt/datadog
RUN curl -L https://github.com/DataDog/dd-trace-dotnet/releases/download/v${TRACER_VERSION}/datadog-dotnet-apm-${TRACER_VERSION}.tar.gz \
| tar xzf - -C /opt/datadog
WORKDIR /app
COPY --from=buildcontainer /app/build .
COPY ./Entrypoint.sh /
RUN chmod +x /Entrypoint.sh && /Entrypoint.sh
ENTRYPOINT ["dotnet","testdatadog.dll"]
Entrypoint.sh
#!/bin/bash
set -e
curl http://169.254.169.254/latest/meta-data/local-ipv4 > temp_var
export DD_AGENT_HOST=$(cat temp_var)
exec "$#"
When I ssh in to my ec2 and see for environment variables I don't see the DD_AGENT_HOST set. When I am manually trying to set the env it works. Am I missing something? appreciate the inputs.

The gist of the problem is that your directive RUN chmod +x /Entrypoint.sh && /Entrypoint.sh got executed at BUILD time, and had no impact on your RUNTIME environment.
Konrad's correct in changing your ENTRYPOINT to have Entrypoint.sh change your environment.
The issue with Konrad's solution is that the run command he used to start the container had no impact on the bash shell that docker ran when he issued the exec command.
Expanding on Konrad's answer a little, you can actually get entrypoint.sh to set your environment for you.
I copied Konrad's Dockerfile, but changed the ENTRYPOINT as follows:
FROM alpine:latest AS build
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
FROM alpine:latest
RUN apk add --no-cache bash
COPY --from=build /entrypoint.sh /entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh", "bash" ]
Now, the entrypoint.sh will set the environment, and execute bash.
I used Konrad's command to run the container:
docker run -itd --rm --name entrypoint entrypoint-test:latest
24a7f3d740c37bb345374a835a465482e3bf49a04361e55205b6d63af48d5c3d
This results in the container being launched. Entrypoint.sh will run bash for us, but it's in daemon mode, so we will have to attach to it:
$ docker attach 24a7f3d740c37bb345374a835a465482e3bf49a04361e55205b6d63af48d5c3d
bash-5.0# echo $DD_AGENT_HOST
127.0.0.1
Alternatively, you can just run the docker image without the -d option, avoiding the daemon mode:
$ docker run -it --rm --name entrypoint entrypoint-test:latest
bash-5.0# echo $DD_AGENT_HOST
127.0.0.1
bash-5.0# echo Hit Ctrl-P Ctrl-Q to leave this container running
All that said, will this work for your dotnet invocation?
ENTRYPOINT [ "/entrypoint.sh", "dotnet" , "testdatadog.dll" ]

This:
RUN chmod +x /Entrypoint.sh && /Entrypoint.sh
actually runs the following command:
bash -c "chmod +x /Entrypoint.sh && /Entrypoint.sh"
Your script sets the environment variable for the Bash instance that runs it, which itself exits as soon as the script is finished, discarding its environment.
You need to move the execution of Entrypoint.sh to the ENTRYPOINT line.
Edit:
So this is my test Dockerfile (note that copying and changing permissions on the script is done in a separate stage to reduce the size of the final image):
FROM alpine:latest AS build
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
FROM alpine:latest
RUN apk add --no-cache bash
COPY --from=build /entrypoint.sh /entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh", "sleep", "10m" ]
and entrypoint.sh:
#!/bin/bash
set -e
echo "127.0.0.1" > temp_var
export DD_AGENT_HOST=$(cat temp_var)
exec "$#"
I ran the following commands:
docker build -t entrypoint-test .
docker run -itd --rm --name entrypoint entrypoint-test:latest
docker exec -it entrypoint bash
and inside the newly opened Bash shell:
export
Result:
declare -x HOME="/root"
declare -x HOSTNAME="c951e699bf7b"
declare -x OLDPWD
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
declare -x PWD="/"
declare -x SHLVL="1"
declare -x TERM="xterm"
No DD_AGENT_HOST!
So the I searched for the container's main process (in my case sleep)
ps -a | grep sleep
and got
1 root 0:00 sleep 10m
32 root 0:00 grep sleep
Finally I ran
strings /proc/1/environ
to see the environment of that proces.
Result:
HOSTNAME=3f9760ceb473
PWD=/
HOME=/root
TERM=xterm
SHLVL=0
DD_AGENT_HOST=127.0.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
DD_AGENT_HOST found!
So what's happening?
It's simple. entrypoint.sh sets the variable only for the process it executes - in my case sleep. docker exec creates a new, unrelated process running Bash. Since a new process (both in Linux and Windows) inherits environment from the parent process and the new Bash process, spawned by docker exec, is not a child (but rather a sibling) of the container's main process, it has no knowledge of DD_AGENT_HOST variable.
I hope this helps.
Edit 2:
I believe that what David Maze meant is that you can replace
ENTRYPOINT [ "/entrypoint.sh", "sleep", "10m" ]
with
ENTRYPOINT [ "/entrypoint.sh" ]
CMD [ "sleep", "10m" ]
and then you can run
docker run -it --rm --name entrypoint entrypoint-test:latest bash
so that entrypoint.sh executes bash rather than sleep 10m, allowing you to inspect the environment directly rather than through /proc/$pid/environ.
The equivalent in your Dockerfile would be:
ENTRYPOINT [ "/Entrypoint.sh" ]
CMD [ "dotnet" , "testdatadog.dll" ]

Related

How can i Convert CMD to Entrypoint instruction in dockerfile

My cmd instruction in dockerfile is:
CMD /etc/init.d/ssh start && su - gpadmin bash -c /home/gpadmin/entrypoint.sh && tail -f /dev/null
I want to convert it to ENTRYPOINT instruction. My entrypoint script file is entrypoint.sh
I want to enter the entrypoint script with gpadmin user and also i want the container to stay alive with docker run command that is why i am using tail -f /dev/null command

Docker entrypoint user switch

I am creating a docker image to be used as base for other applications. The requirements are:
application must run as non root user
optionally, certificates must be loaded before executing the application
I created the following Dockerfile
FROM node:14.15.1-alpine3.11
# Specify node/npm related envs
ENV NPM_CONFIG_LOGLEVEL=warn \
NO_UPDATE_NOTIFIER=1
# Change cwd for next commands
WORKDIR /home/node/code
# Set local registry
RUN echo "registry=http://192.168.100.175:4873" > /home/node/.npmrc && \
chown -R node:node /home/node && \
apk add --update --no-cache tzdata=2021a-r0 ca-certificates=20191127-r2 su-exec=0.2-r1
# Need root to update CA certificates in entrypoint.sh and then switch back to restricted user
USER root
COPY entrypoint.sh entrypoint.sh
ENTRYPOINT [ "./entrypoint.sh" ]
# Execute the service entrypoint
CMD ["sh"]
and entrypoint.sh
#!/bin/sh
DIR_CRT="/home/node/certificates"
if [ "$(ls -A ${DIR_CRT})" ]; then
cp -r "${DIR_CRT}/." /usr/local/share/ca-certificates/
update-ca-certificates
echo "******* Updated CA certificates *******"
fi
exec su-exec node "$#"
This seems to cover the requirements but I noticed that if I open a shell inside the image it is always with node user even if I specify a different one from parameters:
$ docker run --rm -it -u root docker.repo.asts.com/scc-2.0/app-tg:1.6.0-beta50 whoami
node
Is it possible to have both the requirements and the possibility to execute a direct command with required user?
docker run -u xxx works only if you did not use exec in entrypoint to change PID1. E.g.
$ docker run --rm -it node:14.15.1-alpine3.11 whoami
root
$ docker run --rm -u node -it node:14.15.1-alpine3.11 whoami
node
After you use exec su-exec node "$#" to change the user to node, you won't have way to use -u xxx again. The only solution is override the entrypoint like next, but I don't see the meaning here:
docker run --rm -u root --entrypoint=/bin/sh xxx
But, you still could use docker exec -u root or docker exec -u node to get a shell for that user in exist container.

Replacing Docker environment variables while running the image locally

Docker Image : test
Following are default value in Dockerfile:
ENV users=2
ENV rampup=10
ENV duration=120
ENV environment=DEV
Following is entrypoint
ENTRYPOINT ["/entrypoint.sh"]
entrypoint.sh :
bash ./bin/jmeter.sh -n -t -Jenvironment=${environment} -Jusers=${users} -Jrampup=${rampup} -Jduration=${duration} -j ${workspace}report.log
Now I want to run it locally by replacing the environment variables:
docker run test -e environment=STG -e users=20 -e rampup=10 -e duration=120
But, somehow the values are not getting replaced. What is that I am doing incorrectly, can someone please help?
Any docker run options (like -e to set environment variables) need to go before the image name in the docker run command. Anything after the image name is interpreted as the command you'd like the container to run, and when you also have an entrypoint, gets passed as parameters to the entrypoint. (If you edit your script to include the line echo "$#" you'll see those -e options.)
docker run \
-e environment=STG -e users=20 -e rampup=10 -e duration=120 \
test
Dockerfile and Docker run command seems fine, I am pretty sure the issue is not with Docker, Here is the simplest example that you can.
FROM alpine
ENV users=2
ENV rampup=10
ENV duration=120
ENV environment=DEV
#COPY entrypoint.sh /entrypoint.sh
RUN echo $'#!/bin/ash \n\
echo \"env is Jenvironment=${environment} -Jusers=${users} -Jrampup=${rampup} -Jduration=${duration} -j ${workspace}report.log"' > /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
Build
Docker build -t testenv .
Run
docker run -e rampup=10 -e users=test -t alpintenv ash
So you can try to change you entrypoint.sh to
#!/bin/bash
./bin/jmeter.sh -n -t -Jenvironment=${environment} -Jusers=${users} -Jrampup=${rampup} -Jduration=${duration} -j ${workspace}report.log

Run docker with dynamic parameter

I'm trying to run a java application on a docker container where the jvm argument of the java program would be dynamic.
Dockerfile:
FROM amazonlinux
ADD http://company.com/artifactory/bins-release-local/com/marc/1.3.1/marc-1.3.1.tar.gz /root/
ADD log4j2.xml /root/
RUN tar xzf /root/marc-1.3.1.tar.gz -C /root && rm -f /root/marc-1.3.1.tar.gz
RUN yum install -y java
ENTRYPOINT ["/bin/bash", "-c", "/usr/bin/java", "${JVM_ARGS}", "-jar", "/root/marc.jar"]
I try to run the container like so:
docker run --rm -it --env-file jvm_args.env -e CLIENT=google moshe/java:latest
And the jvm_args.env is:
JVM_ARGS=-d64
-Dicmq=${CLIENT}
-Dlog4j.configurationFile=/root/log4j2.xml
-server
I couldn't seem to get it to work. I need the client to be dynamic and the JVM_ARGS should contain the client.
Ideas?

Dockerfile entrypoint not lunching on interactive mode

I'm absolutely new to Docker. I want a docker to do git pull / git push / resolve conflicts on some repositories.
I've created this Dockerfile
FROM needcaffeine/git
RUN apt-get update
RUN mkdir -p /root/.ssh
ADD .ssh/id_rsa /root/.ssh/id_rsa
RUN chmod 700 /root/.ssh/id_rsa
RUN echo "Host github.com\n\tStrictHostKeyChecking no\n" >> /root/.ssh/config
VOLUME ["/root/repos"]
ENTRYPOINT ["bash"]
but when I run it with
docker run my-tag-for-that-image
It don't give me an interactive prompt even when I'm using bash as ENTRYPOINT.
Try passing -it to docker run, i.e.:
docker run my-tag-for-that-image
From docker help run:
-i, --interactive=false Keep STDIN open even if not attached
-t, --tty=false Allocate a pseudo-TTY

Resources