Using Minio with django-storages

Using Minio with django-storages

·

2 min read

TL;DR Here's the example code on github: github.com/naomiaro/django-minio-storage

This post assumes that you've added a host entry for minio to /etc/hosts

127.0.0.1   minio

Recently while working on an application for the BC Public Service, I've tried configuring django-storages to be backed by a private Minio bucket rather than Amazon S3. Minio is API compatible with Amazon S3 cloud storage service, so we can use this point to our advantage when setting up django-storages backed by a minio bucket.

The settings passed to Django look as follows for django-storages:

# django-storages settings

DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"

MINIO_ACCESS_KEY = os.getenv("MINIO_ROOT_USER")
MINIO_SECRET_KEY = os.getenv("MINIO_ROOT_PASSWORD")
MINIO_BUCKET_NAME = os.getenv("MINIO_BUCKET_NAME")
MINIO_ENDPOINT = os.getenv("MINIO_ENDPOINT")

AWS_ACCESS_KEY_ID = MINIO_ACCESS_KEY
AWS_SECRET_ACCESS_KEY = MINIO_SECRET_KEY
AWS_STORAGE_BUCKET_NAME = MINIO_BUCKET_NAME
AWS_S3_ENDPOINT_URL = MINIO_ENDPOINT
AWS_DEFAULT_ACL = None
AWS_QUERYSTRING_AUTH = True
AWS_S3_FILE_OVERWRITE = False

Credentials from minio.env are passed via Docker so that they are available as environment variables.

**Note that these credentials are just default local development settings, don't store any secrets in github.

Let's take a closer look at the projects' development docker-compose.yml file.

minio:
    image: minio/minio
    hostname: "minio"
    volumes:
      - ./minio:/minio_files
    env_file:
      - minio.env
    command: 'minio server /minio_files --console-address ":9001"'
    ports:
      - 9000:9000
      - 9001:9001

The minio service starts the Minio server for local dev. The volume will mount any uploaded files back into the local minio folder so the contents can be seen if needed.

createbuckets:
    image: minio/mc
    depends_on:
      - minio
    env_file:
      - minio.env
    entrypoint: >
      /bin/sh -c "
      /usr/bin/mc config host add myminio http://minio:9000 minioadmin minioadmin;
      /usr/bin/mc mb --quiet myminio/photos;
      /usr/bin/mc policy set none myminio/photos;
      "

The createbuckets service uses the Minio client to setup configuration and create a private bucket (policy set to none). If you want to view the bucket via the Minio console, it's available at http://minio:9000 with user/pass minioadmin/minioadmin

The demo Django project code on github includes a Django app photos which defines a single model Record. The record contains a photo uploaded to our private bucket by using a model ImageField.

photo = models.ImageField(upload_to="docs")

The method photo_tag creates an image tag which can be rendered on our admin panel page directly.

def photo_tag(self):
        return mark_safe(
            '<img src="%s" width="600" />'
            % (media_storage.url(name=self.photo.file.name))
        )

Because the bucket is private and we have setting AWS_QUERYSTRING_AUTH = True, Minio will generate a signed url for secure access to load and display our image. Links are valid for one hour by default. Look into adjusting setting AWS_QUERYSTRING_EXPIRE if one hour is not suitable.

http://minio:9000/photos/docs/IMG_20190628_203544.jpg?AWSAccessKeyId=minioadmin&Signature=l08S%2BWA7qzguBFl6FfUtcGSn%2Ftc%3D&Expires=1651646316

The admin panel nicely displays the photo inline below thanks to jazzmin and our photo_tag method on our Record model.

Screenshot 2022-05-03 at 22.51.55.png

Did you find this article valuable?

Support Naomi by becoming a sponsor. Any amount is appreciated!