pythondjangoamazon-s3localstackdjango-storage

EndpointConnectionError using Localstack with Django


I'm working on setting up Localstack in my Django app so we don't need to connect to S3 for local development. This is the relevant part of my docker-compose:

  app:
    build:
      context: .
      dockerfile: docker/app.Dockerfile
    command: >
      bash -c "poetry run python manage.py runserver_plus 0.0.0.0:8000 --reloader-type watchdog"
    ports:
      - 8000:8000
      - 5678:5678
    volumes:
      - .:/app
      - venv:/app/.venv
    depends_on:
      - db
      - celery
      - elasticsearch
      - localstack
    stdin_open: true
    tty: true
    networks:
      - proxynet

  localstack:
    container_name: localstack
    image: localstack/localstack
    ports:
      - '4566:4566'
    volumes:
      - ./localstack-data:/var/lib/localstack
      - /var/run/docker.sock:/var/run/docker.sock

And I have these settings in my settings.py file:

MEDIA_URL = "/media/"
MEDIA_ROOT = BASE_DIR("media")
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_DEFAULT_ACL = "private"
AWS_S3_ACCESS_KEY_ID = "local"
AWS_S3_SECRET_ACCESS_KEY = "local"
AWS_S3_ENDPOINT_URL = "http://localhost:4566"
AWS_STORAGE_BUCKET_NAME = "mybucket"

But no matter what I try, when I try to upload a file in my application, I get a botocore.exceptions.EndpointConnectionError: Could not connect to the endpoint URL: "http://localhost:4566/mybucket". This only happens when the request to S3 is made through the Django request/response cycle, because I have a few scripts I wrote that are working fine with localstack. For example:

#!/bin/bash

export AWS_ACCESS_KEY_ID=local
export AWS_SECRET_ACCESS_KEY=local
export AWS_DEFAULT_REGION=us-east-1

aws s3api create-bucket --bucket "$1" --endpoint-url http://localhost:4566

# Check if the bucket creation was successful
if [ $? -eq 0 ]; then
    echo "Bucket '$1' created successfully."
else
    echo "Failed to create bucket '$1'."
fi

I have tried using both http://localhost:4566 and http://localstack:4566 as my endpoint url, but I get the same ConnectionError either way. I even tried writing my own ultra-simplified version of the S3Boto3Storage class to see if the error was coming from somewhere in that code, but I still got the connection error. What am I missing?

Also, it's probably worth noting that we're on older versions of packages: Django 3.2.0 and django-storages 1.9.1


Solution

  • I was able to figure this out. Small mistake, I just forgot to include the networks argument for my localstack image, so my main app container wasn't able to access it. I added:

    networks:
      - proxynet
    

    to my localstack image and everything worked as it should.