Skip to content

parhamdavari/BucketBridge

Repository files navigation

BucketBridge

Docker Image GitHub Container Registry

Minimal FastAPI bridge to a private MinIO bucket. Provides upload, download, delete, and health endpoints while keeping MinIO off the public network.

Highlights

  • Docker Compose stack with MinIO, bootstrapper, and FastAPI app
  • Streamed uploads/downloads so large files do not exhaust memory
  • Presigned upload/download endpoints for direct browser access to the object store
  • Opinionated bootstrap script that creates the bucket, user, and policy on startup
  • Container healthchecks and startup retries to ensure MinIO is ready before serving traffic

Prerequisites

  • Docker + Docker Compose v2
  • Copy of the repo and permission to run containers locally

Quick Start

cp .env.example .env
# Update credentials if needed, then:
docker compose up -d --build

The API becomes available at http://localhost:8080 (or the port set in APP_PORT) once the bootstrap container finishes.

Configuration

Environment variables are read from .env by Docker Compose.

Variable Purpose
MINIO_ROOT_USER, MINIO_ROOT_PASSWORD Admin credentials used by the MinIO server and bootstrap container
MINIO_BUCKET Bucket created at startup and used by the app
OMS_ACCESS_KEY, OMS_SECRET_KEY Application user with RW access to the bucket
S3_REGION Region name passed to the AWS SDK (defaults to us-east-1)
APP_PORT Port exposed by FastAPI inside the container (default 8080)

Services

  • minio: MinIO server on an internal Docker network; console exposed at http://localhost:9001
  • minio-init: One-shot container that waits for MinIO, then provisions the bucket, IAM policy, and app user
  • app: FastAPI service exposing the REST API on http://localhost:8080

API Reference

Base URL: http://localhost:8080

Method Path Description
POST /files/upload Multipart upload; optional key query parameter to override filename
GET /files/{key} Stream file download
DELETE /files/{key} Remove object from bucket
GET /files/{key}/metadata Return metadata (length, type, etag, last modified) without streaming the object
POST /files/presign-upload Generate a presigned PUT URL so clients can upload directly to MinIO
POST /files/presign-download Generate a presigned GET URL for direct downloads
GET /health Verifies connectivity to MinIO

Example Requests

# Upload a file
curl -F "file=@README.md" http://localhost:8080/files/upload

# Download the same file
curl -o README.copy.md http://localhost:8080/files/README.md

# Remove it again
curl -X DELETE http://localhost:8080/files/README.md

# Inspect metadata without downloading
curl http://localhost:8080/files/README.md/metadata

# Request an upload URL that expires in 15 minutes
curl \
  -X POST http://localhost:8080/files/presign-upload \
  -H 'Content-Type: application/json' \
  -d '{
        "key": "uploads/example.txt",
        "content_type": "text/plain",
        "content_length": 1024,
        "expires_in": 900
      }'

Presigned URL Notes

  • Presigned URLs embed the S3_ENDPOINT host. Ensure that value points to a hostname or load balancer reachable by any client that consumes the URL (for example https://storage.example.com).
  • If you prefer to keep MinIO private, skip the presigned endpoints and keep using the streaming upload/download routes instead.
  • Clients must send the headers included in the presign response verbatim; otherwise MinIO will reject the request.

Access Control Strategy

  • Treat BucketBridge as an internal utility service. Expose the presign endpoints from your primary API (where business logic and authentication already live), then have that API call the wrapper over the private Docker network.
  • By routing presign requests through the main API, you can reuse your existing AAA mechanisms, attach business rules (ownership checks, rate limits, audit logging), and prevent untrusted callers from talking to the wrapper directly.
  • If you must expose the wrapper externally, secure it like any public API: verify JWTs on every request, restrict credentials to the least privilege required, and apply network-level controls (e.g., reverse proxy ACLs or service mesh policies).

Development Notes

  • App source lives in app/main.py; S3 helper in app/s3wrap.py
  • Python dependencies defined in app/requirements.txt
  • init/bootstrap.sh contains the provisioning logic for the MinIO user and bucket

Deployment with Pre-built Image

Instead of building locally, you can use the pre-built multi-architecture image from GitHub Container Registry:

# Pull the latest image (supports amd64 and arm64)
docker pull ghcr.io/parhamdavari/bucketbridge:latest

# Or pull a specific version
docker pull ghcr.io/parhamdavari/bucketbridge:v1.0.0

Update your docker-compose.yml to use the pre-built image:

app:
  image: ghcr.io/parhamdavari/bucketbridge:latest
  # Remove the 'build: ./app' line
  depends_on:
    minio:
      condition: service_healthy
    minio-init:
      condition: service_completed_successfully
  environment:
    # ... your S3 configuration

Shutdown

Stop the stack with docker compose down. To remove MinIO data as well, add the -v flag.

About

Unified FastAPI bridge for S3-compatible object storage with streaming and presigned URLs.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors