364

I have copied this code from what seems to be various working dockerfiles around, here is mine:

FROM ubuntu

MAINTAINER Luke Crooks "luke@pumalo.org"

# Update aptitude with new repo
RUN apt-get update

# Install software 
RUN apt-get install -y git python-virtualenv

# Make ssh dir
RUN mkdir /root/.ssh/

# Copy over private key, and set permissions
ADD id_rsa /root/.ssh/id_rsa
RUN chmod 700 /root/.ssh/id_rsa
RUN chown -R root:root /root/.ssh

# Create known_hosts
RUN touch /root/.ssh/known_hosts

# Remove host checking
RUN echo "Host bitbucket.org\n\tStrictHostKeyChecking no\n" >> /root/.ssh/config

# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:Pumalo/docker-conf.git /home/docker-conf

This gives me the error

Step 10 : RUN git clone git@bitbucket.org:Pumalo/docker-conf.git /home/docker-conf
 ---> Running in 0d244d812a54
Cloning into '/home/docker-conf'...
Warning: Permanently added 'bitbucket.org,131.103.20.167' (RSA) to the list of known hosts.
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
2014/04/30 16:07:28 The command [/bin/sh -c git clone git@bitbucket.org:Pumalo/docker-conf.git /home/docker-conf] returned a non-zero code: 128

This is my first time using dockerfiles, but from what I have read (and taken from working configs) I cannot see why this doesn't work.

My id_rsa is in the same folder as my dockerfile and is a copy of my local key which can clone this repo no problem.

Edit:

In my dockerfile I can add:

RUN cat /root/.ssh/id_rsa

And it prints out the correct key, so I know its being copied correctly.

I have also tried to do as noah advised and ran:

RUN echo "Host bitbucket.org\n\tIdentityFile /root/.ssh/id_rsa\n\tStrictHostKeyChecking no" >> /etc/ssh/ssh_config

This sadly also doesn't work.

ccpizza
  • 28,968
  • 18
  • 162
  • 169
crooksey
  • 8,521
  • 6
  • 30
  • 52
  • 1
    Watch out! Docker images have a **versioned file system and they remember command history**. A lot of the answers will bake git credentials into your docker image. At best you are letting anyone who has the image get access to the repo until you delete the key from Github/Gitlab/etc.. At worst you are giving anyone who has the image **total access to your Github/etc. account**! There is almost no secure way to clone a git repo into a Dockerfile, [see this answer](https://stackoverflow.com/a/55761914) for a real alternative (copying files in). – jrh Feb 17 '22 at 15:36
  • Hypothetically even if you stored your git credentials in a Docker secret (none of these answers do that), you will still have to expose that secret in a place where the git cli can access it, and if you write it to file, you have now stored it in the image forever for anyone to read (**even if you delete the credentials later**). **I am not aware of any way to securely handle git CLI credentials that git clone can use that will not also bake that credential into your image.** – jrh Feb 17 '22 at 15:38
  • 2
    I flagged this question, because it is so old that **many answers are dangerously wrong now**. Read the docs on **how to do this in modern docker**: https://docs.docker.com/develop/develop-images/build_enhancements/#using-ssh-to-access-private-data-in-builds – P.R. Aug 02 '22 at 11:33

11 Answers11

375

My key was password protected which was causing the problem, a working file is now listed below (for help of future googlers)

FROM ubuntu

MAINTAINER Luke Crooks "luke@pumalo.org"

# Update aptitude with new repo
RUN apt-get update

# Install software 
RUN apt-get install -y git
# Make ssh dir
RUN mkdir /root/.ssh/

# Copy over private key, and set permissions
# Warning! Anyone who gets their hands on this image will be able
# to retrieve this private key file from the corresponding image layer
ADD id_rsa /root/.ssh/id_rsa

# Create known_hosts
RUN touch /root/.ssh/known_hosts
# Add bitbuckets key
RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts

# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:User/repo.git
Asu
  • 1,723
  • 2
  • 21
  • 32
crooksey
  • 8,521
  • 6
  • 30
  • 52
  • 14
    Just in case, here it is a [link](http://learninglamp.wordpress.com/2012/06/26/remove-passphrase-from-ssh-key/) describing how to remove the password protection of the key – Thomas Jul 09 '14 at 11:12
  • Does `ssh-keyscan` take the place of running an authentication agent and `ssh-add id_rsa`? Thanks – Peter Becich Jul 29 '14 at 02:20
  • Keyscan takes the public key of a server and in this instance adds it to the known hosts. – crooksey Jul 30 '14 at 12:49
  • Can it be a good idea to remove the key from the image with another RUN after the clone has succeeded? – Evgeny Goldin Oct 30 '14 at 10:36
  • @EvgenyGoldin - Yes. That should be the next step after cloning the source. – Blake Caldwell Nov 14 '14 at 04:24
  • 1
    @dome just create another key that isn't, there is no way as of yet to use password protected keys. – crooksey Dec 23 '14 at 12:35
  • 109
    Just an FYI, after you run RUN ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts, the Image will save that as a layer. If anyone gets a hold of your image, they can retrieve the key... even if you delete that file in a later layer, b/c they can go back to Step 7 when you added it. – Bernie Perez Jan 07 '15 at 22:37
  • 29
    Thanks for the helpful answer. But for us the build failed randomly and after investigation we noticed that `ssh-keyscan` has a default timeout of 5 seconds which bitbucket often exceeded. `ssh-keyscan` won't even report an error. So better run `RUN ssh-keyscan -T 60 bitbucket.org >> /root/.ssh/known_hosts` to be safe. – fluidsonic Feb 26 '15 at 17:05
  • @crooksey what did you mean "my key is password protected"? Can you elaborate please. I followed this but I still get access denied. – anlogg Jul 26 '15 at 03:57
  • Never mind password protected key is the one without passphrase. – anlogg Jul 26 '15 at 13:46
  • 3
    All this should be run in one layer and /root/.ssh should removed at the end of that layer. Minor improvements: no need to touch known_hosts and just use > instead of >>, you do not need to append. – smets.kevin Oct 26 '16 at 12:49
  • the `ADD id_rsa /root/.ssh/id_rsa` command - where does it get the `id_rsa` file? Isn't it located in `~/.ssh/`? – ilya1725 Dec 01 '16 at 02:14
  • @ilya1725 `ADD ... `, first parameter is relative to current `Dockerfile`, second parameter will be stored on the built docker image. you may replace `id_rsa` with the key you want if you have many, just get your desired key beside your `Dockerfile` by placing it there manually or doing a symlink from your own `~/.ssh`. – GabLeRoux Dec 08 '16 at 21:35
  • 1
    @GabeRoux What I found is that `docker build` process would complain is `ADD` or any other command attempts to access anything in parent directory or above. Down to children is fine. I've ended up wrapping `docker build` into a shell script to prepare, build, and run. – ilya1725 Dec 08 '16 at 22:16
  • 9
    Could someone explain why running `ssh-keyscan` is an issue? My understanding is that it will simply pull the public key of Github/Bitbucket. What alternative can be used so it doesn't end up in a layer? – Pedro May 14 '17 at 19:45
  • 15
    @Pedro The keyscan step in particular is not an issue at all, you're clearly right. If anything, these host public keys should be spread as much as possible. See sshd(8) for details on the `known_hosts` file. People just upvote random things when they sound alarming enough. – tne Jul 06 '17 at 16:11
  • You dont need to copy over the pub key too? – Misterparker Sep 18 '17 at 23:00
  • @crooksey I found following error while tried your solution: Service 'test_service' failed to build: ADD failed: stat /var/lib/docker/tmp/docker-builder567300658/id_rsa Can you help me? – Ganesh Kunwar Dec 14 '17 at 04:30
  • 8
    This will make the private key accessible to anyone who has access to the docker image—even if you add `RUN rm /root/.ssh/id_rsa`. This seems like a pretty big problem that some people might not think of and should probably be mentioned in your answer. – 3ocene Feb 28 '18 at 21:49
  • Hey @3ocene, could you follow up why RUN rm id_rsa will keep the key accessible? Thx – Lukas Lukac Jun 08 '18 at 14:30
  • 5
    @EnchanterIO Docker images are built in layers. Each layer is accessible individually. `RUN rm /root/.ssh/id_rsa` just creates a new layer where the key is removed, but the previous layer where it still exists doesn't get deleted. When you run `docker build` it prints an id for each layer and you can then `docker run` that id and read the key. – 3ocene Jun 08 '18 at 20:12
  • ah that's really interesting @3ocene! Never though of it like that. If you have some good resource on the topic let me know, gonna check it more in depth! For now I just run the git clone on the host machine with access and then I copy the content to the container. Like this I have a nice separation I believe. – Lukas Lukac Jun 09 '18 at 14:27
  • @LukasLukac It's only two years later, but here's a decent article on [removing your private key](https://vsupalov.com/build-docker-image-clone-private-repo-ssh-key/) from the image layers. – hlongmore Jun 09 '20 at 00:04
  • 1
    @Misterparker (nearly 3 years later; I add this comment for anyone else coming along after in case you already know) the public key should have been uploaded to bitbucket or whatever private repo you are using, and does not need to be in the image. As discussed in this article on [How to Use SSH Public Key Authentication](https://serverpilot.io/docs/how-to-use-ssh-public-key-authentication/), "if you have the private key, you can prove you have it without showing what it is. It's like proving you know a password without having to show someone the password." – hlongmore Jun 09 '20 at 00:25
  • @crooksey: Getting git@bitbucket.org: Permission denied (publickey). after using above solution please suggest. – Abhishek Verma Jul 21 '21 at 18:38
  • An Intermediate Docker Layer can be used to avoid having passwords/keys left in the Image history. More info at: https://vsupalov.com/build-docker-image-clone-private-repo-ssh-key/ – Ruben Alves Feb 08 '22 at 12:57
  • 1
    @Pedro ssh-keyscan isn't the problem, the problem is copying your private ssh key into the image itself. – Braiam Feb 17 '22 at 09:21
119

You should create new SSH key set for that Docker image, as you probably don't want to embed there your own private key. To make it work, you'll have to add that key to deployment keys in your git repository. Here's complete recipe:

  1. Generate ssh keys with ssh-keygen -q -t rsa -N '' -f repo-key which will give you repo-key and repo-key.pub files.

  2. Add repo-key.pub to your repository deployment keys.
    On GitHub, go to [your repository] -> Settings -> Deploy keys

  3. Add something like this to your Dockerfile:

    ADD repo-key /
    RUN \
      chmod 600 /repo-key && \  
      echo "IdentityFile /repo-key" >> /etc/ssh/ssh_config && \  
      echo -e "StrictHostKeyChecking no" >> /etc/ssh/ssh_config && \  
      // your git clone commands here...
    

Note that above switches off StrictHostKeyChecking, so you don't need .ssh/known_hosts. Although I probably like more the solution with ssh-keyscan in one of the answers above.

Marcin R
  • 1,521
  • 1
  • 9
  • 6
102

There's no need to fiddle around with ssh configurations. Use a configuration file (not a Dockerfile) that contains environment variables, and have a shell script update your docker file at runtime. You keep tokens out of your Dockerfiles and you can clone over https (no need to generate or pass around ssh keys).

Go to Settings > Personal Access Tokens

  • Generate a personal access token with repo scope enabled.
  • Clone like this: git clone https://MY_TOKEN@github.com/user-or-org/repo

Some commenters have noted that if you use a shared Dockerfile, this could expose your access key to other people on your project. While this may or may not be a concern for your specific use case, here are some ways you can deal with that:

  • Use a shell script to accept arguments which could contain your key as a variable. Replace a variable in your Dockerfile with sed or similar, i.e. calling the script with sh rundocker.sh MYTOKEN=foo which would replace on https://{{MY_TOKEN}}@github.com/user-or-org/repo. Note that you could also use a configuration file (in .yml or whatever format you want) to do the same thing but with environment variables.
  • Create a github user (and generate an access token for) for that project only
Nick
  • 2,803
  • 1
  • 39
  • 59
Calvin Froedge
  • 16,135
  • 16
  • 55
  • 61
  • What context are you talking about for `Settings > Applications`? – turboladen Apr 29 '15 at 05:17
  • @turboladen Your github account – Calvin Froedge Apr 29 '15 at 19:14
  • 1
    The downside of this approach is that you are storing credentials for a private repo within the Dockerfile as opposed to @crooksey's approach which would allow you to reference a key that is stored separately from a Dockerfile. Without context around how OP is storing the Dockerfile we cannot determine if this would cause an issue but from personal experience I like to store my Dockerfiles within a VCS and wouldn't want to commit anything that contained credentials. Once Docker implement ability to pass env variables to build command then I agree this would be cleanest solution. – Jabbslad May 12 '15 at 22:23
  • @Jabbslad While I appreciate what you're saying, I handle that by setting an environment variable locally, so the token never goes in the Dockerfile. – Calvin Froedge May 13 '15 at 01:31
  • 2
    @CalvinFroedge by locally I assume you mean your host? I am not aware of a way to expose environment variables on the host to a container at build time which is why we have open issues like this https://github.com/docker/docker/issues/6822. Please can you clarify? – Jabbslad May 13 '15 at 06:21
  • @Jabbslad While you can't put env variables directly into the docker file, you can use a configuration file that can contain environment variables, which a shell script uses to update your docker file at runtime. Check out this blog post: http://blog.james-carr.org/2013/09/04/parameterized-docker-containers/ This is only if you're concerned with putting the token in the Dockerfile (some people probably will not be). – Calvin Froedge May 13 '15 at 14:41
  • @CalvinFroedge ok I see what you mean, that's similar to what I ended up doing for anything that needs parameterising. The downside is that it essentially moves commands that should be run during `docker build` and stored within the image into the `docker run` step but I agree it's the best we have got until parameterised builds is implemented. Thanks for the clarification. – Jabbslad May 13 '15 at 14:52
  • 1
    Even cleaner (separation of concerns): a linked volume for the cloned repo + a dedicated container only for the cloning task + a linked volume only with the SSH keys (or token, as you suggest). See http://stackoverflow.com/a/30992047, maybe combined with http://stackoverflow.com/a/29981990. – Peterino Dec 14 '15 at 01:30
  • 10
    Also the question is for a BITBUCKET repo, not a github repo. – Michael Draper Feb 15 '16 at 05:40
  • This is a cleaner solution that copying the ssh keys. In addition, you may create a GitHub secret and put your token in the secret and hence there is no need to create separate shell script just to hide personal token. – Tushar Jul 23 '20 at 03:21
  • 1
    This is not a secure solution, no matter how you store the credential (whether it's in a secret, env var, etc...) `git clone https://MY_TOKEN@github.com/user-or-org/repo` will show up in the image history and will leak your PAT. – jrh Nov 06 '21 at 15:03
  • For anyone having difficulties on finding the link do generate personal private keys, maybe it´s because it changed recently. So go under: log into github -> settings (your settings, not your repository´s) -> developer settings -> personal private keys. – Jorge Mauricio Mar 07 '22 at 01:25
  • Thank you! Worked great for me. Just a comment, you need to add "$MY_TOKEN" so the git clone works! Or in docker commands: ```ARG MY_TOKEN=your token RUN https://$MY_TOKEN@github.com/user-or-org/repo``` – ABarrier Mar 27 '22 at 08:23
88

You often do not want to perform a git clone of a private repo from within the docker build. Doing the clone there involves placing the private ssh credentials inside the image where they can be later extracted by anyone with access to your image.

Instead, the common practice is to clone the git repo from outside of docker in your CI tool of choice, and simply COPY the files into the image. This has a second benefit: docker caching. Docker caching looks at the command being run, environment variables it includes, input files, etc, and if they are identical to a previous build from the same parent step, it reuses that previous cache. With a git clone command, the command itself is identical, so docker will reuse the cache even if the external git repo is changed. However, a COPY command will look at the files in the build context and can see if they are identical or have been updated, and use the cache only when it's appropriate.

BuildKit has a feature just for ssh which allows you to still have your password protected ssh keys, the result looks like:

# syntax=docker/dockerfile:experimental
FROM ubuntu as clone
LABEL maintainer="Luke Crooks <luke@pumalo.org>"

# Update aptitude with new repo
RUN apt-get update \
 && apt-get install -y git

# Make ssh dir
# Create known_hosts
# Add bitbuckets key
RUN mkdir /root/.ssh/ \
 && touch /root/.ssh/known_hosts \
 && ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts

# Clone the conf files into the docker container
RUN --mount=type=ssh \
    git clone git@bitbucket.org:User/repo.git

And you can build that with:

$ eval $(ssh-agent)
$ ssh-add ~/.ssh/id_rsa
(Input your passphrase here)
$ DOCKER_BUILDKIT=1 docker build -t your_image_name \
  --ssh default=$SSH_AUTH_SOCK .

Again, this is injected into the build without ever being written to an image layer, removing the risk that the credential could accidentally leak out.


BuildKit also has a features that allow you to pass an ssh key in as a mount that never gets written to the image:

# syntax=docker/dockerfile:experimental
FROM ubuntu as clone
LABEL maintainer="Luke Crooks <luke@pumalo.org>"

# Update aptitude with new repo
RUN apt-get update \
 && apt-get install -y git

# Make ssh dir
# Create known_hosts
# Add bitbuckets key
RUN mkdir /root/.ssh/ \
 && touch /root/.ssh/known_hosts \
 && ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts

# Clone the conf files into the docker container
RUN --mount=type=secret,id=ssh_id,target=/root/.ssh/id_rsa \
    git clone git@bitbucket.org:User/repo.git

And you can build that with:

$ DOCKER_BUILDKIT=1 docker build -t your_image_name \
  --secret id=ssh_id,src=$(pwd)/id_rsa .

Note that this still requires your ssh key to not be password protected, but you can at least run the build in a single stage, removing a COPY command, and avoiding the ssh credential from ever being part of an image.


If you are going to add credentials into your build, consider doing so with a multi-stage build, and only placing those credentials in an early stage that is never tagged and pushed outside of your build host. The result looks like:

FROM ubuntu as clone

# Update aptitude with new repo
RUN apt-get update \
 && apt-get install -y git
# Make ssh dir
# Create known_hosts
# Add bitbuckets key
RUN mkdir /root/.ssh/ \
 && touch /root/.ssh/known_hosts \
 && ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts

# Copy over private key, and set permissions
# Warning! Anyone who gets their hands on this image will be able
# to retrieve this private key file from the corresponding image layer
COPY id_rsa /root/.ssh/id_rsa

# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:User/repo.git

FROM ubuntu as release
LABEL maintainer="Luke Crooks <luke@pumalo.org>"

COPY --from=clone /repo /repo
...

To force docker to run the git clone even when the lines before have been cached, you can inject a build ARG that changes with each build to break the cache. That looks like:

# inject a datestamp arg which is treated as an environment variable and
# will break the cache for the next RUN command
ARG DATE_STAMP
# Clone the conf files into the docker container
RUN git clone git@bitbucket.org:User/repo.git

Then you inject that changing arg in the docker build command:

date_stamp=$(date +%Y%m%d-%H%M%S)
docker build --build-arg DATE_STAMP=$date_stamp .
Braiam
  • 1
  • 11
  • 47
  • 78
BMitch
  • 231,797
  • 42
  • 475
  • 450
  • 2
    You suggest to use git from outside of Docker, however you explain how to deal with ssh keys anyway. When do you consider this necessary/appropriate? – JCarlosR Sep 28 '19 at 02:25
  • 4
    @JCarlosR when you don't have an external system in which to run the build (e.g. a CI/CD system capable of running the clone in advance). There can be exceptions, but a clone inside a Dockerfile is a code smell. – BMitch Jan 21 '20 at 10:32
  • @BMitch Please explain why it is a code smell, as long as security issues are avoided, it is fine. – Luk Aron Jan 30 '21 at 09:45
  • 2
    @LukAron it's an indication that a CI system is being replaced by a complex Dockerfile, and causes lots of issues like leaking secrets and breaking docker's caching logic. It's a bit like answering a question on how to define a global variable, yes there's an answer, but a majority of those looking for the answer should really consider if they wanted dependency injection. Both can be more work to implement, but they are a better solution to a majority of the use cases. – BMitch Jan 30 '21 at 13:39
  • 4
    @BMitch `git clone` of a private repo in a Dockerfile can be more than just a code smell, it can be a straight up security risk. I think it's worth mentioning that the answers that do `git clone https://{{MY_TOKEN}}@github.com` are all wrong because even if you somehow hide that clone command in a secret or something, the PAT would still be present in the remote property of the cloned repo. So thanks for this answer, it has very good information. I think `COPY`ing a previously downloaded tarball (not downloaded in the Dockerfile) is the solution for me. – jrh Nov 05 '21 at 13:06
37

Another option is to use a multi-stage docker build to ensure that your SSH keys are not included in the final image.

As described in my post you can prepare your intermediate image with the required dependencies to git clone and then COPY the required files into your final image.

Additionally if we LABEL our intermediate layers, we can even delete them from the machine when finished.

# Choose and name our temporary image.
FROM alpine as intermediate
# Add metadata identifying these images as our build containers (this will be useful later!)
LABEL stage=intermediate

# Take an SSH key as a build argument.
ARG SSH_KEY

# Install dependencies required to git clone.
RUN apk update && \
    apk add --update git && \
    apk add --update openssh

# 1. Create the SSH directory.
# 2. Populate the private key file.
# 3. Set the required permissions.
# 4. Add github to our list of known hosts for ssh.
RUN mkdir -p /root/.ssh/ && \
    echo "$SSH_KEY" > /root/.ssh/id_rsa && \
    chmod -R 600 /root/.ssh/ && \
    ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts

# Clone a repository (my website in this case)
RUN git clone git@github.com:janakerman/janakerman.git

# Choose the base image for our final image
FROM alpine

# Copy across the files from our `intermediate` container
RUN mkdir files
COPY --from=intermediate /janakerman/README.md /files/README.md

We can then build:

MY_KEY=$(cat ~/.ssh/id_rsa)
docker build --build-arg SSH_KEY="$MY_KEY" --tag clone-example .

Prove our SSH keys are gone:

docker run -ti --rm clone-example cat /root/.ssh/id_rsa

Clean intermediate images from the build machine:

docker rmi -f $(docker images -q --filter label=stage=intermediate)
Yo-han
  • 351
  • 2
  • 12
jaker
  • 7,730
  • 1
  • 20
  • 22
  • ARG SSH_PRIVATE_KEY needs to be replaced with ARG SSH_KEY – Joseph Persico Feb 18 '19 at 20:01
  • cant we just delete the keys once git clone is done? – Broncha Jun 17 '19 at 08:01
  • 1
    You could do, but you'd need to do it as part of a single `RUN` so you don't leave the key in a previous image layer. As of docker `1.13` you can use the `--squash` **experimental** argument which would remove the SSH key in your final image layers too. – jaker Jun 18 '19 at 11:52
  • You can start `FROM alpine/git AS intermediate` and then skip the `apk add` commands – isapir Dec 29 '20 at 04:26
  • is there any way to let the container generate an ssh key and add that ssh key to GitHub or GitLab by some API on the fly? – Luk Aron Jan 30 '21 at 09:32
  • This isn't a secure solution, your SSH key will show up in the image log. A variant of this could work, e.g., [BMitch's answer](https://stackoverflow.com/a/55761914). – jrh Nov 06 '21 at 15:04
21

For bitbucket repository, generate App Password (Bitbucket settings -> Access Management -> App Password, see the image) with read access to the repo and project.

bitbucket user menu

Then the command that you should use is:

git clone https://username:generated_password@bitbucket.org/reponame/projectname.git
Nomce
  • 738
  • 1
  • 6
  • 18
  • 1
    Simplest :) I must admit I'd prefer an SSH based approach, but I could not get any of the above working... files aren't found, etc. – Janos Sep 13 '17 at 09:24
  • I don't see "Access Management" ... I guess it is outdated? – Martin Thoma May 03 '18 at 12:31
  • It's possible, I can't confirm it because I don't use the bitbucket repository free service, sorry. – Nomce May 03 '18 at 14:46
  • 1
    Worked! Plain and simple... Great! – Josemy May 09 '18 at 10:33
  • @Joss Great! Can you take a screenshot from the menu so that the the answer can be completed with that? To Help Martin and others. Thanks! – Nomce May 09 '18 at 12:24
  • 2
    Of course... You just have to click on your profile picture on the left bar, then on *Bitbucket settings* and you will see something like this: https://imgur.com/EI33zj3 – Josemy May 09 '18 at 15:57
  • 1
    This worked for me. However, I have submodules and `--recursive` did not work. I had to put in `git clone` for each submodule, which is fine but would have been great if it would have worked recursively. – Zailyn Tamayo Jan 23 '19 at 03:15
  • This isn't a secure solution, your username and password will show up in the image history in the `git clone` command. You can't securely use git clone like that in a Dockerfile, you have to COPY in the source, or share credentials some other way. – jrh Nov 06 '21 at 15:05
8

Nowsaday you can use the Buildkit option --ssh default when you build your container ; Prior to build, you need to add your SSH deploy key to your ssh-agent.

Here is the full process from the beginning :

  1. Create a key pair on your deployment server. Just run ssh-keygen -t ecdsa Store your key pair into ~/.ssh

  2. Add your public key generated (.pub extension) at your git provider website (gitlab, github..)

  3. Add your key to your ssh-agent (a program that basically manages your keys easier than handling every file)

eval $(ssh-agent)
ssh-add /path/to/your/private/key
  1. Add this to your Dockerfile :
# this 3 first lines add your provider public keys to known_host 
# so git doesn't get an error from SSH.

RUN mkdir -m 700 /root/.ssh && \
  touch -m 600 /root/.ssh/known_hosts && \
  ssh-keyscan your-git-provider.com > /root/.ssh/known_hosts 


# now you can clone with --mount=type=ssh option, 
# forwarding to Docker your host ssh agent

RUN mkdir -p /wherever/you/want/to/clone && cd /wherever/you/want/to/clone && \
  --mount=type=ssh git clone git@gitlab.com:your-project.git
  1. And now you can finally build your Dockerfile (with buildkit enabled)
DOCKER_BUILDKIT=1 docker build . --ssh default

As you cannot currently pass console parameters to build in docker-compose, this solution is not available yet for docker-compose, but it should be soon (it's been done on github and proposed as a merge request)

Jerem Lachkar
  • 1,008
  • 11
  • 24
4

p.s. this solution is quick & easy; but at a cost of reduced security (see comments by @jrh).


Create an access token: https://github.com/settings/tokens

pass it in as an argument to docker (p.s. if you are using CapRover, set it under App Configs)

In your Dockerfile:

ARG GITHUB_TOKEN=${GITHUB_TOKEN}
RUN git config --global url."https://${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"
RUN pip install -r requirements.txt

p.s. this assumes that private repos are in the following format in requirements.txt:

git+https://github.com/<YOUR-USERNAME>/<YOUR-REPO>.git
Neil
  • 7,482
  • 6
  • 50
  • 56
  • 3
    This isn't a secure solution, your personal access token will show up in the image log (in the git config command). There is no secure way to clone like that from a Dockerfile, you need to use something like COPY or share credentials some other way that won't show up in the history. – jrh Nov 06 '21 at 15:06
0

For other people searching I had the same issue adding --ssh default flag made it work

mosaad
  • 2,276
  • 5
  • 27
  • 49
0

In addition to @Calvin Froedge's approach to use Personal Access Token (PAT),

You may need to add oauth or oauth2 as username before your PAT to authenticate like this:

https://oauth:<token>@git-url.com/user/repo.git
Mechanic
  • 5,015
  • 4
  • 15
  • 38
0

recently had a similar issue with a private repository in a Rust project. I suggest avoiding ssh permissions/config altogether.

Instead:

  1. clone the repository within the build environment e.g. CI, where the permissions already exist (or can be easily configured)
  2. copy the files into the Dockerfile (this can also be cached natively within the CI)

Example

part 1) within CI

CARGO_HOME=tmp-home cargo fetch

part 2) within Dockerfile

COPY tmp-home $CARGO_HOME

the process is the same regardless of language/package system

stacksonstacks
  • 8,613
  • 6
  • 28
  • 44