使用 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 容器正在从其中一个表中读取并在容器处于活动状态时使用该信息。
下面是我的 Dockerfile
和 docker-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()
我正在尝试使用 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 容器正在从其中一个表中读取并在容器处于活动状态时使用该信息。
下面是我的 Dockerfile
和 docker-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()