# Rust + Docker: Easy packaging of your applications

Let's first create a simple web app with a health check endpoint by running the commands below.

```bash
cargo new rust_docker_app --bin
cd rust_docker_app
cargo add actix-web
touch Dockerfile
```

**So what we've actually done here:**

* created a new binary crate, called **rust\_docker\_app**
    
* added web framework dependency (I prefer [Actix](https://actix.rs/), but you can choose any)
    
* created empty [DockerFile](https://docs.docker.com/engine/reference/builder/)
    

Now let's create a web server with one simple health check endpoint. To do this, you need to update your `main.rs` file with:

```rust
use actix_web::{App, HttpServer, HttpResponse, get};

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(ping)
    })
    .bind(("0.0.0.0", 8080))?
    .run()
    .await
}

#[get("/ping")]
async fn ping() -> HttpResponse {
    HttpResponse::Ok().body("pong")
}
```

So we created an app with `0.0.0.0` address and `8080` port bindings.

`0.0.0.0` is the special **“all interfaces”** address. You must set a docker container’s main process (Actix web app in our case) to bind to it, or it will be unreachable from outside the container.

Our app has only one endpoint, which responds with a "pong" message all the time.

Now let's update our **Dockerfile** with:

```bash
FROM rust:1.66.0 as build
COPY . /rust_docker_app
WORKDIR /rust_docker_app

RUN --mount=type=cache,target=/usr/local/cargo/registry --mount=type=cache,target=/root/target \
    cargo build --release
 
FROM debian:buster-slim as runtime
COPY --from=build /rust_docker_app/target/release/rust_docker_app .
CMD ["./rust_docker_app"]
```

We don't need any project files except compiled binary in our image, that's why we use multi-stage build.

You can read more about multi-stage builds here: [https://docs.docker.com/build/building/multi-stage/](https://docs.docker.com/build/building/multi-stage/)

**So what does this Dockerfile do step by step:**

* copy project files to the first (build) stage
    
* compile the code
    
* copy the binary executable file from the "build" stage to the "runtime" stage, leaving behind everything else we don’t want in the final image
    
* run the compiled binary
    

This part is needed `--mount=type=cache,target=/usr/local/cargo/registry` for caching **Rust** dependencies and it defines which path should be cached as a container image layer.

Now we are ready to build our image. Simply just run the below command in the project root directory:

```bash
docker build -t rust_docker_app .
```

And finally, let's run our web server:

```bash
docker run -p 8080:8080 rust_docker_app
```

Now you can access the health check endpoint by [http://127.0.0.1:8080/ping](http://127.0.0.1:8080/ping). Just try to get it via browser or **CURL** or any other **HTTP** client.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673271946245/a040db39-0f49-48d7-a429-5998d8d3a5e5.png align="center")

I hope you enjoy it. As always you can find working example in my [**GitHub**](https://github.com/paramako-blog/rust_docker_app) repository :)
