From 660da70666ea1eac921f5554907bc90d14d05877 Mon Sep 17 00:00:00 2001 From: WaveringAna Date: Mon, 27 Jan 2025 16:24:31 -0500 Subject: [PATCH] bundle frontend too --- .env.example | 3 ++ .gitignore | 7 ++-- Dockerfile | 35 +++++++++++++++---- build.sh | 87 ++++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 37 +++++++++++++++++++- src/main.rs | 2 ++ 6 files changed, 162 insertions(+), 9 deletions(-) create mode 100644 .env.example create mode 100755 build.sh diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..7b4ca89 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +DATABASE_URL=postgresql://user:password@localhost/dbname +SERVER_HOST=127.0.0.1 +SERVER_PORT=8080 diff --git a/.gitignore b/.gitignore index f23e992..2eddc74 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,8 @@ **/node_modules node_modules .env -.env.* -/static \ No newline at end of file +/static +/target +/release +release.tar.gz +*.log \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 75f422a..c388602 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,21 @@ -# Build stage -FROM rust:latest as builder +# Frontend build stage +FROM oven/bun:latest AS frontend-builder + +WORKDIR /usr/src/frontend + +# Copy frontend files +COPY frontend/package*.json ./ +RUN bun install + +COPY frontend/ ./ + +# Build frontend with production configuration +ARG API_URL=http://localhost:8080 +ENV VITE_API_URL=${API_URL} +RUN bun run build + +# Rust build stage +FROM rust:latest AS backend-builder # Install PostgreSQL client libraries and SSL dependencies RUN apt-get update && \ @@ -16,7 +32,10 @@ COPY src/ src/ COPY migrations/ migrations/ COPY .sqlx/ .sqlx/ -# Build your application +# Create static directory and copy frontend build +COPY --from=frontend-builder /usr/src/frontend/dist/ static/ + +# Build the application RUN cargo build --release # Runtime stage @@ -30,9 +49,13 @@ RUN apt-get update && \ WORKDIR /app # Copy the binary from builder -COPY --from=builder /usr/src/app/target/release/simplelink /app/simplelink +COPY --from=backend-builder /usr/src/app/target/release/simplelink /app/simplelink + # Copy migrations folder for SQLx -COPY --from=builder /usr/src/app/migrations /app/migrations +COPY --from=backend-builder /usr/src/app/migrations /app/migrations + +# Copy static files +COPY --from=backend-builder /usr/src/app/static /app/static # Expose the port (this is just documentation) EXPOSE 8080 @@ -42,4 +65,4 @@ ENV SERVER_HOST=0.0.0.0 ENV SERVER_PORT=8080 # Run the binary -CMD ["./simplelink"] \ No newline at end of file +CMD ["./simplelink"] diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..db82f91 --- /dev/null +++ b/build.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# Default values +API_URL="http://localhost:8080" +RELEASE_MODE=false + +# Parse command line arguments +for arg in "$@" +do + case $arg in + api-domain=*) + API_URL="${arg#*=}" + shift + ;; + --release) + RELEASE_MODE=true + shift + ;; + esac +done + +echo "Building project with API_URL: $API_URL" +echo "Release mode: $RELEASE_MODE" + +# Check if cargo is installed +if ! command -v cargo &> /dev/null; then + echo "cargo is not installed. Please install Rust and cargo first." + exit 1 +fi + +# Check if npm is installed +if ! command -v npm &> /dev/null; then + echo "npm is not installed. Please install Node.js and npm first." + exit 1 +fi + +# Build frontend +echo "Building frontend..." +# Create .env file for Vite +echo "VITE_API_URL=$API_URL" > frontend/.env + +# Install frontend dependencies and build +cd frontend +npm install +npm run build +cd .. + +# Create static directory if it doesn't exist +mkdir -p static + +# Clean existing static files +rm -rf static/* + +# Copy built files to static directory +cp -r frontend/dist/* static/ + +# Build Rust project +echo "Building Rust project..." +if [ "$RELEASE_MODE" = true ]; then + cargo build --release + + # Create release directory + mkdir -p release + + # Copy binary and static files to release directory + cp target/release/simplelink release/ + cp -r static release/ + cp .env.example release/.env + + # Create a tar archive + tar -czf release.tar.gz release/ + + echo "Release archive created: release.tar.gz" +else + cargo build +fi + +echo "Build complete!" +echo "To run the project:" +if [ "$RELEASE_MODE" = true ]; then + echo "1. Extract release.tar.gz" + echo "2. Configure .env file" + echo "3. Run ./simplelink" +else + echo "1. Configure .env file" + echo "2. Run 'cargo run'" +fi diff --git a/docker-compose.yml b/docker-compose.yml index de2fac9..e159faf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,42 @@ services: interval: 5s timeout: 5s retries: 5 + networks: + - shortener-network + + app: + build: + context: . + dockerfile: Dockerfile + args: + - API_URL=${API_URL:-http://localhost:8080} + container_name: shortener-app + ports: + - "8080:8080" + environment: + - DATABASE_URL=postgresql://shortener:shortener123@db:5432/shortener + - SERVER_HOST=0.0.0.0 + - SERVER_PORT=8080 + depends_on: + db: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/api/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + networks: + - shortener-network + deploy: + restart_policy: + condition: on-failure + max_attempts: 3 + window: 120s + +networks: + shortener-network: + driver: bridge volumes: shortener-data: - diff --git a/src/main.rs b/src/main.rs index 059c8e2..f02382a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ use actix_cors::Cors; +use actix_files as fs; use actix_web::{web, App, HttpServer}; use anyhow::Result; use simplelink::{handlers, AppState}; @@ -61,6 +62,7 @@ async fn main() -> Result<()> { .route("/health", web::get().to(handlers::health_check)), ) .service(web::resource("/{short_code}").route(web::get().to(handlers::redirect_to_url))) + .service(fs::Files::new("/", "./static").index_file("index.html")) }) .workers(2) .backlog(10_000)