From c8858b8e5a89f7a1840fcb0f6cabaa741586b082 Mon Sep 17 00:00:00 2001 From: Rik Heijmann Date: Fri, 28 Feb 2025 21:42:04 +0100 Subject: [PATCH] Add the setup guide for Docker & updated the dockerfile and docker-compose.yml file. --- .env.example | 9 +- .gitignore | 3 +- Dockerfile | 63 +++++++----- docker-compose.yml | 142 +++++++++++++++++++-------- documentation/installation_docker.md | 57 +++++++++++ 5 files changed, 205 insertions(+), 69 deletions(-) create mode 100644 documentation/installation_docker.md diff --git a/.env.example b/.env.example index 6bdd65e..55a9bca 100644 --- a/.env.example +++ b/.env.example @@ -24,8 +24,13 @@ SERVER_WORKER_THREADS=2 # 🛢️ DATABASE CONFIGURATION # ============================== -# PostgreSQL connection URL (format: postgres://user:password@host/database) -DATABASE_URL="postgres://postgres:1234@localhost/database_name" +# For running Axium standalone: +DATABASE_URL="postgres://dbuser:1234@localhost/axium" + +# For docker: +DATABASE_USER=dbuser +DATABASE_PASSWORD=1234 +DATABASE_DB=axium # Maximum number of connections in the database pool DATABASE_MAX_CONNECTIONS=20 diff --git a/.gitignore b/.gitignore index 800b6dc..198689c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ /target cert.pem key.pem -Cargo.lock \ No newline at end of file +Cargo.lock +/docker \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index d06453e..c78240a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,56 +1,67 @@ # --- Stage 1: Builder Stage --- - FROM rust:1.75-slim-bookworm AS builder + FROM rust:1.84-alpine AS builder WORKDIR /app - # Install required build dependencies - RUN apt-get update && apt-get install -y --no-install-recommends \ - pkg-config \ - libssl-dev \ - && rm -rf /var/lib/apt/lists/* + # Install required build dependencies for Rust and SQLx + RUN apk add --no-cache \ + pkgconfig \ + openssl-dev \ + sqlite-dev \ + build-base \ + cmake \ + curl \ + ninja-build \ + clang \ + && rm -rf /var/cache/apk/* - # Cache dependencies - COPY Cargo.toml Cargo.lock ./ - RUN cargo fetch --locked + # Cache dependencies (from Cargo.toml and Cargo.lock) to speed up future builds + COPY Cargo.toml ./ + RUN cargo fetch - # Copy source code + # Copy the source code for the application COPY src src/ - COPY build.rs build.rs + + # Set SQLX_OFFLINE to true for offline SQLx compilation + ENV SQLX_OFFLINE=true + + # Copy the pre-generated SQLx metadata for offline mode + COPY .sqlx .sqlx/ + + # Copy the migrations folder + COPY migrations migrations/ # Build the application in release mode - RUN cargo build --release --locked + RUN cargo build --release --locked --no-default-features # Strip debug symbols to reduce binary size RUN strip /app/target/release/Axium - # --- Stage 2: Runtime Stage --- - FROM debian:bookworm-slim + FROM alpine:latest - # Install runtime dependencies only - RUN apt-get update && apt-get install -y --no-install-recommends \ + # Install runtime dependencies only (ca-certificates, openssl) + RUN apk add --no-cache \ ca-certificates \ openssl \ - && rm -rf /var/lib/apt/lists/* + && rm -rf /var/cache/apk/* - # Create non-root user - RUN useradd --no-log-init -r -m -u 1001 appuser + # Create non-root user for security purposes + RUN adduser -D -u 1001 appuser WORKDIR /app - # Copy built binary from builder stage + # Copy the built binary from the builder stage COPY --from=builder /app/target/release/Axium . - # Copy environment file (consider secrets management for production) - COPY .env .env - - # Change ownership to non-root user + # Ensure the .env file and other app files have the correct ownership and permissions RUN chown -R appuser:appuser /app + # Switch to the non-root user USER appuser - # Expose the application port + # Expose the application port (default 3000) EXPOSE 3000 - # Run the application + # Run the application when the container starts CMD ["./Axium"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 895b710..a6cfab7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,53 +1,115 @@ -version: "3.9" - services: + # Service for the Axium application axium: + # Build the Docker image from the current directory using the specified Dockerfile build: context: . dockerfile: Dockerfile + + # Map ports from the container to the host machine ports: - - "3000:3000" + - "${SERVER_PORT:-3000}:${SERVER_PORT:-3000}" # Expose server port + + # Environment variables for the service environment: - - ENVIRONMENT=${ENVIRONMENT:-development} #default value if not defined. - - SERVER_IP=${SERVER_IP:-0.0.0.0} - - SERVER_PORT=${SERVER_PORT:-3000} - - SERVER_TRACE_ENABLED=${SERVER_TRACE_ENABLED:-true} - - SERVER_WORKER_THREADS=${SERVER_WORKER_THREADS:-2} - - DATABASE_URL=${DATABASE_URL:-postgres://postgres:1234@db/database_name} - - DATABASE_MAX_CONNECTIONS=${DATABASE_MAX_CONNECTIONS:-20} - - DATABASE_MIN_CONNECTIONS=${DATABASE_MIN_CONNECTIONS:-5} - - SERVER_HTTPS_ENABLED=${SERVER_HTTPS_ENABLED:-false} - - SERVER_HTTPS_HTTP2_ENABLED=${SERVER_HTTPS_HTTP2_ENABLED:-true} - # Mount volume for certs for HTTPS - - SERVER_HTTPS_CERT_FILE_PATH=/app/certs/cert.pem # Changed to /app/certs - - SERVER_HTTPS_KEY_FILE_PATH=/app/certs/key.pem # Changed to /app/certs - - SERVER_RATE_LIMIT=${SERVER_RATE_LIMIT:-5} - - SERVER_RATE_LIMIT_PERIOD=${SERVER_RATE_LIMIT_PERIOD:-1} - - SERVER_COMPRESSION_ENABLED=${SERVER_COMPRESSION_ENABLED:-true} - - SERVER_COMPRESSION_LEVEL=${SERVER_COMPRESSION_LEVEL:-6} - - JWT_SECRET_KEY=${JWT_SECRET_KEY:-Change me!} #VERY important to change this! + # Set environment (e.g., development, production) + - ENVIRONMENT=${ENVIRONMENT:-development} # Default to development if not set + + # Server settings + - SERVER_IP=${SERVER_IP:-0.0.0.0} # Default IP to listen on + - SERVER_PORT=${SERVER_PORT:-3000} # Default port to listen on + - SERVER_TRACE_ENABLED=${SERVER_TRACE_ENABLED:-true} # Enable tracing by default + - SERVER_WORKER_THREADS=${SERVER_WORKER_THREADS:-2} # Number of worker threads + + # Database connection settings + - DATABASE_URL=postgres://${DATABASE_USER:-dbuser}:${DATABASE_PASSWORD:-1234}@db/${DATABASE_DB:-axium} + - DATABASE_MAX_CONNECTIONS=${DATABASE_MAX_CONNECTIONS:-20} # Max database connections + - DATABASE_MIN_CONNECTIONS=${DATABASE_MIN_CONNECTIONS:-5} # Min database connections + + # HTTPS settings + - SERVER_HTTPS_ENABLED=${SERVER_HTTPS_ENABLED:-false} # Disable HTTPS by default + - SERVER_HTTPS_HTTP2_ENABLED=${SERVER_HTTPS_HTTP2_ENABLED:-true} # Enable HTTP/2 for HTTPS + + # Certificate paths for HTTPS + - SERVER_HTTPS_CERT_FILE_PATH=/app/certs/cert.pem + - SERVER_HTTPS_KEY_FILE_PATH=/app/certs/key.pem + + # Rate limiting settings + - SERVER_RATE_LIMIT=${SERVER_RATE_LIMIT:-5} # Default rate limit + - SERVER_RATE_LIMIT_PERIOD=${SERVER_RATE_LIMIT_PERIOD:-1} # Rate limit period in seconds + + # Compression settings + - SERVER_COMPRESSION_ENABLED=${SERVER_COMPRESSION_ENABLED:-true} # Enable compression by default + - SERVER_COMPRESSION_LEVEL=${SERVER_COMPRESSION_LEVEL:-6} # Compression level + + # JWT secret key (change this in production!) + - JWT_SECRET_KEY=${JWT_SECRET_KEY:-Change me!} # VERY important to change this! + + # Depend on the database service and wait until it's healthy depends_on: - - db # Ensure the database is up before the app + db: + condition: service_healthy + + # Mount volumes for certificates volumes: - - ./certs:/app/certs # Mount volume for certs + - ./certs:/app/certs # Mount local certs directory to container + + # Health check settings healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:3000/health"] - interval: 10s - timeout: 5s - retries: 3 - start_period: 15s + # Test the health of the service by checking the /health endpoint + test: ["CMD", "curl", "-f", "http://${SERVER_IP:-0.0.0.0}:${SERVER_PORT:-3000}/health"] + interval: 10s # Check every 10 seconds + timeout: 5s # Timeout after 5 seconds + retries: 3 # Retry up to 3 times + start_period: 15s # Wait 15 seconds before starting checks + # Resource limits for the service + deploy: + resources: + limits: + # Limit CPU usage (default: 0.5 cores) + cpus: '${AXIUM_CPU_LIMIT:-0.5}' + # Limit RAM usage (default: 512MB) + memory: ${AXIUM_MEMORY_LIMIT:-512M} + + # Service for the PostgreSQL database db: - image: postgres:16-alpine - restart: always - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: "1234" # Change this in production! - POSTGRES_DB: database_name # Matches the DB name in .env - ports: - - "5432:5432" - volumes: - - db_data:/var/lib/postgresql/data + # Use the official PostgreSQL 17 Alpine image + image: postgres:17-alpine -volumes: - db_data: + # Always restart the container if it fails + restart: always + + # Environment variables for the database + environment: + # Set database user, password, and database name + - POSTGRES_USER=${DATABASE_USER:-dbuser} + - POSTGRES_PASSWORD=${DATABASE_PASSWORD:-1234} + - POSTGRES_DB=${DATABASE_DB:-axium} + + # Map the database port to the host machine + ports: + - "5432:5432" # Expose PostgreSQL port + + # Mount volumes for database data and logs + volumes: + - ./docker/db/data:/var/lib/postgresql/data # Store database data + - ./docker/db/logs:/var/log/postgresql # Store logs + + # Health check settings for the database + healthcheck: + # Test the health of the database using pg_isready + test: ["CMD", "pg_isready", "-U", "${DATABASE_USER:-dbuser}"] + interval: 60s # Check every minute + timeout: 10s # Timeout after 10 seconds + retries: 5 # Retry up to 5 times + start_period: 15s # Wait 15 seconds before starting checks + + # Resource limits for the database service + deploy: + resources: + limits: + # Limit CPU usage (default: 0.5 cores) + cpus: '${DB_CPU_LIMIT:-0.5}' + # Limit RAM usage (default: 256MB) + memory: ${DB_MEMORY_LIMIT:-256M} \ No newline at end of file diff --git a/documentation/installation_docker.md b/documentation/installation_docker.md new file mode 100644 index 0000000..fbd4d8e --- /dev/null +++ b/documentation/installation_docker.md @@ -0,0 +1,57 @@ +### Setup Instructions for Axium within Docker + +This guide walks you through building **Axium** as a docker container. + +Make sure that you have docker aswell as docker compose (which is bundled with docker in the most recent releases of docker) installed. + +Please note! That in a production system I wouldn't want to run the database on the same server as the API. + +The shown commands except nano will work on Windows' PowerShell (you can use notepad.exe instead of nano). + +--- + +1. **Clone the Axium repository**: + Clone the Axium repository from GitHub: + ```sh + git clone https://github.com/Riktastic/Axium.git + ``` + +--- + +2. **Navigate to the Axium directory**: + Move into the cloned repository: + ```sh + cd Axium + ``` + +--- + +3. **Copy the Example environment file**: + Copy the `.env.example` file to `.env` to configure your environment: + ```sh + cp .env.example .env + ``` + +--- + +4. **Edit the `.env` File**: + Update the `.env` file with your database settings if necessary: + ```sh + nano .env + ``` + +--- + +1. **Build and run the container**: + Start Axium using Docker Compose: + ```sh + docker compose up + ``` + +--- + +After sucessfully building the image, it will start two containers: +- axium-axium-1: Axium, +- axium-db-1: The PostgreSQL database + +The database will store its files within the `./docker` folder. \ No newline at end of file