Skip to content

Commit f27dc4f

Browse files
Copilotngocbd
andcommitted
Add comprehensive Rust project structure with Axum, SQLx, Redis, and PostgreSQL
Co-authored-by: ngocbd <439333+ngocbd@users.noreply.github.com>
1 parent 41f7891 commit f27dc4f

22 files changed

Lines changed: 2098 additions & 0 deletions

.env.example

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Database Configuration
2+
DATABASE_URL=postgresql://postgres:password@localhost:5432/container_engine
3+
4+
# Redis Configuration
5+
REDIS_URL=redis://localhost:6379
6+
7+
# Server Configuration
8+
PORT=3000
9+
10+
# JWT Configuration
11+
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
12+
JWT_EXPIRES_IN=3600
13+
14+
# API Key Configuration
15+
API_KEY_PREFIX=ce_api_
16+
17+
# Kubernetes Configuration
18+
KUBERNETES_NAMESPACE=container-engine
19+
20+
# Domain Configuration
21+
DOMAIN_SUFFIX=container-engine.app
22+
23+
# Logging
24+
RUST_LOG=container_engine=debug,tower_http=debug

.gitignore

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Rust
2+
/target/
3+
Cargo.lock
4+
5+
# IDE
6+
.vscode/
7+
.idea/
8+
*.swp
9+
*.swo
10+
11+
# OS
12+
.DS_Store
13+
Thumbs.db
14+
15+
# Environment
16+
.env
17+
.env.local
18+
19+
# Logs
20+
*.log
21+
22+
# Temporary files
23+
/tmp/
24+
/temp/
25+
26+
# Database
27+
*.db
28+
*.sqlite
29+
30+
# Redis
31+
dump.rdb
32+
33+
# Docker
34+
.dockerignore
35+
36+
# Kubernetes
37+
*.kubeconfig

Cargo.toml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
[package]
2+
name = "container-engine"
3+
version = "0.1.0"
4+
edition = "2021"
5+
description = "An open-source alternative to Google Cloud Run built with Rust & Axum"
6+
license = "MIT"
7+
repository = "https://github.com/ngocbd/Open-Container-Engine"
8+
9+
[dependencies]
10+
# Web framework
11+
axum = { version = "0.7", features = ["macros", "tracing"] }
12+
tokio = { version = "1.0", features = ["full"] }
13+
tower = { version = "0.4", features = ["util"] }
14+
tower-http = { version = "0.5", features = ["fs", "trace", "cors"] }
15+
16+
# Database
17+
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres", "uuid", "chrono", "migrate"] }
18+
19+
# Redis
20+
redis = { version = "0.25", features = ["tokio-comp"] }
21+
22+
# Serialization
23+
serde = { version = "1.0", features = ["derive"] }
24+
serde_json = "1.0"
25+
26+
# Logging and tracing
27+
tracing = "0.1"
28+
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
29+
30+
# Configuration
31+
config = "0.14"
32+
clap = { version = "4.0", features = ["derive"] }
33+
34+
# Async utilities
35+
futures = "0.3"
36+
37+
# HTTP client (for container registry operations)
38+
reqwest = { version = "0.11", features = ["json"] }
39+
40+
# Authentication and security
41+
bcrypt = "0.15"
42+
jsonwebtoken = "9.0"
43+
uuid = { version = "1.0", features = ["v4", "serde"] }
44+
45+
# Date and time
46+
chrono = { version = "0.4", features = ["serde"] }
47+
48+
# Error handling
49+
anyhow = "1.0"
50+
thiserror = "1.0"
51+
52+
# Environment variables
53+
dotenv = "0.15"
54+
55+
# Validation
56+
validator = { version = "0.18", features = ["derive"] }
57+
58+
# Regex
59+
regex = "1.0"
60+
61+
# Kubernetes client (for container orchestration)
62+
kube = { version = "0.95", features = ["runtime", "derive"] }
63+
k8s-openapi = { version = "0.23", features = ["latest"] }
64+
65+
[dev-dependencies]
66+
tower-test = "0.4"
67+
tempfile = "3.0"

Dockerfile

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Use the official Rust image as a parent image
2+
FROM rust:1.80 as builder
3+
4+
# Install system dependencies
5+
RUN apt-get update && apt-get install -y \
6+
pkg-config \
7+
libssl-dev \
8+
&& rm -rf /var/lib/apt/lists/*
9+
10+
# Set the working directory
11+
WORKDIR /app
12+
13+
# Copy Cargo files
14+
COPY Cargo.toml Cargo.lock ./
15+
16+
# Copy source code
17+
COPY src ./src
18+
COPY migrations ./migrations
19+
20+
# Build the application
21+
RUN cargo build --release
22+
23+
# Runtime stage
24+
FROM debian:bookworm-slim
25+
26+
# Install runtime dependencies
27+
RUN apt-get update && apt-get install -y \
28+
ca-certificates \
29+
libssl3 \
30+
&& rm -rf /var/lib/apt/lists/*
31+
32+
# Create app user
33+
RUN useradd -m -u 1001 appuser
34+
35+
# Set the working directory
36+
WORKDIR /app
37+
38+
# Copy the binary from builder stage
39+
COPY --from=builder /app/target/release/container-engine /app/container-engine
40+
41+
# Copy migrations
42+
COPY --from=builder /app/migrations ./migrations
43+
44+
# Change ownership to app user
45+
RUN chown -R appuser:appuser /app
46+
47+
# Switch to app user
48+
USER appuser
49+
50+
# Expose port
51+
EXPOSE 3000
52+
53+
# Run the application
54+
CMD ["./container-engine"]

docker-compose.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
version: '3.8'
2+
3+
services:
4+
postgres:
5+
image: postgres:16
6+
environment:
7+
POSTGRES_DB: container_engine
8+
POSTGRES_USER: postgres
9+
POSTGRES_PASSWORD: password
10+
ports:
11+
- "5432:5432"
12+
volumes:
13+
- postgres_data:/var/lib/postgresql/data
14+
healthcheck:
15+
test: ["CMD-SHELL", "pg_isready -U postgres"]
16+
interval: 5s
17+
timeout: 5s
18+
retries: 5
19+
20+
redis:
21+
image: redis:7-alpine
22+
ports:
23+
- "6379:6379"
24+
volumes:
25+
- redis_data:/data
26+
healthcheck:
27+
test: ["CMD", "redis-cli", "ping"]
28+
interval: 5s
29+
timeout: 3s
30+
retries: 5
31+
32+
container-engine:
33+
build: .
34+
ports:
35+
- "3000:3000"
36+
environment:
37+
DATABASE_URL: postgresql://postgres:password@postgres:5432/container_engine
38+
REDIS_URL: redis://redis:6379
39+
PORT: 3000
40+
JWT_SECRET: your-super-secret-jwt-key-change-this-in-production
41+
JWT_EXPIRES_IN: 3600
42+
API_KEY_PREFIX: ce_api_
43+
KUBERNETES_NAMESPACE: container-engine
44+
DOMAIN_SUFFIX: container-engine.app
45+
RUST_LOG: container_engine=debug,tower_http=debug
46+
depends_on:
47+
postgres:
48+
condition: service_healthy
49+
redis:
50+
condition: service_healthy
51+
volumes:
52+
- .:/app
53+
- target_cache:/app/target
54+
working_dir: /app
55+
56+
volumes:
57+
postgres_data:
58+
redis_data:
59+
target_cache:
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
-- Create users table
2+
CREATE TABLE users (
3+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
4+
username VARCHAR(50) UNIQUE NOT NULL,
5+
email VARCHAR(255) UNIQUE NOT NULL,
6+
password_hash VARCHAR(255) NOT NULL,
7+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
8+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
9+
last_login TIMESTAMPTZ,
10+
is_active BOOLEAN NOT NULL DEFAULT true
11+
);
12+
13+
-- Create api_keys table
14+
CREATE TABLE api_keys (
15+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
16+
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
17+
name VARCHAR(100) NOT NULL,
18+
description TEXT,
19+
key_hash VARCHAR(255) NOT NULL,
20+
key_prefix VARCHAR(20) NOT NULL,
21+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
22+
expires_at TIMESTAMPTZ,
23+
last_used TIMESTAMPTZ,
24+
is_active BOOLEAN NOT NULL DEFAULT true
25+
);
26+
27+
-- Create deployments table
28+
CREATE TABLE deployments (
29+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
30+
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
31+
app_name VARCHAR(63) NOT NULL,
32+
image VARCHAR(255) NOT NULL,
33+
port INTEGER NOT NULL DEFAULT 80,
34+
env_vars JSONB NOT NULL DEFAULT '{}',
35+
replicas INTEGER NOT NULL DEFAULT 1,
36+
resources JSONB NOT NULL DEFAULT '{}',
37+
health_check JSONB,
38+
status VARCHAR(50) NOT NULL DEFAULT 'pending',
39+
url VARCHAR(255) NOT NULL,
40+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
41+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
42+
deployed_at TIMESTAMPTZ,
43+
44+
UNIQUE(user_id, app_name)
45+
);
46+
47+
-- Create domains table
48+
CREATE TABLE domains (
49+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
50+
deployment_id UUID NOT NULL REFERENCES deployments(id) ON DELETE CASCADE,
51+
domain VARCHAR(253) NOT NULL UNIQUE,
52+
status VARCHAR(50) NOT NULL DEFAULT 'pending',
53+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
54+
verified_at TIMESTAMPTZ
55+
);
56+
57+
-- Create indexes for better performance
58+
CREATE INDEX idx_users_email ON users(email);
59+
CREATE INDEX idx_users_username ON users(username);
60+
CREATE INDEX idx_api_keys_user_id ON api_keys(user_id);
61+
CREATE INDEX idx_api_keys_key_prefix ON api_keys(key_prefix);
62+
CREATE INDEX idx_api_keys_active ON api_keys(is_active);
63+
CREATE INDEX idx_deployments_user_id ON deployments(user_id);
64+
CREATE INDEX idx_deployments_status ON deployments(status);
65+
CREATE INDEX idx_deployments_app_name ON deployments(app_name);
66+
CREATE INDEX idx_domains_deployment_id ON domains(deployment_id);
67+
CREATE INDEX idx_domains_domain ON domains(domain);
68+
69+
-- Add triggers to update updated_at automatically
70+
CREATE OR REPLACE FUNCTION update_updated_at_column()
71+
RETURNS TRIGGER AS $$
72+
BEGIN
73+
NEW.updated_at = NOW();
74+
RETURN NEW;
75+
END;
76+
$$ language 'plpgsql';
77+
78+
CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users
79+
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
80+
81+
CREATE TRIGGER update_deployments_updated_at BEFORE UPDATE ON deployments
82+
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

0 commit comments

Comments
 (0)