Sergei_Erjemin
@Sergei_Erjemin
Улыбайся, будь самураем...

Как на MacOS правильно подключить Django к БД в Docker?

Приучаю себя к хорошему, заставляю себя перейти с Windows на macOS. Под окошками схема отработана, там надо всего-навсего поставить специально скомпилированный коннектор к БД (например, отсюда) и все работает. Но под macOS, хоть и прилетают коннекторы через PIP, выдаётся ошибка:
django.db.utils.OperationalError: (2002, "Can't connect to server on '192.168.1.ххх' (60)")
...

Схема такая:

Docker Compose

Есть вот такой docker-compose.yml:
version: "3.0"
services:
  mariadb:
    container_name: MariaDB
    image: mariadb:10.7.6
    volumes:
      - "/Users/xxx/VM/docker-data/mariadb/data:/var/lib/mysql"
    environment:
      - "MYSQL_ROOT_PASSWORD=*****"
      - "MYSQL_ROOT_HOST=192.168.1.xxx"
    ports:
      - "3307:3306"
    command:
      --bind-address="0.0.0.0"
      --skip_ssl="true"
      --character-set-server="utf8"
      --collation-server="utf8_unicode_ci"

В docker через CLI создан внешний суперпользователь, база, пользователь базы, выданы права этому пользователю. Контейнер запущен. Через DataGrip к этой базе отлично коннектится, таблицы видны и все ок. С других машин в домашней сетки тоже коннектится (ведь база "светит" на внешний адрес по порту 3307).

Установка коннектора на macOS

Само собой по PIP просто так коннектор не поставится. Нужно чтобы в системе был клиент БД. Не знаю, правильно ли делаю, но нагуглилось такое:
# устанавливаю коннектор
brew install mariadb-connector-c

# симлинк конфиг-файла, в каталог, где его будет искать python-коннектор 
sudo ln -s /usr/local/opt/mariadb-connector-c/bin/mariadb_config /usr/local/bin/mysql_config

# активируем виртуальное окружение, ставим коннектор
source ~/path-to-project-enveroment/bin/activate
pip install mysqlclient

# выключаем окружение, удаляем симлинк и отключаем системный коннектор (можно этого и не делать)
deactivate
sudo rm /usr/local/bin/mysql_config
brew unlink mariadb-connector-c

Python-коннектор базы данных стоит и даже притащил зависимость:
mysql-connector-python==8.0.31
mysqlclient==2.1.1

Под окошками, когда коннектор стоит, уже все работает. Но не под macOS. Само собой проверил-перепроверил настройки БД в Django (собственно по ошибке видно, что пытается коннектится по верному IP БД):
import socket
from prj.my_secret import MY_DATABASE_HOST_DEV1, MY_DATABASE_HOST_DEV2, MY_DATABASE_PORT_DEV, MY_DATABASE_NAME_DEV, MY_DATABASE_USER_DEV, MY_DATABASE_PASSWORD_DEV, MY_HOST_HOME1

DATABASES = {
        'default': {
        'ENGINE': "django.db.backends.mysql",
        'HOST': MY_DATABASE_HOST_DEV1 if socket.gethostname() == MY_HOST_HOME1 else MY_DATABASE_HOST_DEV2,
        'PORT': MY_DATABASE_PORT_DEV,  
        'NAME': MY_DATABASE_NAME_DEV,  
        'USER': MY_DATABASE_USER_DEV,  
        'PASSWORD': MY_DATABASE_PASSWORD_DEV,  
        # 'OPTIONS': { 'autocommit': True, }
    }
}


Что делать? Почему?? Что за грабли с macOS?

P.S. macOS Monterey 12.6, процессор M1 (UPD: macOS Ventura 13.0,).
  • Вопрос задан
  • 175 просмотров
Решения вопроса 1
Sergei_Erjemin
@Sergei_Erjemin Автор вопроса
Улыбайся, будь самураем...
Пока разбирался, проделал несколько итерация установить/удалить/переустановить (примерно час заняло) -- поэтому не могу сказать, что конкретно сработало. Выводы такие:
  • mysql-connector-python -- не нужен. Похоже именно он вставал колом, и не давал коннекта в базу данных. Похоже, что его притащило в виртуальное окружение во время предыдущих экспериментов, и я его принял за зависимость..
  • симлинки не нужны -- mysqlclient отлично находит сокет базы.

В результате последовательность действий:
brew install mariadb-connector-c
source ~/path-to-project-enveroment/bin/activate
pip install mysqlclient

# выключаем окружение отключаем системный коннектор (можно не делать)
deactivate
brew unlink mariadb-connector-c

После обновления macOS до 13.0 Ventura потребуется предварительно сделать команду:
xcode-select --install
И повторить все еще один раз.

P.S. Отдельную проблему создает то, что имя хоста на macOS может меняться. У меня код в Django проверяет на каком хосте запущен и подставляет соответствующие настройки в settings.py ... В моем случае, в hostname прописано m1, но проверка через Python показывает:
import socket
socket.gethostname()
'm1.N1'

Догадки, но кажется добавление N1 как-то связано с моделью домашнего интернет-роутера... Почему macOS его добавляет, а другие компы в сети нет -- загадка. Иногда hostname может становится 'm1.local' (и для этого не надо перезагружаться, достаточно просто чтоб компьютер перешел в режим сна... хотя х.з. ... в macOS гибридный режим сна, и если во время сна перегружается по питанию, внешне это никак не заметно). В общем, это странное поведение hostname тоже попортило немного крови. :)
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@Drno
Лично мое мнение.
Такие вещи проще всего ставить в среде, для которых они создавались.
Ставим виртуалку с Ubuntu, ставим внутрь всё что надо
Ответ написан
@maksam07
Приучаю себя к хорошему
переходите на линукс.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы