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
The code for this blog post is at https://github.com/c-ameron/rocket-add
I’ve developed an example API called Rocket-Add which built on top of a very cool web framework in Rust called Rocket
This application extends the ‘Hello World’ example with a new api call add/<num1>/<num2> which adds two numbers and outputs the result
$ curl localhost:8000/add/5/10
The sum of 5 and 10 is 15
The API endpoint is written as a function
#[get("/add/<num1>/<num2>")]
fn add(num1: i32, num2: i32) -> String {
let s: String = math_utils::add(num1, num2).to_string();
format!("The sum of {} and {} is {}", num1, num2, s)
}
Looking closely, you can see the addition calls an external library math_utils with the call math_utils::add(num1, num2)
The math_utils crate is from a private Github repository https://github.com/c-ameron/rust-math-utils.git
For reference, this is the code for the add function in math_utils being used
pub fn add(num1: i32, num2: i32) -> i32 {
num1 + num2
}
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
git clone [email protected]:c-ameron/rocket-add.git
cd rocket-add
mkdir -p $(git rev-parse --show-toplevel)/.cargo
export CARGO_HOME=$(git rev-parse --show-toplevel)/.cargo
Currently Cargo by default won’t fetch from private repositories
To get around this, create a .cargo/config file which tells Cargo to use the git cli for fetching
$ cat .cargo/config
[net]
git-fetch-with-cli = true
Then in our Cargo.toml we tell Cargo to fetch our crate with SSH
math_utils = { version = "0.1.0", git = "ssh://[email protected]/c-ameron/rust-math-utils.git"}
Now we can run cargo fetch and it will download all the crates to the local .cargo folder
A key problem when building a Docker image is downloading private dependencies without mounting an SSH key
To solve this problem, we can copy over our pre-fetched .cargo folder to the Docker image and build from there. Cargo won’t need to use any SSH keys to fetch from private repositories
Note that we’re having to set the WORKDIR and CARGO_HOME inside the Docker image for Cargo to resolve its crates correctly
FROM rustlang/rust:nightly AS builder
WORKDIR /workdir
ENV CARGO_HOME=/workdir/.cargo
COPY ./Cargo.toml ./Cargo.lock ./
COPY ./.cargo ./.cargo
COPY ./src ./src
RUN cargo +nightly build --release
We can also take advantage of multi-stage builds in Docker, and create a smaller binary image
FROM rustlang/rust:nightly AS builder
WORKDIR /workdir
ENV CARGO_HOME=/workdir/.cargo
COPY ./Cargo.toml ./Cargo.lock ./
COPY ./.cargo ./.cargo
COPY ./src ./src
RUN cargo +nightly build --release
FROM debian:stretch-slim
EXPOSE 8000
COPY --from=0 /workdir/target/release/rocket-add /usr/local/bin
ENTRYPOINT ["/usr/local/bin/rocket-add"]
This approach saves time downloading the same crates 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
.cargo in the future-Z offline flag. See https://doc.rust-lang.org/cargo/reference/unstable.html#offline-modecrates.ioYou can pick as item to see how to apply in markdown.
You can try the evidence!
Paragraphs can be written like so. A paragraph is the basic block of Markdown. A paragraph is what text will turn into when there is no reason it should become anything else.
<span class="evidence">Paragraphs can be written like so. A paragraph is the basic block of Markdown. A paragraph is what text will turn into when there is no reason it should become anything else.</span>Like the Medium component.
Image on the left and Text on the right:
<div class="side-by-side">
<div class="toleft">
<img class="image" src="https://cameron.ci/https://avatars.githubusercontent.com/u/6181947" alt="Alt Text">
<figcaption class="caption">Photo by John Doe</figcaption>
</div>
<div class="toright">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Text on the left and Image on the right:
<div class="side-by-side">
<div class="toleft">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
<div class="toright">
<img class="image" src="https://cameron.ci/https://avatars.githubusercontent.com/u/6181947" alt="Alt Text">
<figcaption class="caption">Photo by John Doe</figcaption>
</div>
</div>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
You can give evidence to a post. Just add the tag to the markdown file.
star: trueYou can add a especial hr to your text.
<div class="breaker"></div>You can add an especial hidden content that appears on hover.
<div class="spoiler"><p>your content</p></div>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
You can add Gists from github.
{ % gist sergiokopplin/91ff4220480727b47224245ee2e9c291 % }You can add Pens from Codepen.
<p data-height="268" data-theme-id="0" data-slug-hash="gfdDu" data-default-tab="result" data-user="chriscoyier" class='codepen'>
See the Pen <a href='https://codepen.io/chriscoyier/pen/gfdDu/'>Crappy Recreation of the Book Cover of *The Flame Alphabet*</a> by Chris Coyier (<a href='https://codepen.io/chriscoyier'>@chriscoyier</a>) on <a href='https://codepen.io'>CodePen</a>.
</p>
<script async src="//assets.codepen.io/assets/embed/ei.js"></script>See the Pen Crappy Recreation of the Book Cover of *The Flame Alphabet* by Chris Coyier (@chriscoyier) on CodePen.
Add your presentations here!
<iframe src="//www.slideshare.net/slideshow/embed_code/key/hqDhSJoWkrHe7l" width="560" height="310" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe>Do you want some videos? Youtube, Vimeo or Vevo? Copy the embed code and paste on your post!
Example
<iframe width="560" height="310" src="https://www.youtube.com/embed/r7XhWUDj-Ts" frameborder="0" allowfullscreen></iframe>This note demonstrates some of what Markdown is capable of doing.
And that’s how to do it.
This note **demonstrates** some of what [Markdown][some/link] is *capable of doing*.There are six levels of headings. They correspond with the six levels of HTML headings. You’ve probably noticed them already in the page. Each level down uses one more hash character. But we are using just 4 of them.
# Heading
## Heading
### Heading
#### Heading1. Item 1
2. A second item
3. Number 3* An item
* Another item
* Yet another item
* And there's more...Here is a quote. What this is should be self explanatory. Quotes are automatically indented when they are used.
> Here is a quote. What this is should be self explanatory.URLs can be made in a handful of ways:
* A named link to [MarkItDown][3].
* Another named link to [MarkItDown](https://google.com/)
* Sometimes you just want a URL like <https://google.com/>.A horizontal rule is a line that goes across the middle of the page. It’s sometimes handy for breaking things up.
---Markdown can also contain images. I’ll need to add something here sometime.
![Markdowm Image][/image/url]
Figure Caption?
![Markdowm Image][/image/url]
<figcaption class="caption">Photo by John Doe</figcaption>
Bigger Images?
![Markdowm Image][/image/url]{: class="bigger-image" }
A HTML Example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h1>Just a test</h1>
</body>
</html>A CSS Example:
pre {
padding: 10px;
font-size: .8em;
white-space: pre;
}
pre, table {
width: 100%;
}
code, pre, tt {
font-family: Monaco, Consolas, Inconsolata, monospace, sans-serif;
background: rgba(0,0,0,.05);
}A JS Example:
// Sticky Header
$(window).scroll(function() {
if ($(window).scrollTop() > 900 && !$("body").hasClass('show-menu')) {
$('#hamburguer__open').fadeOut('fast');
} else if (!$("body").hasClass('show-menu')) {
$('#hamburguer__open').fadeIn('fast');
}
});
Example of project - Indigo Minimalist Jekyll Template - Demo. This is a simple and minimalist template for Jekyll for those who likes to eat noodles.
What has inside?
Check it out here. If you need some help, just tell me.
]]>