How Can Rust, React and Docker Simplify Modern App Development?

I am thrilled and proud of the progress made in integrating the best tools for modern application development. After tackling multiple challenges, I successfully created a containerized full-stack app with Rust powering the backend and React driving the frontend. Containerizing it with Docker ensures smooth deployments and scalability.

A Solved Code

Here’s a complete guide and code implementation for a Rust backend, React frontend, and Docker containerization.

Backend in Rust (Using Actix-Web Framework)

main.rs:

codeuse actix_web::{web, App, HttpResponse, HttpServer, Responder};

async fn get_items() -> impl Responder {
HttpResponse::Ok().json(vec![
{"name": "MacBook Pro", "price": 100000},
{"name": "Pendrive", "price": 4000},
{"name": "Mobile", "price": 35000},
])
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new().route("/items", web::get().to(get_items))
})
.bind("0.0.0.0:8080")?
.run()
.await
}

Dependencies (in Cargo.toml):

code[dependencies]
actix-web = "4.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

Frontend in React

Install Dependencies:

codenpx create-react-app frontend
cd frontend
npm install axios

React Component for Fetching Items:

codeimport React, { useState, useEffect } from 'react';
import axios from 'axios';

const App = () => {
const [items, setItems] = useState([]);
const [cart, setCart] = useState([]);
const [total, setTotal] = useState(0);

useEffect(() => {
axios.get('http://localhost:8080/items')
.then(response => setItems(response.data))
.catch(error => console.error('Error fetching items:', error));
}, []);

const addToCart = (item) => {
setCart([...cart, item]);
setTotal(total + item.price);
};

return (
<div>
<h1>Shop</h1>
{items.map((item, index) => (
<div key={index}>
<h3>{item.name}</h3>
<p>Price: ${item.price}</p>
<button onClick={() => addToCart(item)}>Add to Cart</button>
</div>
))}

<h2>Cart</h2>
<ul>
{cart.map((item, index) => (
<li key={index}>
{item.name} - ${item.price}
</li>
))}
</ul>
<h3>Total Bill: ${total}</h3>
</div>
);
};

export default App;

Dockerizing the Application

Dockerfile for Rust Backend:

code# Stage 1: Build the Rust application
FROM rust:1.70 as builder
WORKDIR /app
COPY . .
RUN cargo build --release

# Stage 2: Create a minimal image
FROM debian:buster-slim
WORKDIR /app
COPY --from=builder /app/target/release/backend /app/backend
EXPOSE 8080
CMD ["./backend"]

Dockerfile for React Frontend:

code# Stage 1: Build the React application
FROM node:16 as builder
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
RUN npm run build

# Stage 2: Serve with NGINX
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Docker Compose:

codeversion: '3.8'
services:
backend:
build:
context: ./backend
ports:
- "8080:8080"

frontend:
build:
context: ./frontend
ports:
- "3000:80"
depends_on:
- backend

Explanation

  1. Rust Backend:
    • The backend serves an API endpoint (/items) using the Actix-Web framework. It returns a JSON response containing item data.
    • Rust’s performance and reliability make it a perfect choice for the backend.
  2. React Frontend:
    • The React app fetches data from the Rust API and displays it dynamically. Users can add items to the cart, and the total price is updated in real time.
  3. Dockerization:
    • Docker simplifies deployment by packaging the backend and frontend into isolated containers.
    • A docker-compose.yml file orchestrates the services, ensuring they communicate seamlessly.
  4. Development Workflow:
    • Developers can run docker-compose up to start the entire application stack locally.
    • The application runs on localhost:3000 for the frontend and localhost:8080 for the backend.

Conclusion

Combining Rust, React, and Docker creates a powerful and efficient full-stack application. Rust’s speed and memory safety make it ideal for the backend, while React’s component-based architecture ensures a dynamic frontend. Docker ties everything together for easy deployment and scaling.

Related blog posts