Storing and retrieving files in modern applications is a must-have feature. With FastAPI’s performance and simplicity, paired with MinIO’s lightweight, S3-compatible object storage, you have a powerful stack for building scalable, file-heavy applications. In this tutorial, we’ll walk through how to integrate FastAPI with MinIO, fully containerized using Docker Compose.
What You’ll Learn
- What MinIO is and why it’s useful
- How to configure a Docker Compose environment for FastAPI and MinIO
- How to upload and retrieve files from MinIO using FastAPI
- Using the
boto3
library to interact with MinIO
What is MinIO?
MinIO is a high-performance, Kubernetes-native object storage system that’s compatible with Amazon S3 APIs. It allows developers to self-host S3-like storage, perfect for local development and private deployments.
Project Structure
fastapi-minio/
├── app/
│ ├── main.py
│ └── minio_client.py
├── .env
├── Dockerfile
├── docker-compose.yml
└── requirements.txt
Step 1: Docker Compose Setup
services:
app:
build: .
container_name: app
ports:
- "8000:8000"
environment:
MINIO_ENDPOINT: minio:9000
MINIO_ACCESS_KEY: admin123
MINIO_SECRET_KEY: admin123
depends_on:
- minio
minio:
image: minio/minio
container_name: minio
environment:
MINIO_ROOT_USER: admin123
MINIO_ROOT_PASSWORD: admin123
volumes:
- minio_data:/data
ports:
- "9000:9000"
- "9001:9001"
command: server --console-address ":9001" /data
volumes:
minio_data:
Step 2: FastAPI Application main.py
In main.py file put these codes:
from fastapi import FastAPI, UploadFile, File, HTTPException
from app.minio_client import create_bucket, upload_to_minio, download_from_minio
app = FastAPI()
BUCKET_NAME = "mybucket"
@app.on_event("startup")
async def startup_event():
create_bucket(BUCKET_NAME)
@app.post("/upload")
async def upload(file: UploadFile = File(...)):
result = upload_to_minio(file, BUCKET_NAME)
if result:
return {"message": "Upload successful", "filename": file.filename}
raise HTTPException(status_code=500, detail="Upload failed")
@app.get("/download/{filename}")
async def download(filename: str):
content = download_from_minio(filename, BUCKET_NAME)
if content:
return content
raise HTTPException(status_code=404, detail="File not found")
Step 4: FastAPI Application minio_client.py
import os
import io
import boto3
from botocore.exceptions import ClientError
from fastapi.responses import StreamingResponse
MINIO_ENDPOINT = os.getenv("MINIO_ENDPOINT", "minio:9000")
MINIO_ACCESS_KEY = os.getenv("MINIO_ACCESS_KEY", "minioadmin")
MINIO_SECRET_KEY = os.getenv("MINIO_SECRET_KEY", "minioadmin123")
s3 = boto3.client(
"s3",
endpoint_url=f"http://{MINIO_ENDPOINT}",
aws_access_key_id=MINIO_ACCESS_KEY,
aws_secret_access_key=MINIO_SECRET_KEY,
region_name="us-east-1"
)
def create_bucket(bucket_name):
try:
s3.head_bucket(Bucket=bucket_name)
except ClientError:
s3.create_bucket(Bucket=bucket_name)
def upload_to_minio(file, bucket_name):
try:
s3.upload_fileobj(file.file, bucket_name, file.filename)
return True
except ClientError as e:
print(e)
return False
def download_from_minio(filename, bucket_name):
try:
fileobj = io.BytesIO()
s3.download_fileobj(bucket_name, filename, fileobj)
fileobj.seek(0)
return StreamingResponse(fileobj, media_type="application/octet-stream")
except ClientError as e:
print(e)
return None
Step 5: Dockerfile for FastAPI
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY ./app ./app
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Step 6: requirements.txt
fastapi
uvicorn
boto3
python-multipart
Step 7: Running the project
docker compose up --build -d
Step 8: Testing the project
Since we are using FastAPI we don’t need any API Testing Client as we have access to Swagger in this address:
http://localhost:8000/doc

Click on “upload” api and click on “Try it out”, upload a file you will see that it gets succeeded.
For download you can click on “download” api and put the name of the file in the field and just run and you will see that you get a “download” button to download the file.
By the way the source code of project is here:
Leave a Reply