I'm trying to execute an SSH command from inside a Docker container in a Jenkins pipeline. I'm using the CloudBees Docker Pipeline Plugin to spin up the container and execute commands, and the SSH Agent Plugin to manage my SSH keys. Here's a basic version of my Jenkinsfile:
node { step([$class: 'WsCleanup']) docker.image('node').inside { stage('SSH') { sshagent (credentials: [ 'MY_KEY_UUID' ]) { sh "ssh -vvv -o StrictHostKeyChecking=no [email protected] uname -a" } } } }
When the SSH command runs, I get this error:
+ ssh -vvv -o StrictHostKeyChecking=no [email protected] uname -a No user exists for uid 1005
I combed through the logs and realized the Docker Pipeline Plugin is automatically telling the container to run with the same user that is logged in on the host by passing a UID as a command line argument:
$ docker run -t -d -u 1005:1005 [...]
I decided to check what users existed in the host and the container by running cat /etc/passwd
in each environment. Sure enough, the list of users was different in each. 1005 was the jenkins user on the host machine, but that UID didn't exist in the container. To solve the issue, I mounted /etc/passwd
from the host to the container when spinning it up:
node { step([$class: 'WsCleanup']) docker.image('node').inside('-v /etc/passwd:/etc/passwd') { stage('SSH') { sshagent (credentials: [ 'MY_KEY_UUID' ]) { sh "ssh -vvv -o StrictHostKeyChecking=no [email protected] uname -a" } } } }
The solution provided by @nathan-thompson is awesome, but in my case I was unable to find the user even in the /etc/passwd
of the host machine! It means mounting the passwd
file did not fix the problem. This question https://superuser.com/questions/580148/users-not-found-in-etc-passwd suggested some users are logged in the host using an identity provider like LDAP.
The solution was finding a way to add the proper line to the passwd
file on the container. Calling getent passwd $USER
on the host will provide the passwd
line for the Jenkins user running the container.
I added a step running on the node (and not the docker agent) to get the line and save it in a file. Then in the next step I mounted the generated passwd
to the container:
stages { stage('Create passwd') { steps { sh """echo \$(getent passwd \$USER) > /tmp/tmp_passwd """ } } stage('Test') { agent { docker { image '*******' args '***** -v /tmp/tmp_passwd:/etc/passwd' reuseNode true registryUrl '*****' registryCredentialsId '*****' } } steps { sh """ssh -i ******** """ } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With