# Grabbing private code in Dockerfiles

**URL:** <https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807>\
**Category:** Product support\
**Tags:** support, raspberrypi3\
**Created:** [April 18, 2017, 7:56pm UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807 "2017-04-18T19:56:32Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![nckswt](https://sea2.discourse-cdn.com/balena/user_avatar/forums.balena.io/nckswt/32/368_2.png) [@nckswt](https://forums.balena.io/u/nckswt)\
**Post date:** [April 18, 2017, 7:56pm UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807/1 "2017-04-18T19:56:32Z")

</div>

I’m fairly new to Resin, so apologies if this is a solved problem I just haven’t found the answer to.

I have a directory structure like the following:

```
project_root
├── private_repo_1
├── private_repo_2
├── private_repo_n
└── private_installation_repo
    ├── .dockerignore
    ├── Dockerfile
    └── entrypoint.sh

```

(The project is fairly large, so we want to keep the docker-related code tucked away in a separate repository.)

My Dockerfile needs access to the source code in the private repositories, but this seems to be a tricky problem. For one, I can’t simply `RUN git clone <repo>` because of [security issues with ssh keys](https://github.com/moby/moby/issues/6396). Similarly, I can’t copy code from my development machine (e.g. `COPY ../../project_root project_root`) because of [security issues with relative directories](https://github.com/moby/moby/issues/2745).

So, I’m trying to figure out a solution more elegant than some of the hacky solutions I’ve found. Does anyone know of good examples to follow?

---

<div class="post-metadata">

**Author:** ![pimterry](https://sea2.discourse-cdn.com/balena/user_avatar/forums.balena.io/pimterry/32/140_2.png) [@pimterry](https://forums.balena.io/u/pimterry)\
**Post date:** [April 18, 2017, 9:46pm UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807/2 "2017-04-18T21:46:39Z")

</div>

I’m not familiar with Moby, so I don’t fully understand the bugs you’ve linked there. To build this image though, you’re going to need to give the [Resin.io](http://Resin.io) build server access to checkout code from those repos during the build process somehow, which isn’t trivial. I’m afraid I don’t have any easy examples: for most cases it’s much easier to push a complete single repo to Resin directly.

We don’t yet have a fantastic solution to this. Right now the best option is to commit a SSH key that has access to clone the private repos (private\_repo\_1, private\_repo\_2, …) inside the Dockerfile repo (private\_installation\_repo), so that the Dockerfile build can access them to clone the rest of the code.

Of course this alone isn’t fantastic for security, and you should be very careful if you need to do this. You can reduce the risks significantly though by using [deploy keys](https://developer.github.com/guides/managing-deploy-keys/#deploy-keys) (assuming your repos are on Github). These allow you to generate an SSH keys with minimal privileges, that can read a single repo and no more, limiting the risk if they’re ever exposed.

If you want to control access to this further, you can look at tools like [Vault](https://www.vaultproject.io), which allow you run your own hosted service that controls access to these keys, and commit a single key for that into your repo, which you can revoke, manage and audit independently of the SSH keys themselves. That’s quite a bit more involved though, so it depends on your needs and your security concerns here.

---

<div class="post-metadata">

**Author:** ![nckswt](https://sea2.discourse-cdn.com/balena/user_avatar/forums.balena.io/nckswt/32/368_2.png) [@nckswt](https://forums.balena.io/u/nckswt)\
**Post date:** [April 19, 2017, 4:32pm UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807/3 "2017-04-19T16:32:39Z")

</div>

Thanks for the help, Tim!

I think the deploy keys approach will work just fine for now. I’ll take a look into Vault as well - that might very well be our long-term solution.

---

<div class="post-metadata">

**Author:** ![nckswt](https://sea2.discourse-cdn.com/balena/user_avatar/forums.balena.io/nckswt/32/368_2.png) [@nckswt](https://forums.balena.io/u/nckswt)\
**Post date:** [April 20, 2017, 2:51pm UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807/4 "2017-04-20T14:51:26Z")

</div>

In playing around a little bit, I’m realizing it’ll be easier to have deployment pipelines for both development and production. I think the Vault solution you provided will work for production, but I’ve run into a snag with the development pipeline.

For my local development `Dockerfile`, it makes more sense for me to `ADD project_root` from local code than to `RUN git clone` for each private repo, but I need to put `project_root` in the Dockerfile’s context somehow (a hacky solution would be to `mv` my Dockerfile to the project root, then `resin local push`, then `mv` it back 😵).

Ideally, I’d want to call `resin local push` from the directory containing `project_root`, _while specifying the path to `Dockerfile`_ (as in [this example](http://stackoverflow.com/a/34392052/362703)). This would `rsync` my `project_root` over to my device, then call something like `docker build -f private_installation_repo/Dockerfile .` on the device itself.

Is anything like that currently possible or in the works?

---

<div class="post-metadata">

**Author:** ![curcuz](https://sea2.discourse-cdn.com/balena/user_avatar/forums.balena.io/curcuz/32/137_2.png) [@curcuz](https://forums.balena.io/u/curcuz)\
**Post date:** [April 20, 2017, 8:30pm UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807/5 "2017-04-20T20:30:45Z")

</div>

@nckswt I don’t see any easy way of achieving that with resin as for now, but this is interesting feedback, thanks! looping in @kostas and @hedley maybe they have better ideas than me 🙂

---

<div class="post-metadata">

**Author:** ![pimterry](https://sea2.discourse-cdn.com/balena/user_avatar/forums.balena.io/pimterry/32/140_2.png) [@pimterry](https://forums.balena.io/u/pimterry)\
**Post date:** [April 21, 2017, 9:56am UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807/6 "2017-04-21T09:56:01Z")

</div>

You might be able to do this by symlinking the individual private repos (private\_repo\_n) all into `private_installation_repo`. You’d essentially be creating a new root that’s exactly the same but which does have the Dockerfile at the top level, without having to actually move anything around . I assume `resin local push` handles symlinks correctly, but I must admit I’ve never actually tested this. Definitely sounds like a bug if it doesn’t though 😄.

That’s a bit of hassle to manage, but you could easily set up a dev environment script to set it up, and potentially put it in a git hook to make that even easier.

---

<div class="post-metadata">

**Author:** ![nckswt](https://sea2.discourse-cdn.com/balena/user_avatar/forums.balena.io/nckswt/32/368_2.png) [@nckswt](https://forums.balena.io/u/nckswt)\
**Post date:** [April 21, 2017, 2:23pm UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807/7 "2017-04-21T14:23:58Z")

</div>

That’s not a bad idea - I’ll try a few things out and report back! Thanks 😄

---

<div class="post-metadata">

**Author:** ![nckswt](https://sea2.discourse-cdn.com/balena/user_avatar/forums.balena.io/nckswt/32/368_2.png) [@nckswt](https://forums.balena.io/u/nckswt)\
**Post date:** [April 26, 2017, 8:47pm UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807/8 "2017-04-26T20:47:45Z")

</div>

Just to follow-up: we’ve decided to unify our private repos into one repo to simplify our operations (cloning in the Dockerfile, managing PRs, setting up Jenkins, etc.).

Though, if we ever do have a repo outside of this unified repo, we’ll use a [GitHub machine user](https://developer.github.com/guides/managing-deploy-keys/#machine-users) with [personal access tokens](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) for authentication. Some of our (non-Resin-related) install code didn’t play nicely with using `ssh-config` to manage deploy keys 😒

Thanks for the help, Tim and Carlo!

---

<div class="post-metadata">

**Author:** ![curcuz](https://sea2.discourse-cdn.com/balena/user_avatar/forums.balena.io/curcuz/32/137_2.png) [@curcuz](https://forums.balena.io/u/curcuz)\
**Post date:** [April 27, 2017, 7:57pm UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807/9 "2017-04-27T19:57:52Z")

</div>

@nckswt, glad to hear you have a solution (plus a jolly in the sleeve for future situations 🙂 )

---

<div class="post-metadata">

**Author:** ![fritz](https://sea2.discourse-cdn.com/balena/user_avatar/forums.balena.io/fritz/32/6305_2.png) [@fritz](https://forums.balena.io/u/fritz)\
**Post date:** [August 22, 2018, 9:57am UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807/10 "2018-08-22T09:57:07Z")

</div>

Hi,  
@pimterry: I do have a similar issue. We need to fetch code from our private bitbucket server (self-hosted).  
I played around and added a private id\_rsa key to the Dockerfile and added the public key to the repository.  
But I don’t seem to get this to work.  
I have the following Dockerfile:

RUN mkdir -p /root/.ssh/  
COPY id\_rsa\_resin /root/.ssh/id\_rsa  
COPY config /root/.ssh/config  
RUN chmod 400 /root/.ssh/id\_rsa  
ENV GIT\_SSH\_COMMAND=“ssh -i ~/.ssh/id\_rsa -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no”  
RUN echo “$GIT\_SSH\_COMMAND”

RUN touch /root/.ssh/known\_hosts  
RUN ssh-keyscan -t rsa our.bitbucker.server.url \>\> /root/.ssh/known\_hosts

My ssh config file looks like this:

Host our.bitbucker.server.url  
Hostname our.bitbucker.server.url  
IdentityFile /root/.ssh/id\_rsa  
IdentitiesOnly yes

But when it comes to the npm install steps later on, I get the following error message:

[main] —\> Running in 85434b806424  
[main] npm ERR! Error while executing:  
[main]  
[main] npm ERR! /usr/bin/git ls-remote -h -t ssh://our.bitbucker.server.url:7999/test/resin-access-test-repo.git  
[main] npm ERR!  
[main] npm ERR!  
[main] Host key verification failed.  
[main] npm ERR! fatal: Could not read from remote repository.  
[main] npm  
[main] ERR!  
[main]  
[main] npm  
[main] ERR!  
[main] Please make sure you have the correct access rights  
[main] npm ERR!  
[main] and the repository exists.  
[main]  
[main] npm ERR!  
[main]  
[main] npm  
[main]  
[main] ERR!  
[main] exited with error code: 128  
[main]  
[main]  
[main] npm  
[main] ERR!  
[main] A complete log of this run can be found in:  
[main] npm ERR!  
[main] /root/.npm/\_logs/2018-08-22T09\_41\_25\_955Z-debug.log

I also tried to add the key using:  
RUN ssh-agent /root/.ssh/

but this seems to be not allowed:

[main] Step 11/20 : RUN ssh-agent /root/.ssh/  
[main] —\> Running in 858af7450af0  
[main] /root/.ssh/: Permission denied  
[main]  
[main] Removing intermediate container 858af7450af0  
[main] The command ‘/bin/sh -c ssh-agent /root/.ssh/’ returned a non-zero code: 1

So, any idea on how I could add our private key so that the build server is able to fetch the source from the private repos?

Thanks  
Fritz

---

<div class="post-metadata">

**Author:** ![SplitIce](https://avatars.discourse-cdn.com/v4/letter/s/c5a1d2/32.png) [@SplitIce](https://forums.balena.io/u/SplitIce)\
**Post date:** [August 22, 2018, 10:19pm UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807/13 "2018-08-22T22:19:22Z")

</div>

We had similar concerns.

We ended up resolving this by moving most of our docker work to shell files (which are located for us in a seperate repo). Our docker file contains one layer and looks like:

- Apt-get update
- Setup SSH agent and required tools
- Install base64 encoded deploy key from docker file
- git clone actual repo (e.g to /tmp/build)
- run shell script (e.g /tmp/build/build.sh)
- cleanup (e.g rm /tmp -R -f)

---

<div class="post-metadata">

**Author:** ![pimterry](https://sea2.discourse-cdn.com/balena/user_avatar/forums.balena.io/pimterry/32/140_2.png) [@pimterry](https://forums.balena.io/u/pimterry)\
**Post date:** [August 23, 2018, 12:49pm UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807/14 "2018-08-23T12:49:12Z")

</div>

@fritz it’s hard to be sure exactly what the cause is, but the `Host key verification failed` message you’re seeing in the output there is suspicious.

That means the key of the _host_ is failing to verify, not the client key you’re connecting with. [https://askubuntu.com/questions/45679/ssh-connection-problem-with-host-key-verification-failed-error](https://askubuntu.com/questions/45679/ssh-connection-problem-with-host-key-verification-failed-error) has some more details, and might be useful. Regardless though, that’s not a problem with your id\_rsa key, and that setup might well be working correctly.

I should note here by the way that we are working on first-class support for secrets in builds as we speak. That should make managing secrets like these private keys much easier in future, though it won’t solve this host verification issue. We don’t have a fixed ETA yet, but you can check the status of that on our public roadmap here: [https://trello.com/c/ucTQpzRE/44-build-secrets-and-variables](https://trello.com/c/ucTQpzRE/44-build-secrets-and-variables)

---

<div class="post-metadata">

**Author:** ![fritz](https://sea2.discourse-cdn.com/balena/user_avatar/forums.balena.io/fritz/32/6305_2.png) [@fritz](https://forums.balena.io/u/fritz)\
**Post date:** [August 23, 2018, 7:08pm UTC](https://forums.balena.io/t/grabbing-private-code-in-dockerfiles/807/15 "2018-08-23T19:08:05Z")

</div>

Hi,  
thanks to both of you for your remarks.  
Indeed, there was an issue with obtaining the right host key.  
So I added the known\_hosts file with just the entry of our bitbucket server to the image and used:  
COPY known\_hosts /root/.ssh/known\_hosts

That did the trick. The repo could be loaded successfully.  
Great.  
Thanks!  
Fritz
