使用 docker 持久化 mysql 数据库

Persisting mysql database with docker

我正在尝试使用 Docker 将 Python 脚本和 MySQL 数据库容器化。 python 脚本使用 TCP 连接与主机上的程序 运行 交互,因此我为 Docker 容器设置了一个“主机”网络以允许这样做。 python 脚本目前正在与主机上的程序正常通信(TCP 通信符合预期)。 python 脚本也与另一个容器中的 MySQL 数据库 运行 通信正常(没有来自 pymysql 的错误)。当我使用 Docker 桌面 CLI 界面时,随着 python 代码将信息推送到表中,我可以看到数据库容器上 /var/lib/mysql/donuts/*.ibd 中文件的时间戳正在更新。

但是,我的问题是,当我使用 docker compose down 关闭两个容器然后使用 docker compose up 再次启动它们时,数据库中的信息不会持久存在。实际上,如果我使用 CLI 使用 mysql -u donuts 进入数据库容器,然后在容器为 运行 时尝试手动检查表,两个表都是空的。我一直在兜圈子,试图找出为什么我看不到表中的数据,即使我看到 /var/lib/mysql/donuts/*.ibd 中的文件在 Python 容器正在插入行的同一实例中更新。当容器 运行 时,数据被存储在某个地方,至少是暂时的,因为 python 容器正在从其中一个表中读取并在容器处于活动状态时使用该信息。

下面是我的 Dockerfiledocker-compose.yml 文件,整个项目都可以找到 here. The python code that interacts with the database is here,但我认为问题一定出在 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 && \
    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

当然,一旦我 post 我就找到了答案。我的数据库连接上下文管理器缺少 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()