While I create an image based on official Jenkins Docker and copy .ssh
directory to jenkins
user's home (/var/jenkins_home
), owner of the /var/jenkins_home/.ssh
becomes root
which prevents me to open ssh session with jenkins
user. Using RUN chown -R 1000:1000 /var/jenkins_home/.ssh
in Dockerfile
does not work.
Also, permissions of the files copied while creating image becomes 644
by default. However, to be able to open ssh session, permissions of /var/jenkins_home/.ssh/id_rsa
must be 600
.
How can I create an image from official Jenkins Docker image having provided ssh keys for jenkins
user?
Setting up your environmentInstall the Docker Pipelines plugin on Jenkins: Manage Jenkins → Manage Plugins. Search Docker Pipelines, click on Install without restart and wait until is done. Upload your Dockerfile definition to your Github repository.
Whenever a Jenkins build requires Docker, it will create a “Cloud Agent” via the plugin. The agent will be a Docker Container configured to talk to our Docker Daemon. The Jenkins build job will use this container to execute the build and create the image before being stopped.
In the case of Jenkins, this means the Docker image contains the files you require to support a minimal Linux operating system, along with the version of Java required to run Jenkins. A container is an isolated environment in the OS where the Docker image is executed.
Official Jenkins Docker image defines Jenkins home directory(/var/jenkins_home
) as VOLUME
which prevents RUN chown -R 1000:1000 /var/jenkins_home/...
to be effective:
$ touch test.txt
$ vi Dockerfile
--- Dockerfile ---
FROM jenkins:2.32.3
COPY test.txt /tmp
COPY test.txt /var/jenkins_home/test.txt
USER root
RUN chown 1000:1000 /tmp/test.txt
RUN chown 1000:1000 /var/jenkins_home/test.txt
USER jenkins
--- Dockerfile ---
$ docker build -t myjenkins .
...
$ docker run -it myjenkins /bin/bash
jenkins@750f43b7e9ec:/$ ls -all /var/jenkins_home/test.txt
-rw-r--r-- 1 root root 0 Mar 24 06:54 /var/jenkins_home/test.txt
jenkins@750f43b7e9ec:/$ ls -all /tmp/test.txt
-rw-r--r-- 1 jenkins jenkins 0 Mar 24 06:54 /tmp/test.txt
Official Jenkins Docker has a solution for it: Copying directories and files those must be under jenkins user's home to /usr/share/jenkins/ref/
. When jenkins container starts, it will check /var/jenkins_home
has this reference content, and copy them there if required. (See Installing more tools
of official Jenkins Docker documentation).
$ touch test.txt
$ vi Dockerfile
--- Dockerfile ---
FROM jenkins:2.32.3
COPY test.txt /usr/share/jenkins/ref/test.txt
--- Dockerfile ---
$ docker build -t myjenkins .
...
$ docker run -it myjenkins /bin/bash
jenkins@1e9520a92f8e:/$ ls -all /var/jenkins_home/test.txt
-rw-r--r-- 1 jenkins jenkins 0 Mar 24 08:21 /var/jenkins_home/test.txt
Now we need to set file's permission to 600
:
$ touch test.txt
$ vi Dockerfile
--- Dockerfile ---
FROM jenkins:2.32.3
COPY test.txt /usr/share/jenkins/ref/test.txt
USER root
RUN chmod 600 /usr/share/jenkins/ref/test.txt
USER jenkins
--- Dockerfile ---
$ docker build -t myjenkins .
...
$ docker run -it myjenkins /bin/bash
cp: cannot open ‘/usr/share/jenkins/ref/test.txt’ for reading: Permission denied
Strange! The error is thrown by Jenkins' initialization script: jenkins.sh. The script runs while Jenkins container is starting. What we can do here is changing file permission while container starts instead of changing it in Dockerfile
. Then we need an entrypoint script that copies the file to /var/jenkins_home
, changes it's permission and, as a last step, calls jenkins.sh
. I created entrypoint.sh
based on https://github.com/openfrontier/docker-jenkins/blob/master/entrypoint.sh.
$ touch test.txt
$ vi entrypoint.sh
--- enrypoint.sh ---
#! /bin/bash -e
cp /usr/share/jenkins/ref/test.txt /var/jenkins_home
chmod 600 /var/jenkins_home/test.txt
echo "start JENKINS"
# if 'docker run' first argument start with '--' the user is passing jenkins launcher arguments
if [[ $# -lt 1 ]] || [[ "$1" == "--"* ]]; then
exec /bin/tini -- /usr/local/bin/jenkins.sh "$@"
fi
exec "$@"
--- enrypoint.sh ---
$ vi Dockerfile
--- Dockerfile ---
FROM jenkins:2.32.3
COPY test.txt /usr/share/jenkins/ref/test.txt
COPY entrypoint.sh /entrypoint.sh
USER root
RUN chown 1000:1000 /entrypoint.sh \
&& chmod +x /entrypoint.sh
USER jenkins
ENTRYPOINT ["/entrypoint.sh"]
--- Dockerfile ---
$ docker build -t myjenkins .
...
$ docker run -it myjenkins /bin/bash
start JENKINS
jenkins@770ba9099cb4:/$ ls -all /var/jenkins_home/test.txt
-rw------- 1 jenkins jenkins 0 Mar 24 10:36 /var/jenkins_home/test.txt
Let's make it for ssh
directory having id_rsa
and id_rsa.pub
files. Note that as directory name I used ssh
instead of .ssh
. Otherwise content of .ssh
would directly be copied to /var/jenkins_home
. That is how Docker behaves for directories whose names begin with a dot (e.g. .m2).
Here is all the necessary steps. You can see that I could successfully open an ssh session from within container:
$ ls -all
total 8
drwxr-xr-x 3 myuser mygroup 54 Mar 24 13:41 .
drwxr-xr-x 6 myuser mygroup 70 Mar 24 09:54 ..
-rw-r--r-- 1 myuser mygroup 242 Mar 24 13:35 Dockerfile
-rw-r--r-- 1 myuser mygroup 338 Mar 24 13:33 entrypoint.sh
drwx------ 2 myuser mygroup 36 Mar 24 11:24 ssh
$ ls -all ssh/
total 8
drwx------ 2 myuser mygroup 36 Mar 24 11:24 .
drwxr-xr-x 3 myuser mygroup 54 Mar 24 13:41 ..
-rw------- 1 myuser mygroup 1679 Mar 24 11:23 id_rsa
-rw-r--r-- 1 myuser mygroup 391 Mar 24 11:23 id_rsa.pub
$ vi entrypoint.sh
--- enrypoint.sh ---
#! /bin/bash -e
mkdir -p /var/jenkins_home/.ssh
mv /usr/share/jenkins/ref/.ssh/id_rsa /var/jenkins_home/.ssh
chmod 600 /var/jenkins_home/.ssh/id_rsa
echo "start JENKINS"
# if 'docker run' first argument start with '--' the user is passing jenkins launcher arguments
if [[ $# -lt 1 ]] || [[ "$1" == "--"* ]]; then
exec /bin/tini -- /usr/local/bin/jenkins.sh "$@"
fi
exec "$@"
--- enrypoint.sh ---
$ vi Dockerfile
--- Dockerfile ---
FROM jenkins:2.32.3
# Copy ssh as .ssh
COPY ssh/ /usr/share/jenkins/ref/.ssh
COPY entrypoint.sh /entrypoint.sh
USER root
# Change owner of .ssh directory and files under it to
# jenkins user's owner (1000:1000) and make sure
# permisson of id_rsa is not 600.
RUN chown -R 1000:1000 /usr/share/jenkins/ref/.ssh \
&& chmod 644 /usr/share/jenkins/ref/.ssh/id_rsa
RUN chown 1000:1000 /entrypoint.sh \
&& chmod +x /entrypoint.sh
USER jenkins
ENTRYPOINT ["/entrypoint.sh"]
--- Dockerfile ---
$ docker build -t myjenkins .
...
$ docker run -it myjenkins /bin/bash
jenkins@3090dda362d6:/$ ls -all /var/jenkins_home/.ssh/id_rsa
-rw------- 1 jenkins jenkins 1679 Mar 24 08:23 /var/jenkins_home/.ssh/id_rsa
jenkins@3090dda362d6:/$ ssh rose1
The authenticity of host 'rose1 (XX.XX.XX.XX)' can't be established.
ECDSA key fingerprint is XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'rose1,XX.XX.XX.XX' (ECDSA) to the list of known hosts.
Last login: Thu Mar 23 15:55:41 2017 from 10.74.200.56
[jenkins@rose1 ~]$
Update 1
I have uploaded given files to GitHub: https://github.com/kumlali/stackoverflow_answers/tree/master/docker_jenkins_ssh_keys/answer1
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