Reputation: 651
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?
Upvotes: 7
Views: 12546
Reputation: 651
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
Upvotes: 10
Reputation: 651
I have found a little bit complex but more generic way to achieve that. New solution requires;
ssh-agent
, credentials
and ssh-credentials
pluginsMain idea here is to copy ssh keys into a directory other than JENKINS_HOME
, adding them to Jenkins' credentials by using post-initialization script and using ssh-agent
plug-in for ssh.
I have uploaded necessary setup and instructions to GitHub: https://github.com/kumlali/stackoverflow_answers/tree/master/docker_jenkins_ssh_keys/answer2
Upvotes: 1