Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a Jenkins Docker image that uses provided ssh keys for jenkins user?

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?

like image 373
Ali Sadik Kumlali Avatar asked Mar 24 '17 12:03

Ali Sadik Kumlali


People also ask

How do I make Docker images automatically with Jenkins pipeline?

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.

Can Jenkins produce a Docker image?

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.

What is required for Jenkins to build a Docker image?

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.


1 Answers

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

like image 50
Ali Sadik Kumlali Avatar answered Sep 30 '22 07:09

Ali Sadik Kumlali