This project is a Rust-based backend/web API that connects to a PostgreSQL database. It uses Docker and Docker Compose for easy local development and deployment, and includes utilities for database management, migrations, and more. You can choose to run PostgreSQL either locally (via Docker) or remotely by configuring the environment variables.
Before you begin, ensure you have the following installed:
- Docker (version 20+)
- Docker Compose (version 1.29+)
git clone <repository-url>
cd <repository-directory>
Decide whether you're connecting to a local PostgreSQL container (using Docker) or a remote PostgreSQL instance. Configure this using .env
files.
- Create a
.env.local
file based on the template below and specifyPOSTGRES_HOST=postgres
.
Example .env.local
:
POSTGRES_USER=refactor
POSTGRES_PASSWORD=password
POSTGRES_DB=refactor
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_SCHEMA=refactor_platform
DATABASE_URL=postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB
BACKEND_LOG_FILTER_LEVEL="DEBUG"
BACKEND_PORT=4000
BACKEND_INTERFACE=0.0.0.0
BACKEND_ALLOWED_ORIGINS="http://localhost:3000,https://localhost:3000"
BACKEND_SERVICE_PROTOCOL="http"
BACKEND_SERVICE_PORT=${BACKEND_PORT}
BACKEND_SERVICE_HOST="localhost"
BACKEND_API_VERSION="0.0.1"
FRONTEND_SERVICE_INTERFACE=0.0.0.0
FRONTEND_SERVICE_PORT=3000
USERNAME=appuser
USER_UID=1000
USER_GID=1000
CONTAINER_NAME=refactor-platform
PLATFORM=linux/arm64
TIPTAP_URL=https://{Tiptap API Key}.collab.tiptap.cloud/
TIPTAP_AUTH_KEY=tiptap-auth-key
TIPTAP_JWT_SIGNING_KEY=tiptap-jwt-signing-key
- Create a
.env.remote-db
file and setPOSTGRES_HOST
to the external IP or hostname of the remote PostgreSQL instance.
Example .env.remote-db
:
# PostgreSQL environment variables for local development
POSTGRES_USER=refactor # Default PostgreSQL user for local development
POSTGRES_PASSWORD=password # Default PostgreSQL password for local development
POSTGRES_DB=refactor # Default PostgreSQL database for local development
POSTGRES_HOST=postgres # The local Docker Compose PostgreSQL container hostname
POSTGRES_PORT=5432 # PostgreSQL default port for local development
POSTGRES_SCHEMA=refactor_platform # PostgreSQL schema for the application
# Database connection URL for the Rust application
DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
# Rust application environment variables
BACKEND_LOG_FILTER_LEVEL="DEBUG"
BACKEND_ALLOWED_ORIGINS="http://localhost:3000,https://localhost:3000"
BACKEND_PORT=4000
BACKEND_INTERFACE=0.0.0.0
# Next.js application build & environment variables
BACKEND_SERVICE_PROTOCOL="http"
BACKEND_SERVICE_PORT=${BACKEND_PORT}
BACKEND_SERVICE_HOST="localhost"
BACKEND_API_VERSION="0.0.1"
FRONTEND_SERVICE_INTERFACE=0.0.0.0
FRONTEND_SERVICE_PORT=3000
PLATFORM=linux/arm64 # For Raspberry Pi 5 or Apple Silicon
CONTAINER_NAME="refactor-platform"
# App user configuration
USERNAME=appuser # Username for the non-root user in the container
USER_UID=1000 # User ID for the appuser
USER_GID=1000 # Group ID for the appuser
TIPTAP_URL=https://{Tiptap API Key}.collab.tiptap.cloud/
TIPTAP_AUTH_KEY=tiptap-auth-key
TIPTAP_JWT_SIGNING_KEY=tiptap-jwt-signing-key
The docker-compose.yaml
file uses environment variables defined in your .env
file setting important
configuration variables for both the Rust backend and the Next.js frontend applications.
services:
postgres:
image: postgres:17
container_name: postgres
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
ports:
- "${POSTGRES_PORT}:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./migration/src/setup.sql:/docker-entrypoint-initdb.d/0-setup.sql
- ./migration/src/refactor_platform_rs.sql:/docker-entrypoint-initdb.d/1-refactor_plaform_rs.sql
- ./migration/src/setup_default_user.sql:/docker-entrypoint-initdb.d/2-setup_default_user.sql
networks:
- backend_network
rust-app:
image: rust-backend
build:
context: .
dockerfile: Dockerfile
target: runtime
platform: ${PLATFORM}
container_name: ${CONTAINER_NAME}
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_SCHEMA: ${POSTGRES_SCHEMA}
POSTGRES_HOST: postgres
POSTGRES_PORT: ${POSTGRES_PORT}
DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:${POSTGRES_PORT}/${POSTGRES_DB}
BACKEND_PORT: ${BACKEND_PORT}
BACKEND_INTERFACE: ${BACKEND_INTERFACE}
BACKEND_ALLOWED_ORIGINS: ${BACKEND_ALLOWED_ORIGINS}
BACKEND_LOG_FILTER_LEVEL: ${BACKEND_LOG_FILTER_LEVEL}
TIPTAP_URL: ${TIPTAP_URL}
TIPTAP_AUTH_KEY: ${TIPTAP_AUTH_KEY}
TIPTAP_JWT_SIGNING_KEY: ${TIPTAP_JWT_SIGNING_KEY}
ports:
- "${BACKEND_PORT}:${BACKEND_PORT}"
depends_on:
- postgres
networks:
- backend_network
command: ["sh", "-c", "sleep 5 && /usr/local/bin/refactor_platform_rs"]
nextjs-app:
build:
context: https://github.com/refactor-group/refactor-platform-fe.git#main
dockerfile: Dockerfile
target: runner
args:
NEXT_PUBLIC_BACKEND_SERVICE_PROTOCOL: ${BACKEND_SERVICE_PROTOCOL}
NEXT_PUBLIC_BACKEND_SERVICE_PORT: ${BACKEND_PORT}
NEXT_PUBLIC_BACKEND_SERVICE_HOST: ${BACKEND_SERVICE_HOST}
NEXT_PUBLIC_BACKEND_API_VERSION: ${BACKEND_API_VERSION}
FRONTEND_SERVICE_PORT: ${FRONTEND_SERVICE_PORT}
FRONTEND_SERVICE_INTERFACE: ${FRONTEND_SERVICE_INTERFACE}
environment:
NEXT_PUBLIC_BACKEND_SERVICE_PROTOCOL: ${BACKEND_SERVICE_PROTOCOL}
NEXT_PUBLIC_BACKEND_SERVICE_PORT: ${BACKEND_PORT}
NEXT_PUBLIC_BACKEND_SERVICE_HOST: ${BACKEND_SERVICE_HOST}
NEXT_PUBLIC_BACKEND_API_VERSION: ${BACKEND_API_VERSION}
ports:
- "${FRONTEND_SERVICE_PORT}:${FRONTEND_SERVICE_PORT}"
depends_on:
- rust-app
networks:
backend_network:
driver: bridge
volumes:
postgres_data
docker buildx build --platform linux/amd64,linux/arm64 -t rust-backend .
This builds the image for both amd64
and arm64
architectures. Use the --platform
flag to build for a specific architecture.
docker-compose --env-file .env.local up --build
docker-compose --env-file .env.remote-db up --build
The web API will be accessible at http://localhost:<SERVICE_PORT>
docker-compose run rust-app rebuild-db
docker-compose run rust-app seed-db
If you have a DBML file (schema.dbml
), convert it to SQL:
docker-compose run -v $(pwd)/sql:/app/sql -v $(pwd)/schema.dbml:/app/schema.dbml rust-app dbml2sql
docker-compose run -v $(pwd)/sql:/app/sql -v $(pwd)/schema.dbml:/app/schema.dbml rust-app dbml2sql
docker-compose down
docker-compose down -v
-
Verify PostgreSQL is running:
docker-compose ps
-
Check logs for PostgreSQL:
docker-compose logs postgres
-
Verify the container is running:
docker-compose ps
-
Check logs for the Rust app:
docker-compose logs rust-app
-
Confirm the correct port in
.env
:SERVICE_PORT=4000
Change the ports in .env
or docker-compose.yaml
:
services:
postgres:
ports:
- "5433:5432"
rust-app:
ports:
- "9090:8080"
docker-compose build
docker-compose up
Ensure volumes are configured in docker-compose.yaml
:
volumes:
postgres_data:
-
Run containers in detached mode:
docker-compose up -d
-
Access a running container:
docker exec -it <container_name> bash
-
Restart a single service:
docker-compose restart rust-app
-
Test interactively:
docker run -it rust-backend:latest
-
Debug inside the container:
docker run -it --entrypoint /bin/bash rust-backend:latest