1

I try to clone a test project from GitLab using a Dockerfile and an SSH key pair: ssh-keygen -t rsa -P "". The private key is passwordless, the public key is published at the GitLab account.

This can be quickly tested by anyone else, just open an account on GitLab and publish your SSH public key, and add a new empty project to clone.

Without Docker, using ssh -i C:\path\to\my\private_key\id_rsa git@gitlab.com, it works. Without Docker, cloning the project also works.

I load the private key in the Dockerfile and delete it in the end. Not important, but for all who see a security risk here: I delete the key pair directly after usage, both on client and server. I only try to get around the password entry for the user account when cloning, since that does not seem to work during the run of a Dockerfile, and would be the real security risk as it could leave the password in the logs.

Start: Go to the Dockerfile directory, paste the private key "id_rsa" in a new ".ssh" subfolder. Then:

docker build -t NEW_IMAGENAME . --build-arg ssh_prv_key="$(cat ./.ssh/id_rsa)"

Working code up to now:

FROM vcatechnology/linux-mint:18.2
ARG ssh_prv_key
RUN apt-get update && \
    apt upgrade -y && \
    apt-get install -y git  
RUN apt-get install -y openssh-client # openssh-server
RUN mkdir /root/.ssh/
RUN echo "Host *\n  User git\n  HostName gitlab.com\n  AddKeysToAgent yes\n  IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config
RUN echo "$ssh_prv_key" > /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa

RUN ssh-keyscan -t rsa -H gitlab.com >> /root/.ssh/known_hosts
RUN ssh -o StrictHostKeyChecking=no git@gitlab.com || true
RUN eval "$(ssh-agent -s)"
RUN chmod 666 /dev/tty

Which leads to:

docker build -t CONTAINERNAME . --build-arg ssh_prv_key="$(cat /.ssh/id_rsa)"
[+] Building 254.9s (14/17)
 => [internal] load build definition from Dockerfile                                                                                                                                                                                    0.0s
 => => transferring dockerfile: 6.84kB                                                                                                                                                                                                  0.0s
 => [internal] load .dockerignore                                                                                                                                                                                                       0.0s
 => => transferring context: 2B                                                                                                                                                                                                         0.0s
 => [internal] load metadata for docker.io/vcatechnology/linux-mint:18.2                                                                                                                                                                0.8s
 => CACHED [ 1/14] FROM docker.io/vcatechnology/linux-mint:18.2@sha256:0557a4999d43c0c622f3a57c3db5b13536024fb5999ecf4f03c6ffec0e4fdb47                                                                                                 0.0s
 => [ 2/14] RUN apt-get update &&  apt upgrade -y &&  apt-get install -y git                                                                                                                                                          244.3s
 => [ 3/14] RUN apt-get install -y openssh-client # openssh-server                                                                                                                                                                      3.1s
 => [ 4/14] RUN mkdir /root/.ssh/                                                                                                                                                                                                       0.6s
 => [ 5/14] RUN echo "Host *\n  User git\n  HostName gitlab.com\n  AddKeysToAgent yes\n  IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config                                                                                         0.6s
 => [ 6/14] RUN echo "$(cat /.ssh/id_rsa)" > /root/.ssh/id_rsa &&     chmod 600 /root/.ssh/id_rsa                                                                                                                                       0.6s
 => [ 7/14] RUN ssh-keyscan -t rsa -H gitlab.com >> /root/.ssh/known_hosts                                                                                                                                                              1.3s
 => [ 8/14] RUN ssh -o StrictHostKeyChecking=no git@gitlab.com || true                                                                                                                                                                  1.6s
 => [ 9/14] RUN eval "$(ssh-agent -s)"                                                                                                                                                                                                  0.6s
 => [10/14] RUN chmod 666 /dev/tty                                                                                                                                                                                                      0.6s

The last steps after this working code in the Dockerfile would be as follows, though each of the first three lines stops the script up to now:

RUN ssh-add /root/.ssh/id_rsa
RUN ssh -tti /root/.ssh/id_rsa git@gitlab.com
RUN git clone git@gitlab.com:GITLAB_USERNAME/test.git
RUN rm -r /root/.ssh
  1. If RUN ssh-add /root/.ssh/id_rsa comes directly after the last working code:

      => ERROR [11/14] RUN ssh-add /root/.ssh/id_rsa                                                                                                                                                                                         0.6s
     ------
      > [11/14] RUN ssh-add /root/.ssh/id_rsa:
     #14 0.579 Could not open a connection to your authentication agent.
     ------
     executor failed running [/bin/sh -c ssh-add /root/.ssh/id_rsa]: exit code: 2
    

The error Could not open a connection to your authentication agent. is famous, see Could not open a connection to your authentication agent. But I could not solve it with that thread.

  1. If RUN ssh -tti /root/.ssh/id_rsa git@gitlab.com comes directly after the last working code:

     #14 1.545 Permission denied (publickey,keyboard-interactive).
     ------
     executor failed running [/bin/sh -c ssh -tti /root/.ssh/id_rsa git@gitlab.com]: exit code: 255
    
  2. If RUN git clone git@gitlab.com:GITLAB_USERNAME/test.git comes directly after the last working code:

     #16 0.450 Cloning into 'test'...
     #16 1.466 Permission denied (publickey,keyboard-interactive).
     #16 1.467 fatal: Could not read from remote repository.
     #16 1.467
     #16 1.467 Please make sure you have the correct access rights
     #16 1.467 and the repository exists.
     ------
     executor failed running [/bin/sh -c git clone git@gitlab.com:GITLAB_USERNAME/test.git]: exit code: 128
    

Thus, ssh obviously needs the "ssh-add" that adds the private key to the "ssh-agent" to know the private key on the client at all, and I guess it also needs the ssh -tti /root/.ssh/id_rsa git@gitlab.com to let ssh know the way to the server.

  1. If RUN ssh -Tvvv git@gitlab.com (the -T avoids Pseudo-terminal will not be allocated because stdin is not a terminal) comes directly after the last working code (this is not needed in the final Dockerfile, it is just a check):

      => ERROR [12/12] RUN ssh -Tvvv git@gitlab.com                                                                                                                                                                                          1.2s
     ------
      > [12/12] RUN ssh -Tvvv git@gitlab.com:
     #16 0.376 OpenSSH_7.2p2 Ubuntu-4ubuntu2.10, OpenSSL 1.0.2g  1 Mar 2016
     #16 0.376 debug1: Reading configuration data /etc/ssh/ssh_config
     #16 0.376 debug1: /etc/ssh/ssh_config line 19: Applying options for *
     #16 0.376 debug1: /etc/ssh/ssh_config line 57: Applying options for *
     #16 0.376 debug2: resolving "gitlab.com" port 22
     #16 0.397 debug2: ssh_connect_direct: needpriv 0
     #16 0.397 debug1: Connecting to gitlab.com [172.65.251.78] port 22.
     #16 0.450 debug1: Connection established.
     #16 0.450 debug1: permanently_set_uid: 0/0
     #16 0.450 debug1: key_load_public: No such file or directory
     #16 0.450 debug1: identity file /root/.ssh/id_rsa type -1
     #16 0.450 debug1: key_load_public: No such file or directory
     #16 0.450 debug1: identity file /root/.ssh/id_rsa-cert type -1
     #16 0.451 debug1: Enabling compatibility mode for protocol 2.0
     #16 0.451 debug1: Local version string SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.10
     #16 0.977 debug1: Remote protocol version 2.0, remote software version OpenSSH_7.9p1 Debian-10+deb10u2
     #16 0.977 debug1: match: OpenSSH_7.9p1 Debian-10+deb10u2 pat OpenSSH* compat 0x04000000
     #16 0.977 debug2: fd 3 setting O_NONBLOCK
     #16 0.977 debug1: Authenticating to gitlab.com:22 as 'git'
     #16 0.977 debug3: hostkeys_foreach: reading file "/root/.ssh/known_hosts"
     #16 0.977 debug3: send packet: type 20
     #16 0.977 debug1: SSH2_MSG_KEXINIT sent
     #16 0.994 debug3: receive packet: type 20
     #16 0.994 debug1: SSH2_MSG_KEXINIT received
     #16 0.994 debug2: local client KEXINIT proposal
     #16 0.994 debug2: KEX algorithms: curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,ext-info-c
     #16 0.994 debug2: host key algorithms: ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
     #16 0.994 debug2: ciphers ctos: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com,aes128-cbc,aes192-cbc,aes256-cbc,3des-cbc
     #16 0.994 debug2: ciphers stoc: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com,aes128-cbc,aes192-cbc,aes256-cbc,3des-cbc
     #16 0.994 debug2: MACs ctos: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
     #16 0.994 debug2: MACs stoc: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
     #16 0.994 debug2: compression ctos: none,zlib@openssh.com,zlib
     #16 0.994 debug2: compression stoc: none,zlib@openssh.com,zlib
     #16 0.994 debug2: languages ctos:
     #16 0.994 debug2: languages stoc:
     #16 0.994 debug2: first_kex_follows 0
     #16 0.994 debug2: reserved 0
     #16 0.994 debug2: peer server KEXINIT proposal
     #16 0.994 debug2: KEX algorithms: curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1
     #16 0.994 debug2: host key algorithms: rsa-sha2-512,rsa-sha2-256,ssh-rsa,ecdsa-sha2-nistp256,ssh-ed25519
     #16 0.994 debug2: ciphers ctos: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
     #16 0.994 debug2: ciphers stoc: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com
     #16 0.994 debug2: MACs ctos: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
     #16 0.994 debug2: MACs stoc: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1
     #16 0.994 debug2: compression ctos: none,zlib@openssh.com
     #16 0.994 debug2: compression stoc: none,zlib@openssh.com
     #16 0.994 debug2: languages ctos:
     #16 0.994 debug2: languages stoc:
     #16 0.994 debug2: first_kex_follows 0
     #16 0.994 debug2: reserved 0
     #16 0.994 debug1: kex: algorithm: curve25519-sha256@libssh.org
     #16 0.994 debug1: kex: host key algorithm: ecdsa-sha2-nistp256
     #16 0.994 debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
     #16 0.994 debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none
     #16 1.014 debug3: send packet: type 30
     #16 1.014 debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
     #16 1.182 debug3: receive packet: type 31
     #16 1.185 debug1: Server host key: ecdsa-sha2-nistp256 SHA256:HbW3g8zUjNSksFbqTiUWPWg2Bq1x8xdGUrliXFzSnUw
     #16 1.186 debug3: hostkeys_foreach: reading file "/root/.ssh/known_hosts"
     #16 1.187 debug3: hostkeys_foreach: reading file "/root/.ssh/known_hosts"
     #16 1.187 debug1: read_passphrase: can't open /dev/tty: No such device or address
     #16 1.188 Host key verification failed.
     ------
     executor failed running [/bin/sh -c ssh -Tvvv git@gitlab.com]: exit code: 255    
    

I have tried a lot, but up to now, I could not solve the error read_passphrase: can't open /dev/tty: No such device or address. The file exists, else I could not change its rights to 666, using chmod 666 /dev/tty. I guess that a terminal is required just for entering an empty password.

What to change to clone a repo from GitLab with a passwordless SSH key pair, using just one Dockerfile?

If there is no chance to do this in just one Dockerfile, an accepted workaround would be a docker-compose file; this is not the favoured answer, though.

EDITED: The needed path and file can be found when looking into the container.

(The start was: docker build -t . --build-arg ssh_prv_key="$(cat ./.ssh/id_rsa)", until the end of the working code only!)
docker run -d -it --name test_bash -d NEW_IMAGENAME:latest
docker exec -it test_bash bash
cd root/.ssh;ls

The last command shows the id_rsa and the known_hosts.

d3cbc35351fd / # cd root/.ssh;ls
id_rsa  known_hosts

And if I run d3cbc35351fd .ssh # ssh -Tvvv git@gitlab.com inside the container, I am asked for the password:

Enter passphrase for key '/root/.ssh/id_rsa':
debug2: bad passphrase given, try again...
Enter passphrase for key '/root/.ssh/id_rsa':
debug2: bad passphrase given, try again...
Enter passphrase for key '/root/.ssh/id_rsa':
debug2: no passphrase given, try next key

This is a try with "", '' and just pressing enter, they all do not work.

If I cannot use SSH in the Dockerfile and neither in the container of that Dockerfile' image, I wonder whether cloning a repo out of a Dockerfile or container is possible at all. I guess that suppressing the password entry will be the next big step to solve this, but even that might not solve it entirely, since I have already tried entering an empty password in the container, to no avail.

6
  • 1
    From your log :read_passphrase: .... I suppose the real cause of read_passphrase is that the key isn't be accepted. You should try to docker run into the container and try it there and verify that the private key is stored correct. And add more verbosity by ssh -vvv git@gitlab.com – jeb Mar 15 at 7:30
  • @jeb Thanks, I changed to -vvv parameter, see the edited answer. You are right, the /root is empty in the container, obviously, there is no /root/.ssh/id_rsa either, then. There is, though, a green-marked /tmp/ssh-TI6EWavBoyJC folder with the file agent.8 in it. (the steps: docker run -it --name test_bash -d MYIMAGE:latest, then docker exec -it test_bash /bin/bash, cd root, ls) – questionto42 Mar 15 at 11:55
  • Try it with mkdir -p /root/.ssh && chmod 700 /root/.ssh – jeb Mar 15 at 12:21
  • Is it necessary to git clone while building the image? Or is it possible to clone while running the container? – jeb Mar 15 at 12:29
  • @jeb I tried it with 700, to no avail. I also tried COPY id_rsa (with "id_rsa" in the same folder as the Dockerfile) instead of echo "$ssh_prv_key" . git clone should happen inside the Dockerfile, I just want to have an installation of everything in one go, without adding another step of cloning. If that is not possible, I will go over to a docker-compose approach where the cloning is done only after the main image was built. If that is not possible again, I would do the cloning manually, then I would just use my password and no key pair would be used. – questionto42 Mar 15 at 12:48
0

The ssh-agent doesn't work as expected in the build process, but you don't need it at all.

I build a minimal sample that works

FROM ubuntu:latest
ARG ssh_prv_key

RUN apt-get update \
&& apt-get install -y git

RUN mkdir -p /root/.ssh &&  chmod 700 /root/.ssh

RUN echo "$ssh_prv_key" > /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa

# Check if the key was successfully copied
# RUN cat -n /root/.ssh/id_rsa

# Dummy ssh to store the host into known_hosts
# The expected output is something like: 
# Hi <user>! You've successfully authenticated, but GitHub does not provide shell access.
RUN ssh -T -o StrictHostKeyChecking=no git@github.com || true

RUN git clone ssh://git@github.com/<myrepo>
7
  • This gives me: => ERROR [7/7] RUN git clone git@gitlab.com:USERNAME/test.git 1.2s ------ > [7/7] RUN git clone git@gitlab.com:USERNAME/test.git: #10 0.475 Cloning into 'key_test'... #10 1.109 Host key verification failed. #10 1.110 fatal: Could not read from remote repository. #10 1.110 #10 1.110 Please make sure you have the correct access rights #10 1.110 and the repository exists. – questionto42 Mar 15 at 15:14
  • @questionto42 git@gitlab.com:USERNAME The :USERNAME looks strange here, does it work in the host system? – jeb Mar 15 at 15:16
  • I use USERNAME as a placeholder for my real GitLab username here. On the host: ssh -i id_rsa git@gitlab.com leads to PTY allocation request failed on channel 0 Welcome to GitLab, @USERNAME! Connection to gitlab.com closed. And git clone git@gitlab.com:USERNAME/test.git clones the empty repo. – questionto42 Mar 15 at 15:18
  • This is just the "Copy URL" that you get in GitLab when you are in the repo and click on the clone button (and choose SSH). It should be the right URL to ssh the repo. Would it not be logical again that this is the same issue of the needed password entry for a private key that does not have a password? I am not using GitHub, but GitLab, perhaps that is also the issue? – questionto42 Mar 15 at 15:22
  • @questionto42 The error is at Host key verification failed, the host key should already stored in ~/.ssh/known_hosts, by the step 6/7 ssh -T -o StrictHostKeyChecking=no git@gitlab.com – jeb Mar 15 at 15:27
0

If you want to get rid of the private key in the image for security reasons, or if you need more information, see Using SSH keys inside docker container with a more thorough answer.


The main error is caused by the

echo "$ssh_prv_key" > /root/.ssh/id_rsa

which passes a wrongly formatted ssh_prv_key, as just one line, although the private key needs many lines. The idea is from Add private key to ssh-agent in docker file that hints at Gitlab CI/Docker: ssh-add keeps asking for passphrase.

--> Thus, do not use RUN echo ... for the private key, instead, use COPY ...!!!

Another small error is RUN ssh -o StrictHostKeyChecking=no git@gitlab.com || true, which does not work, but

both

RUN echo "Host *\n\t StrictHostKeyChecking no" >> /etc/ssh/ssh_config

and

RUN ssh-keyscan -t rsa -H gitlab.com >> /root/.ssh/known_hosts 

work and reach the same aim, choose just one of the two.

Another step is to drop ssh-agent and ssh-add. Both are only needed if you have a password, see Add private key to ssh-agent in docker file.

This is working now.

The Dockerfile looks as follows:

FROM ubuntu:latest
RUN apt-get update && apt-get install -y git
RUN mkdir -p /root/.ssh && chmod 700 /root/.ssh
COPY /.ssh/id_rsa /root/.ssh/id_rsa
RUN chmod 600 /root/.ssh/id_rsa
RUN ssh-keyscan -t rsa -H gitlab.com >> /root/.ssh/known_hosts
RUN git clone git@gitlab.com:GITLAB_USERNAME/test.git
RUN rm -r /root/.ssh

To create the image from the Dockerfile:

  • Go to the directory of the Dockerfile.

  • Paste your private key "id_rsa" (or whatever name you have, then change the code of course) in a new subfolder "/.ssh/" (or paste it in the Dockerfile directory and change the code to COPY id_rsa /root/.ssh/id_rsa).

  • Start (Do not forget the "." at the end, which is the build context):

    docker build -t test .
    

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.