<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Cameron on Medium]]></title>
        <description><![CDATA[Stories by Cameron on Medium]]></description>
        <link>https://medium.com/@c_ameron?source=rss-9e1c9c4f88b0------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*W0_erRlIWNS5zGnSgup6Lw.jpeg</url>
            <title>Stories by Cameron on Medium</title>
            <link>https://medium.com/@c_ameron?source=rss-9e1c9c4f88b0------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 06 Jun 2026 04:49:06 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@c_ameron/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Rust: How to build a Docker image with private Cargo dependencies]]></title>
            <link>https://medium.com/@c_ameron/rust-how-to-build-a-docker-image-with-private-cargo-dependencies-ab91c25c4301?source=rss-9e1c9c4f88b0------2</link>
            <guid isPermaLink="false">https://medium.com/p/ab91c25c4301</guid>
            <category><![CDATA[rust]]></category>
            <category><![CDATA[git]]></category>
            <category><![CDATA[cargo]]></category>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[github]]></category>
            <dc:creator><![CDATA[Cameron]]></dc:creator>
            <pubDate>Wed, 01 May 2019 04:08:50 GMT</pubDate>
            <atom:updated>2020-05-16T14:38:35.233Z</atom:updated>
            <content:encoded><![CDATA[<p><a href="https://www.rust-lang.org/">Rust</a> is growing in popularity, having earned the most loved language in <a href="https://insights.stackoverflow.com/survey/2019#most-loved-dreaded-and-wanted">Stack Overflow’s 2019 Developer Survey</a> for the fourth year in a row. While <a href="https://doc.rust-lang.org/cargo/">Cargo</a> and Rust’s tooling are great, there’s still a few tricks in getting them to work in a production setting</p><p>In this article, I’m going to show you how to fetch private Cargo dependencies and source them when building a Docker image. This solves a key issue with Docker of not copying over SSH keys when building an image</p><p>The code for this blog post can be found in the Github repository below</p><p><a href="https://github.com/c-ameron/rocket-add">c-ameron/rocket-add</a></p><h3>Example Application: Rocket-Add</h3><p>I’ve developed an example API called <a href="https://github.com/c-ameron/rocket-add">Rocket-Add</a> which is built on top of a very cool web framework in Rust called <a href="https://github.com/SergioBenitez/Rocket/">Rocket</a></p><p>This application extends the ‘<em>Hello World</em>’ example with a new API call add/&lt;num1&gt;/&lt;num2&gt; which adds two numbers and outputs the result</p><pre>$ curl localhost:8000/add/5/10<br>The sum of 5 and 10 is 15</pre><p>The API endpoint is written as a function</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f364cc36a99db314593181ab1bdf3b6d/href">https://medium.com/media/f364cc36a99db314593181ab1bdf3b6d/href</a></iframe><p>Looking closely, you can see the addition calls an external library math_utils with the call math_utils::add(num1, num2)</p><p>The math_utils crate is from a private Github repository <a href="https://github.com/c-ameron/rust-math-utils.git">https://github.com/c-ameron/rust-math-utils.git</a></p><p>For reference, this is the code for the add function in math_utils being used</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7ef47ae9f4c507ddc3a1cff7cf62f360/href">https://medium.com/media/7ef47ae9f4c507ddc3a1cff7cf62f360/href</a></iframe><h3>Fetching crates in private repositories</h3><p>Before we go any further, we’re going to take a page from Ruby Bundler’s book and create a local .cargo folder in the project root. This will provide a project-independent place to store our crates and Cargo config</p><pre>git clone <a href="mailto:git@github.com">git@github.com</a>:c-ameron/rocket-add.git<br>cd rocket-add<br>mkdir -p $(git rev-parse --show-toplevel)/.cargo<br>export CARGO_HOME=$(git rev-parse --show-toplevel)/.cargo</pre><p>Currently Cargo by default won’t <a href="https://github.com/rust-lang/cargo/issues/1851">fetch from private repositories</a></p><p>To get around this, create a .cargo/config file which tells Cargo to use the <a href="https://doc.rust-lang.org/nightly/cargo/reference/config.html#configuration-keys">git cli for fetching</a></p><pre>$ cat .cargo/config<br>[net]<br>git-fetch-with-cli = true</pre><p>Then in our Cargo.toml we tell Cargo to fetch our crate with SSH</p><pre>math_utils = { version = &quot;0.1.0&quot;, git = &quot;ssh://git@github.com/c-ameron/rust-math-utils.git&quot;}</pre><p>Now we can run cargo fetch and it will download all the crates to the local .cargo folder</p><h3>Building a Rust Docker image with private dependencies</h3><p>A frequently encountered problem when building a Docker image is downloading private dependencies without mounting an SSH key</p><p>To solve this problem, we can copy over our pre-fetched .cargo folder to the Docker image and build from there. Now Cargo won’t need to use any SSH keys to fetch from private repositories</p><p>Note that we’re having to set the WORKDIR and CARGO_HOME inside the Docker image for Cargo to resolve its crates correctly</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9bb241ddf181aa86fb8a18789de73961/href">https://medium.com/media/9bb241ddf181aa86fb8a18789de73961/href</a></iframe><p>We can also take advantage of <a href="https://docs.docker.com/develop/develop-images/multistage-build/">multi-stage builds</a> in Docker, and create a smaller binary image</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9dc4c8489fb84e35e4539ad284a04478/href">https://medium.com/media/9dc4c8489fb84e35e4539ad284a04478/href</a></iframe><p>This approach saves time downloading the same crates each build and we also don’t need to pass any SSH keys to Docker. However, if there’s any change to our dependencies it will require a rebuild. For a larger application with a lot of changing dependencies, this often means rebuilding from scratch several times a day</p><h3>Notes</h3><ul><li>Docker has implemented experimental support for SSH forwarding when building images in <a href="https://docs.docker.com/develop/develop-images/build_enhancements/#using-ssh-to-access-private-data-in-builds">18.09</a>, potentially negating the need for copying .cargo in the future</li><li>If you want to fetch or build an image completely offline with Cargo, you can use the -Z offline flag. See <a href="https://doc.rust-lang.org/cargo/reference/unstable.html#offline-mode">https://doc.rust-lang.org/cargo/reference/unstable.html#offline-mode</a></li><li>With recently released Rust 1.34, Cargo now has support for <a href="https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#alternative-cargo-registries">alternative registries</a> other than crates.io</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ab91c25c4301" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>