In this guide, you’ll learn how to package your custom app with a Fluvio client into a Docker image, and how to run a container with docker CLI.
We assume you are connected to a cluster with the CLI. If this is not the case, please login to Cloud before continuing.
Example custom Fluvio client
To help illustrate the basic development workflow for all services using a Fluvio client, we’ll create this sample Rust service.
Run these commands to initialize the project
$ cargo new fluvio-rust-client
$ cd fluvio-rust-client
$ cargo add async-std --features attributes
$ cargo add chrono fluvio
Copy this code into src/main.rs
useasync_std::stream::StreamExt;usechrono::Local;usefluvio::metadata::topic::TopicSpec;usefluvio::{Fluvio,RecordKey};constTOPIC_NAME: &str="hello-rust";constPARTITION_NUM: u32=0;constPARTITIONS: u32=1;constREPLICAS: u32=1;/// This is an example of a basic Fluvio workflow in Rust
///
/// 1. Establish a connection to the Fluvio cluster
/// 2. Create a topic to store data in
/// 3. Create a producer and send some bytes
/// 4. Create a consumer, and stream the data back
#[async_std::main]asyncfnmain(){// Connect to Fluvio cluster
letfluvio=Fluvio::connect().await.unwrap();// Create a topic
letadmin=fluvio.admin().await;lettopic_spec=TopicSpec::new_computed(PARTITIONS,REPLICAS,None);let_topic_create=admin.create(TOPIC_NAME.to_string(),false,topic_spec).await;// Create a record
letrecord=format!("Hello World! - Time is {}",Local::now().to_rfc2822());// Produce to a topic
letproducer=fluvio::producer(TOPIC_NAME).await.unwrap();producer.send(RecordKey::NULL,record).await.unwrap();// Fluvio batches outgoing records by default, so flush producer to ensure all records are sent
producer.flush().await.unwrap();// Consume last record from topic
letconsumer=fluvio::consumer(TOPIC_NAME,PARTITION_NUM).await.unwrap();letmutstream=consumer.stream(fluvio::Offset::from_end(1)).await.unwrap();ifletSome(Ok(record))=stream.next().await{letstring=String::from_utf8_lossy(record.value());println!("{}",string);}}
Example Dockerfile
Save the following Dockerfile. This Dockerfile adds our workflow an starts it with cargo run, which will always build the code before it starts.
FROM rust:1.73.0
# Run as the `fluvio` user instead of rootENV USER=fluvio
RUN useradd --create-home "$USER"USER $USERWORKDIR /home/fluvio
# Copy your Rust project and run itCOPY --chown=$USER:$USER Cargo.toml .
COPY --chown=$USER:$USER src ./src
CMD /usr/local/cargo/bin/cargo run
Running docker image
The fluvio clients search for connection information from a config file located at $HOME/.fluvio/config.
Run with docker run
In this example, we build our docker image with docker build then start a container from the image with docker run. We volume mount our host’s config file to the container when we start.
Running `target/debug/fluvio-rust-client`Hello World! - Time is Tue, 10 Oct 2023 21:09:05 +0000
The same event has been published to the topic:
$ fluvio consume -Bd hello-rust
Consuming records from 'hello-rust' starting from the beginning of log
Hello World! - Time is Tue, 10 Oct 2023 21:09:05 +0000
Run with docker compose (alternative)
Copy this yaml file and save it as docker-compose.yaml
In this example, we build our docker image with docker compose build then start a container from the image with docker compose up. We volume mount our host’s config file to the container when we start.