mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3
297 words
1 minute
MinIO with NestJS

Summary#

Recently, I was developing an API with NestJS and needed to find a way to upload and serve static files (assets) --- such as images, documents, and other files --- in a secure and practical way.

After doing a quick search using GPT, I decided to use MinIO, which is an object storage solution compatible with the AWS S3 protocol, but that runs locally (or anywhere) via Docker.

In this post, I’ll share how I organized the project, the configuration using Docker Compose, and how I integrated the API with MinIO to upload files and make them publicly accessible via URL.

Docker#

The project runs in Docker containers, orchestrated by Docker Compose, with the following main services:

  • api: NestJS backend, exposed on port 5400
  • minio: object storage server (S3-compatible), on ports 9000 (API) and 9001 (web console)
  • postgres: PostgreSQL database for persistence
  • redis: cache and session store
  • minio-init: special container used to initialize buckets and define policies in MinIO using mc (MinIO client)
services:
api:
build:
context: .
dockerfile: ./Dockerfile
ports:
- "5400:5400"
env_file:
- ./.env.production
depends_on:
postgres:
condition: service_healthy
minio:
condition: service_started
minio:
image: quay.io/minio/minio:latest
command: server /data --console-address ":9001"
ports:
- "9000:9000"
- "9001:9001"
env_file:
- ./.env.production
volumes:
- minio_data:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/ready"]
interval: 5s
timeout: 3s
retries: 10
minio-init:
image: minio/mc
depends_on:
minio:
condition: service_healthy
entrypoint: >
/bin/sh -c "
mc alias set local http://minio:9000 $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD &&
mc mb -p local/$S3_BUCKET || true &&
mc mb -p local/posts || true &&
mc anonymous set download local/$S3_BUCKET &&
mc anonymous set download local/posts
"
env_file:
- ./.env.production
volumes:
minio_data:
  • MinIO runs with the web console available at http://localhost:9001, where you can view and manage buckets.
  • The minio-init container runs after MinIO becomes healthy and executes commands using the mc client to:
    • Create the buckets defined in the $S3_BUCKET variable and the posts bucket.
    • Set those buckets as public for anonymous download (meaning anyone can view and download the files).

The command used in the docker-compose file for the minio-init container:

mc anonymous set download local/$S3_BUCKET
mc anonymous set download local/posts

Sets the buckets as publicly accessible for anonymous download, allowing anyone to access the files directly via URL.

The public URL to access a file is:

http://localhost:9000/<bucket>/<file-name>

For example:

http://localhost:9000/posts/foto.png

Service#

Example of the service that handles the integration using the @aws-sdk/client-s3 package:

// (service implementation omitted for brevity – use your original TypeScript code here)

Source#

If you’d like to see the complete backend code, including the full setup and integrations, it’s available on my GitHub:
👉 https://github.com/nathan2slime/apl-atani

Share

If this article helped you, please share it with others!

Some information may be outdated