How to access private Azure DevOps repos from a Dockerfile!

I recently got pinged on Twitter about how to access a private repo in Azure DevOps when building a container. I thought this was a great question because there is very little documentation on the subject. The use case for this is if using a PAT isn’t an option (and I don’t recommend it from a security practice), you can access Azure DevOps repos via SSH and that’s what I’m going to recommend for your containers.

If you don’t know how to get your ssh command line link, you can just click on “clone” as you normally would and hit SSH instead of HTTPS.

You can then click “Manage SSH keys” to add your public key to your organization.

Now, for your Docker image build you will want to stick to multi-stage builds because of the way layers works. In a single stage build you might export an ARG to capture the private key file and then delete it but the contents of that file will remain in a layer and is therefore insecure. Best practice is multi-stage builds so we’ll demo that here. It’s also smaller and lighter. 😉

You can see in the below file I first define one build as “intermediate” and install Git. I also setup the environment to access the private repo. In the second build, I copy the project I cloned from the intermediate build.

Note, I did borrow parts of the above Dockerfile from here, but I updated it accordingly for Azure DevOps (formerly VSTS).

You can test that locally by running: export SSH_PRIVATE_KEY=$(cat ~/.ssh/private-key-here) and then docker build --build-arg SSH_PRIVATE_KEY=$SSH_PRIVATE_KEY . -t repo-name/image-name

Then you can run that container and see your project in the /srv dir.

The above image is a good start, but it’s not the best we can do. Currently, our Ubuntu image is 88.3mb. We can get that smaller if we use Alpine instead.

Now our image is only 8.56mb. We have a smaller more secure image by just making one small modification.

Of course, for your Azure Pipeline you will need to add in a variable to your pipeline for your SSH_PRIVATE_KEY ARG you defined in your Dockerfile.

You will then need to reference the build argument in your Docker build task just as you did from command line.

And that should be it! Comment below with any questions or suggestions! Also, if you’re going to Microsoft Ignite, be sure to check out my sessions on Containers and DevOps!

Reminder: All of my posts are provided "AS IS", imply no warranties, and confer no rights or special privileges. Use of included postings, code samples and other works are subject to the terms specified at Microsoft. For more information, click here.

Comments 3

  • Thank you so much for this article! This helped me setting my pipeline locally and it works well!

    Unfortunately, I am having a problem with the value of the ssh private key in the Azure Devops build pipeline.

    When you set the value of the SSL_PRIVATE_KEY, did you just paste the content of the id_rsa value in the field? I did this and it is not working. I generated my key on a Windows 10 machine.

    When I launch the pipeline execution, I get errors on the docker build command like:

    ##[error]bad flag syntax: —–END
    ##[error]See ‘docker build –help’.
    ##[error]/usr/local/bin/docker failed with return code: 125

    Or:
    ##[error]”docker build” requires exactly 1 argument.
    ##[error]See ‘docker build –help’.
    ##[error]Usage: docker build [OPTIONS] PATH | URL | – [flags]
    ##[error]Build an image from a Dockerfile
    ##[error]/usr/local/bin/docker failed with return code: 1

    I also tried to include the build arg parameter but it didn’t work: –build-arg SSH_PRIVATE_KEY=$(SSH_PRIVATE_KEY)

    How did you configure this value?

    • You know, you asked a great question. I went and retried this and I was having trouble too, though not the same problem as you. Ultimately though, I believe the issue is related to formatting and preserving the format of a multiline file when passed through a variable. I will be posting a new post update for that tonight.

      ***Edit*** The new blog post is now live! Please let me know if that helps you.

      • Hi Jessica!

        Thank you for your reply and for yout post update. In fact, I also found two solutions that I would like to share with you:

        1) String replacement in the private key file with sed command (it is similar to your solution with ‘tr’). The only thing I had to do before is to replace the space characters in the certificate header by another character (let’s say comma like you did) and then include this in the Dockerfile:

        RUN sed -i ‘s/ /\n/g’ ~/.ssh/id_rsa
        RUN sed -i ‘s/,/ /g’ ~/.ssh/id_rsa

        2) The other one was to use Secure Files. I did not know it existed beforehand and it proved to be a neat way of achieving this:

        https://docs.microsoft.com/en-us/azure/devops/pipelines/library/secure-files

        Best Regards,
        Bruno.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.