Skip to content

S3 (Object Storage) Provider

The S3 provider requires the [s3] extra to be installed. It uses RustFS by default -- a fully S3-compatible, Apache 2.0 licensed storage server.

Why RustFS instead of MinIO?

MinIO's open-source repository was archived in February 2026. Docker images and pre-built binaries are no longer published. RustFS is API-compatible and uses the same port conventions (9000/9001), making migration seamless.

Installation

pip install django-testcontainers-plus[s3]

This installs boto3, which is used for bucket creation and is typically already present in projects using django-storages.

Auto-Detection

The provider activates automatically from any of these settings:

Setting Detected when
STORAGES[*]['BACKEND'] Contains s3boto3
DEFAULT_FILE_STORAGE Contains s3boto3
AWS_STORAGE_BUCKET_NAME Present and non-empty

Minimal Setup

settings.py
TEST_RUNNER = 'django_testcontainers_plus.runner.TestcontainersRunner'

STORAGES = {
    'default': {
        'BACKEND': 'storages.backends.s3boto3.S3Boto3Storage',
    }
}

AWS_STORAGE_BUCKET_NAME = 'test-uploads'
settings.py
TEST_RUNNER = 'django_testcontainers_plus.runner.TestcontainersRunner'

DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_STORAGE_BUCKET_NAME = 'test-uploads'
settings.py
TEST_RUNNER = 'django_testcontainers_plus.runner.TestcontainersRunner'

STORAGES = {
    'default': {
        'BACKEND': 'storages.backends.s3boto3.S3Boto3Storage',
    },
    'staticfiles': {
        'BACKEND': 'storages.backends.s3boto3.S3StaticStorage',
    }
}

AWS_STORAGE_BUCKET_NAME = 'test-uploads'

A single S3 container serves both media and static files.

Default Container

Property Value
Image rustfs/rustfs
S3 API port Randomly assigned by Docker (maps to 9000)
Console port Randomly assigned by Docker (maps to 9001)
Access key rustfsadmin
Secret key rustfsadmin

Configuration Options

settings.py
TESTCONTAINERS = {
    's3': {
        'image': 'rustfs/rustfs',
        'access_key': 'rustfsadmin',         # used for boto3 + container auth
        'secret_key': 'rustfsadmin',
        'bucket_name': 'test-bucket',        # auto-created bucket
        'environment': {                     # extra container env vars
            'RUSTFS_CONSOLE_ENABLE': 'true',
        },
    }
}

Settings Injection

After the S3 container starts, the provider updates your settings automatically:

Setting Value
AWS_S3_ENDPOINT_URL http://{host}:{port} pointing to the container
AWS_ACCESS_KEY_ID Container access key (always overridden to match container)
AWS_SECRET_ACCESS_KEY Container secret key (always overridden to match container)
AWS_STORAGE_BUCKET_NAME Bucket name (only if not already set)
S3_CONSOLE_URL URL to the RustFS web console

The provider also auto-creates the bucket specified in AWS_STORAGE_BUCKET_NAME (or test-bucket by default).

Example Test

from django.core.files.base import ContentFile
from django.core.files.storage import default_storage


def test_file_upload():
    # RustFS container is automatically started and configured
    content = ContentFile(b"Test file content")
    path = default_storage.save('uploads/test.txt', content)

    assert default_storage.exists(path)
    assert default_storage.open(path).read() == b"Test file content"

    default_storage.delete(path)
    assert not default_storage.exists(path)