Search code examples
dockerrust

rust program (server) will remain running, but will close immediately running as a docker image


I have a very simple "Hello world" server that i wrote in RUST, the program is running correctly locally (not as an image), cargo run

Here is my main.rs file -

use axum::{routing::get, Router};
use std::net::SocketAddr;
use tracing_subscriber;

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(|| async { "Hello, world!" }));

    let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
    tracing::debug!("listening on {}", addr);

    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

Cargo.toml:

[package]
name = "axum-project"
version = "0.1.0"
edition = "2021"
[dependencies]
axum = "0.5"
tokio = { version = "1", features = ["full"] }
tracing = "0.1"
tracing-subscriber = "0.2"

here is my dockerfile that was generated using docker init

https://forms.gle/ybq9Krt8jtBL3iCk7

ARG RUST_VERSION=1.70.0
ARG APP_NAME=rust-image



FROM rust:${RUST_VERSION}-alpine AS build
ARG APP_NAME
WORKDIR /app


RUN apk add --no-cache clang lld musl-dev git


RUN --mount=type=bind,source=src,target=src \
    --mount=type=bind,source=Cargo.toml,target=Cargo.toml \
    --mount=type=bind,source=Cargo.lock,target=Cargo.lock \
    --mount=type=cache,target=/app/target/ \
    --mount=type=cache,target=/usr/local/cargo/git/db \
    --mount=type=cache,target=/usr/local/cargo/registry/ \
    cargo build --locked --release && \
    cp ./target/release/$APP_NAME /bin/server


FROM alpine:3.18 AS final


ARG UID=10001
RUN adduser \
    --disabled-password \
    --gecos "" \
    --home "/nonexistent" \
    --shell "/sbin/nologin" \
    --no-create-home \
    --uid "${UID}" \
    appuser
USER appuser

COPY --from=build /bin/server /bin/

EXPOSE 3000

CMD ["/bin/server"]

Whenever i run the image, ill get 2024-07-10 12:23:01 Hello, world! and the container will shut down.


Solution

  • I modified Dockerfile slightly main.rs and Cargo.toml are the same:

    ARG RUST_VERSION=1.70.0
    ARG APP_NAME=rust-image
    
    FROM rust:${RUST_VERSION}-alpine AS build
    
    RUN apk add --no-cache clang lld musl-dev git
    
    WORKDIR /app
    COPY src /app/src
    COPY Cargo.toml /app
    
    ARG APP_NAME
    
    
    RUN cargo build --release && \
        cp ./target/release/axum-project /bin/server
    
    
    FROM alpine:3.18 AS final
    
    
    ARG UID=10001
    RUN adduser \
        --disabled-password \
        --gecos "" \
        --home "/nonexistent" \
        --shell "/sbin/nologin" \
        --no-create-home \
        --uid "${UID}" \
        appuser
    USER appuser
    
    COPY --from=build /bin/server /bin/
    
    EXPOSE 3000
    
    CMD ["/bin/server"] 
    

    Then:

    cd /path/to/project
    docker build -t foo .
    docker run -it --rm -p 3000:3000 foo
    

    in another terminal:

    curl localhost:3000
    

    each time I do curl I get Hello world back.

    You can work your problem by adding your original bits into Dockerfile one by one, rebuilding and rerunning.