We have multiple Jenkins ssh agents, multiple build containers with different jdk versions and containers use java to publish stuff (sonar results etc.) to other servers.
The containers need to trust the same servers as the host machine (Jenkins ssh agent). So java cacerts inside the container’s jdk needs to match the host machine cacerts. For this I add args:
agent {
docker {
registryUrl "https://private.registry"
registryCredentialsId "private-registry-creds"
image "build_container_jdk17"
args "-v /host/cacerts:/usr/share/jdk-17.0.6+10/lib/security/cacerts:ro"
}
}
when starting the container from a Jenkinsfile.
Problem is the jdk path changes between containers. jdk path inside the container is also stored in an environment variable $JAVA_HOME.
What is the simplest way to get the JAVA_HOME environment variable from inside the container to use on the volume command line argument?
agent {
docker {
registryUrl "https://private.registry"
registryCredentialsId "private-registry-creds"
image "build_container_jdk17"
args "-v /host/cacerts:${CONTAINER_JAVA_HOME}/lib/security/cacerts:ro"
}
}
I tried using:
args '-v /host/cacerts:${JAVA_HOME}/lib/security/cacerts:ro'
Hopeful that the env variable on the right side of the colon would be evaluated from inside the container. This resulted in "invalid volume specification".
I think there’s a way to start the container in one stage, set the variable and restart in the next stage using the variable. I figured I’d ask before trying this since it seems overly complicated and there might be some obvious solution I’m missing.
2
Answers
In his answer mbwmd gave two options to fetch the environment variable from inside a docker container. These are both valid and it depends on your use case which one you would choose.
I wanted to expand on this answer and give the details from Jenkins pipeline perspective as that was part of my question.
When you use a pipeline where the pipeline agent is also the host for the containers. The "docker inspect" option can be preferable:
The docker inspect command was derived from the answer by Vonc here. You could also use jq like mbwmd suggested in his answer if you prefer that. I did not have jq available and wanted to avoid the dependency.
Advantage of this option is you do not need to start the container to get the env variable.
Disadvantage might be that you have to run a docker command from your pipeline. Depending on the pipeline setup this might cause issues in some situations.
Option #2 avoids using docker commands by using a stage to save the environment variable:
This is a good option if you are running multiple stages anyway and do not need the args to be set the first time you run up the container.
you have two options:
example:
docker inspect jenkins/jenkins:lts | jq -r '.[].Config.Env[] | select(contains("JAVA_HOME")) | split("=")[1]'
example:
docker run --rm --entrypoint='printenv' jenkins/jenkins:lts JAVA_HOME
Both options will output
/opt/java/openjdk
, which in turn could be passed into the local evaluation of your volume definitionOption 1 should be faster but requires
jq
to parse the json out put of inspect.Respect quotes and backticks.