DEV Community

Cover image for First steps with Docker + Rust

First steps with Docker + Rust

Roger Torres (he/him/ele) on July 12, 2021

TL;DR: We are going to install Docker and create five different containers for a Rust program, each one a little more complex than the other. Hi...
Collapse
 
metal3d profile image
Patrice Ferlet

For languages than can be statically compiled like Go or Rust, the best is to use "FROM scratch" base and only append the binary in the image. Your images will only be a few Mb sized.

Collapse
 
my profile image
Mindaugas Sharskus

I wanted to suggest scratch too. I once had made Rocket web app image as small as ~10MB. Probably it could be optimized even more.

Collapse
 
rogertorres profile image
Roger Torres (he/him/ele)

Hi! Thank you both for your comments. I understand what you say and I think it is correct. The problem—specific to this tutorial—is that scratch would not work with the project I am using here; at least not without some extra work, which would lead me to fix a few things and explain them (e.g., I would need a static build, a similar problem that I would have with Alpine), which in turn would cross the threshold of a "first steps" beginner post.

Hopefully, people will read this and be aware of this alternative for their particular projects.

Thread Thread
 
metal3d profile image
Patrice Ferlet

Ho, sorry, I thought that Rust makes static bainary by default. I just checked and I understand that I was wrong.

Reading this zderadicka.eu/static-build-of-rust... is a nice complement :)

Thread Thread
 
rsalmei profile image
Rogério Sampaio de Almeida

Hey, Rust does make static binaries by default. But when you use a dependency, it'll bring their own dependencies, and you may end up using one that happens to load something dynamically... Like libc for example.

Collapse
 
cjsmocjsmo profile image
Charlie J Smotherman

Thanks for this. I to am just starting with rust. Going to rewrite a server of mine I wrote in py 2.7 so its time to update it. This looks a lot like the double build Dockerfile I use with my golang containers. Thanks again 😄

Collapse
 
metal3d profile image
Patrice Ferlet

Using rust to rewrite a server made in Python is, IMHO, not the best way. Go is made for this kind of work, easier to use threads (and concurrency) and a lot more readable. It's closer to Python in syntax and you will have more or less the same performances than Rust for this kind of project.

Collapse
 
cjsmocjsmo profile image
Charlie J Smotherman

You are correct and I agree with everything you are saying. To be a little clearer I plan to use Rust during the music server setup process and not necessarily the server itself. Is it a good design choice, probable not. Is it a good way to learn Rust , hopefully :)

Thread Thread
 
rogertorres profile image
Roger Torres (he/him/ele)

If you feel encouraged to do that (and have the time), please share your results (and maybe even the process) of developing such a server :) I would love to read!

Collapse
 
damianesteban profile image
Damian Esteban

To say that Go is "more readable" depends on who you ask. Also, Rust has an excellent concurrency model.

Collapse
 
tomasfejfar profile image
Tomáš Fejfar

When running

RUN cargo build --release
RUN rm src/*.rs
Enter fullscreen mode Exit fullscreen mode

if you ran

RUN cargo build --release & rm src/*.rs
Enter fullscreen mode Exit fullscreen mode

you'd actually get smaller and cleaner layer as the rs files in src would not be part of it. By separating to two different layers you actually create one layer with deps+rs files and another layer that removes the rs files IMHO.

Collapse
 
vbocan profile image
Valer BOCAN

This is interesting read. It would be useful to add a section related to building a Docker image for a Rust workspace as opposed to a regular project. For instance, my app consists of a workspace with three different projects, such that the Cargo.toml file is this:
[workspace]
members = [
"gooblen_lib",
"gooblen_cli",
"gooblen_api"
]

In turn, I have a corresponding Cargo.toml in each project folder (gooblen_lib, gooblen_cli, gooblen_api).

When building the Docker image, the system complains that

no targets specified in the manifest
either src/lib.rs, src/main.rs, a [lib] section, or [[bin]] section must be present
in the child Cargo.toml

Is caching dependencies even supported when working with workspaces?

Collapse
 
cthutu profile image
Matt Davies

You need to run docker run hello-world with sudo for it to work correctly on Linux. Is this expected?

Collapse
 
rogertorres profile image
Roger Torres (he/him/ele)

Hi Matt! Please take a look at this: docs.docker.com/engine/install/lin...

Collapse
 
cthutu profile image
Matt Davies

Thanks!

Collapse
 
pranasb profile image
Pranas Baliuka

Thanks sharing your experience. Consider using Google Distroless as base image in Docker 5. Haven't seen more secure base image so far.

Collapse
 
metal3d profile image
Patrice Ferlet

As said earlier, I would use "scratch" as base image (empty image) with only the binary inside ;)

Collapse
 
stuartwk profile image
Stuart • Edited

When I'm running this, I'm getting the error cannot remove './target/release/deps/holodeck*': No such file or directory. Anyone else getting this issue?

Collapse
 
afonsojramos profile image
Afonso Jorge Ramos

What is this line for?

RUN rm ./target/release/deps/holodeck*

Collapse
 
rogertorres profile image
Roger Torres (he/him/ele) • Edited

Hi Afonso! This removes the binary previously built, so when the last build for release is executed, Docker uses all the cached dependencies and only the application itself (which, in this scenario is the only thing that was changed) is rebuilt.

Collapse
 
pxlmastrxd profile image
Pxlmastr

Very helpful. I now understand how to make my images smaller! Thanks so much and great article!