Постоянная база данных mysql с докером

#python #mysql #docker #docker-compose #mysql-python

Вопрос:

Я пытаюсь вместить скрипт Python и базу данных MySQL с помощью Docker. Скрипт python взаимодействует с программой, запущенной на хост-машине, используя TCP-соединение, поэтому я настроил сеть «хост» для контейнеров Docker, чтобы разрешить это. Скрипт python в настоящее время нормально разговаривает с программой на хост-машине (TCP-связь, как и ожидалось). Скрипт python также взаимодействует с базой данных MySQL, работающей в другом контейнере, нормально (никаких ошибок со стороны pymysql). Когда я использую интерфейс Docker Desktop CLI, я вижу временные метки в файлах в /var/lib/mysql/donuts/*.ibd контейнере базы данных, обновляющихся по мере того, как код python вводит информацию в таблицы.

Однако моя проблема заключается в том, что, когда я опускаю оба контейнера docker compose down , а затем снова поднимаю их docker compose up , информация в базе данных не сохраняется. На самом деле, если я войду в контейнер базы данных с помощью интерфейса командной mysql -u donuts строки, а затем попытаюсь вручную проверить таблицы во время работы контейнеров, обе таблицы будут полностью пустыми. Я ходил по кругу, пытаясь выяснить, почему я не могу видеть данные в таблицах, хотя вижу файлы в /var/lib/mysql/donuts/*.ibd обновлении в том же экземпляре, в который контейнер Python вставляет строки. Данные хранятся где-то во время работы контейнеров, по крайней мере временно, так как контейнер python считывает данные из одной из таблиц и использует эту информацию, пока контейнеры живы.

Ниже приведены мои Dockerfile файлы и docker-compose.yml файлы, и весь проект можно найти здесь. Код python, который взаимодействует с базой данных, находится здесь, но я думаю, что проблема должна быть в настройке Docker, а не в коде Python.

Любые советы по сохранению базы данных были бы очень признательны, спасибо.

 version: '3.1'

services:
  db:
    image: mysql:8.0.25
    container_name: db
    restart: always
    secrets:
      - mysql_root
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root
      MYSQL_DATABASE: donuts
    volumes:
      - mysql-data:/var/lib/mysql
      - ./mysql-init.sql:/docker-entrypoint-initdb.d/mysql-init.sql
    network_mode: "host"

  voyager_donuts:
    container_name: voyager_donuts
    build:
      context: .
      dockerfile: Dockerfile
    image: voyager_donuts
    network_mode: "host"
    volumes:
      - c:/Users/user/Documents/Voyager/DonutsCalibration:/voyager_calibration
      - c:/Users/user/Documents/Voyager/DonutsLog:/voyager_log
      - c:/Users/user/Documents/Voyager/DonutsData:/voyager_data
      - c:/Users/user/Documents/Voyager/DonutsReference:/voyager_reference

volumes:
  mysql-data:

secrets:
  mysql_root:
    file: ./secrets/mysql_root
 
 # get a basic python image
FROM python:3.9-slim-buster

# set up Tini to hand zombie processes etc
ENV TINI_VERSION="v0.19.0"
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod  x /tini

# keep setup tools up to date
RUN pip install -U 
    pip 
    setuptools 
    wheel

# set a working directory
WORKDIR /donuts

# make a new user
RUN useradd -m -r donuts amp;amp; 
    chown donuts /donuts

# install requirements first to help with caching
COPY requirements.txt ./
RUN pip install -r requirements.txt

# copy from current dir to workdir
COPY . .

# stop things running as root
USER donuts

# add entry points
ENTRYPOINT ["/tini", "--"]

# start the code once the container is running
CMD python voyager_donuts.py
 

Ответ №1:

И, конечно, как только я опубликую это, я найду ответ. В моем диспетчере контекста подключения к базе данных отсутствовала commit() строка. Ле вздох, я потратил гораздо больше времени, чем хотел бы признать, на то, чтобы разобраться в этом…

 @contextmanager
def db_cursor(host='127.0.0.1', port=3306, user='donuts',
              password='', db='donuts'):
    """
    Grab a database cursor
    """
    with pymysql.connect(host=host, 
                         port=port, 
                         user=user, 
                         password=password, 
                         db=db) as conn:
        with conn.cursor() as cur:
            yield cur
 

должно было быть:

 @contextmanager
def db_cursor(host='127.0.0.1', port=3306, user='donuts',
              password='', db='donuts'):
    """
    Grab a database cursor
    """
    with pymysql.connect(host=host, 
                         port=port, 
                         user=user, 
                         password=password, 
                         db=db) as conn:
        with conn.cursor() as cur:
            yield cur
        conn.commit()