Как я могу заставить приложение Django подключиться к серверу minio, когда оба находятся за прокси-сервером nginx и внутри отдельных контейнеров docker?

Гол

Доступ к серверу minio через поддомен с сервера Django в среде docker (и сервер minio, и сервер Django находятся за прокси-сервером nginx)

Ожидаемый результат: Django может получить доступ к серверу minio, используя поддомен, указанный в nginx.

Я могу успешно открыть консоль minio через s3-console.localhost

Проблема

Служба Django не может правильно подключиться. Журналы Docker:

Context

nginx.config

user  nginx;
events {
  worker_connections   1000;
}

http {
  server {
    server_name api.lamanin.com api.localhost;
    location / {
      proxy_pass http://api:8000;
    }
  }
  server {
    server_name s3.lamanin.com s3.localhost;
    listen 80;
    location / {
       proxy_pass http://s3:9000;
       proxy_http_version 1.1;
       proxy_set_header Host $host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto $scheme;
    }
  }
  server {
    server_name s3-console.lamanin.com s3-console.localhost;
    listen 80;
    location / {
      proxy_pass http://s3:9090;
    }
  }
  server {
    server_name lamanin.com *.lamanin.com localhost *.localhost;
    listen 80;

    location / {
      proxy_pass http://web:3000;
    }
    
    location /ws {
      proxy_pass http://web:3000;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "Upgrade";
    }
  }
}

docker-compose.yml

version: "3.8"

services:
  s3:
    image: minio/minio
    container_name: s3
    restart: on-failure
    ports:
      - "9000:9000"
      - "9090:9090"
    volumes:
      - s3:/data
    environment:
      - MINIO_ROOT_USER=${MINIO_ROOT_USER}
      - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
    command: server --console-address :9090 --address :9000 /data
  web:
    image: lamanin/web
    container_name: web
    environment:
      - WDS_SOCKET_PORT=${WDS_SOCKET_PORT}
      - ESLINT_NO_DEV_ERRORS=${ESLINT_NO_DEV_ERRORS}
      - REACT_APP_API_URL=${REACT_APP_API_URL}
      - REACT_APP_SHOW_COMING_SOON=${REACT_APP_SHOW_COMING_SOON}
    build:
      context: ./web
      dockerfile: Dockerfile.${ENVIRONMENT}
    restart: on-failure
    volumes:
      - web:/app/src
    ports:
      - "${WEB_PORT}"
    depends_on:
      - api
  db:
    image: postgres
    container_name: "db"
    hostname: "db"
    volumes:
      - db:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=${POSTGRES_DB}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
  api:
    image: lamanin/api
    environment:
      - SECRET_KEY=${SECRET_KEY}
      - POSTGRES_DB=${POSTGRES_DB}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - DJANGO_SUPERUSER_USERNAME=${DJANGO_SUPERUSER_USERNAME}
      - DJANGO_SUPERUSER_PASSWORD=${DJANGO_SUPERUSER_PASSWORD}
      - MINIO_URL=${MINIO_URL}
      - MINIO_DOMAIN=${MINIO_DOMAIN}
      - MINIO_SA_ACCESS_KEY=${MINIO_SA_ACCESS_KEY}
      - MINIO_SA_SECRET_KEY=${MINIO_SA_SECRET_KEY}
      - API_URL=${API_URL}
    container_name: api
    build:
      context: ./api
    restart: on-failure
    command: >
      sh -c "sleep 10 && python3 manage.py collectstatic --no-input &&
            python3 manage.py migrate &&
            python3 manage.py ensure_admin &&
            python3 manage.py runserver 0.0.0.0:8000"
    volumes:
      - api:/code
    ports:
      - "${API_PORT}"
    depends_on:
      - db
      - s3
  nginx:
    build:
      context: .
      dockerfile: Dockerfile.nginx
    container_name: "nginx"
    restart: on-failure
    depends_on:
      - api
      - web
      - s3
    ports:
      - "80:80"

volumes:
  api:
  web:
  db:
  s3:

Соответствующие настройки Django

AWS_ACCESS_KEY_ID = os.getenv('MINIO_SA_ACCESS_KEY')
AWS_SECRET_ACCESS_KEY = os.getenv('MINIO_SA_SECRET_KEY')
AWS_STORAGE_BUCKET_NAME = 'main'
AWS_S3_ENDPOINT_URL = os.getenv('MINIO_URL')

AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=86400',
}

AWS_STATIC_LOCATION = 'static'
STATICFILES_STORAGE = 'ezevent_api.storage_backends.StaticStorage'
STATIC_URL = f'{AWS_S3_ENDPOINT_URL}/{AWS_STORAGE_BUCKET_NAME}/'

AWS_PUBLIC_MEDIA_LOCATION = 'media/public'
DEFAULT_FILE_STORAGE = 'ezevent_api.storage_backends.PublicMediaStorage'

AWS_PRIVATE_MEDIA_LOCATION = 'media/private'
PRIVATE_FILE_STORAGE = 'ezevent_api.storage_backends.PrivateMediaStorage'

client = Minio(
    os.getenv('MINIO_DOMAIN'),
    access_key=AWS_ACCESS_KEY_ID,
    secret_key=AWS_SECRET_ACCESS_KEY,
    secure=os.getenv('MINIO_SECURE') == 'True'
)

found = client.bucket_exists(AWS_STORAGE_BUCKET_NAME)
if not found: client.make_bucket(AWS_STORAGE_BUCKET_NAME)

Переменные окружения

MINIO_URL=http://s3.localhost
MINIO_DOMAIN=s3.localhost
MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=[REDACTED]
MINIO_SA_ACCESS_KEY=service-account-1
MINIO_SA_SECRET_KEY=[REDACTED]
MINIO_SECURE=False

Соответствующие пакеты

https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html

То, что я пробовал

  1. Изначально я не использовал никаких заголовков в настройках прокси, поэтому я добавил несколько заголовков, которые я нашел из этой темы на github: https://github.com/minio/minio/issues/7661.

  2. Я подозревал, что адрес http://s3:9000 не распознается nginx, поэтому я использовал http://localhost:9000, но локальный хост nginx, вероятно, отличается от сервиса s3, потому что они находятся в разных контейнерах.

  3. При запуске службы s3 & nginx с помощью docker, и запуске сервера Django вне docker (запуск вручную с помощью команды python manage.py runserver) он успешно подключается к серверу minio, если используется localhost:9000. Но терпит неудачу, если используется поддомен http://s3.localhost.

Вернуться на верх