如何创建使用为 jenkins 用户提供的 ssh 密钥的 Jenkins Docker 映像?

Ali*_*ali 6 ssh jenkins docker

当我基于官方 Jenkins Docker 创建一个映像并将.ssh目录复制到jenkins用户的家 ( /var/jenkins_home) 时,其所有者/var/jenkins_home/.sshroot阻止我与jenkins用户打开 ssh 会话。使用RUN chown -R 1000:1000 /var/jenkins_home/.sshinDockerfile不起作用。

此外,创建图像时复制的文件的权限变为644默认。但是,为了能够打开 ssh 会话,权限/var/jenkins_home/.ssh/id_rsa必须是600.

如何从为jenkins用户提供 ssh 密钥的官方 Jenkins Docker 映像创建映像?

Ali*_*ali 9

官方 Jenkins Docker 镜像定义了 Jenkins 主目录( /var/jenkins_home) 以VOLUME防止RUN chown -R 1000:1000 /var/jenkins_home/...生效:

$ 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
Run Code Online (Sandbox Code Playgroud)

官方 Jenkins Docker 有一个解决方案:将那些必须在 jenkins 用户家下的目录和文件复制到/usr/share/jenkins/ref/. 当 jenkins 容器启动时,它会检查是否/var/jenkins_home有此引用内容,并在需要时将它们复制到那里。(见Installing more tools官员詹金斯泊坞文档)。

$ 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
Run Code Online (Sandbox Code Playgroud)

现在我们需要将文件的权限设置为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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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 ~]$
Run Code Online (Sandbox Code Playgroud)

Update 1

I have uploaded given files to GitHub: https://github.com/kumlali/stackoverflow_answers/tree/master/docker_jenkins_ssh_keys/answer1