Docker部署Flask+MySQL的跨设备数据同步与本地访问问题
问题描述
我用Flask和MySQL开发自动签到系统,已将应用和数据库部署在Docker中,主电脑(MacOS)本地还运行着MySQL。现在遇到两个问题:
- 两台电脑上的Docker MySQL数据不一致
- 主电脑本地MySQL与Docker中MySQL数据不一致
需求:开发时能通过命令行查询和使用MySQL,同时解决数据同步问题。希望得到两种方案之一:
- Docker中跨设备持久化运行数据库的最佳方案
- 让其他设备及Docker容器访问主电脑本地MySQL的方法
当前我的compose.yaml和Dockerfile如下:
compose.yaml
services: server: build: context: . ports: - 8000:8000 environment: - SQL_PASS=/run/secrets/db-password - MYSQL_ROOT_PASSWORD=/run/secrets/db-password - TWILIO_ACCOUNT_SID=/run/secrets/twilio-sid - TWILIO_AUTH_TOKEN=/run/secrets/twilio-token depends_on: db: condition: service_healthy secrets: - db-password - twilio-sid - twilio-token db: # We use a mariadb image which supports both amd64 & arm64 architecture #image: mariadb:10-focal # If you really want to use MySQL, uncomment the following line image: mysql:8 restart: always healthcheck: test: ['CMD-SHELL', 'mysqladmin ping -h 127.0.0.1 --password="$$(cat /run/secrets/db-password)" --silent'] interval: 3s retries: 5 start_period: 30s secrets: - db-password volumes: - /usr/local/mysql/data/callassure:/db-data - type: bind source: ./initial-data target: /docker-entrypoint-initdb.d/ environment: - MYSQL_DATABASE=callassure - MYSQL_USER=mysql - MYSQL_ROOT_PASSWORD=/run/secrets/db-password - MYSQL_PASSWORD=/run/secrets/db-password expose: - 3306 - 33060 volumes: db-data: secrets: db-password: file: db/password.txt twilio-sid: file: db/sid.txt twilio-token: file: db/auth.txt
Dockerfile
# syntax=docker/dockerfile:1 # Comments are provided throughout this file to help you get started. # If you need more help, visit the Dockerfile reference guide at # https://docs.docker.com/go/dockerfile-reference/ # Want to help us make this template better? Share your feedback here: https://forms.gle/ybq9Krt8jtBL3iCk7 ARG PYTHON_VERSION=3.9.6 FROM python:${PYTHON_VERSION}-slim as base # Prevents Python from writing pyc files. ENV PYTHONDONTWRITEBYTECODE=1 # Keeps Python from buffering stdout and stderr to avoid situations where # the application crashes without emitting any logs due to buffering. ENV PYTHONUNBUFFERED=1 WORKDIR /app # Install required system packages RUN apt-get update && apt-get install -y \ gcc \ default-libmysqlclient-dev \ build-essential \ pkg-config \ && rm -rf /var/lib/apt/lists/* # Create a non-privileged user that the app will run under. # See https://docs.docker.com/go/dockerfile-user-best-practices/ ARG UID=10001 RUN adduser \ --disabled-password \ --gecos "" \ --home "/nonexistent" \ --shell "/sbin/nologin" \ --no-create-home \ --uid "${UID}" \ appuser # Download dependencies as a separate step to take advantage of Docker's caching. # Leverage a cache mount to /root/.cache/pip to speed up subsequent builds. # Leverage a bind mount to requirements.txt to avoid having to copy them into # into this layer. RUN --mount=type=cache,target=/root/.cache/pip \ --mount=type=bind,source=requirements.txt,target=requirements.txt \ python -m pip install -r requirements.txt # Switch to the non-privileged user to run the application. USER appuser # Copy the source code into the container. COPY . . # Expose the port that the application listens on. EXPOSE 8000 # Run the application. CMD ["flask", "run", "-h", "0.0.0.0", "-p", "8000"]
解决方案
方案一:让其他设备及Docker容器访问主电脑本地MySQL
1. 配置本地MySQL允许远程访问
- 找到MySQL配置文件(MacOS下通常是
/usr/local/etc/my.cnf或~/Library/Application Support/com.oracle.oss.mysql.mysqld/my.cnf),修改bind-address为0.0.0.0(或注释掉该行,允许所有IP连接)。 - 重启MySQL服务:
brew services restart mysql(如果是通过Homebrew安装的)。
2. 创建远程访问用户
- 登录本地MySQL:
mysql -u root -p - 执行以下命令创建用户并授权(密码需与你的
db-password.txt一致):CREATE USER 'mysql'@'%' IDENTIFIED BY '你的数据库密码'; GRANT ALL PRIVILEGES ON callassure.* TO 'mysql'@'%'; FLUSH PRIVILEGES;
3. 开放MacOS防火墙端口
- 打开「系统设置」→「网络」→「防火墙」→「防火墙选项」,添加MySQL应用,允许传入连接;或直接开放3306端口。
4. 修改Docker Compose配置
- 移除或注释掉
db服务,修改server服务的环境变量,指向主电脑本地MySQL:services: server: # 其他配置不变 environment: - SQL_HOST=host.docker.internal # 主电脑上的Docker容器用这个地址访问本地MySQL # 其他设备上的Docker容器用主电脑的局域网IP,比如192.168.1.100 - SQL_USER=mysql - SQL_PASS=/run/secrets/db-password - TWILIO_ACCOUNT_SID=/run/secrets/twilio-sid - TWILIO_AUTH_TOKEN=/run/secrets/twilio-token # 移除depends_on中对db的依赖
方案二:跨设备持久化Docker数据库(解决多设备数据一致)
先修正当前Compose的错误
你的db服务中,volumes挂载的/usr/local/mysql/data/callassure:/db-data是错误的——官方MySQL镜像默认将数据存储在/var/lib/mysql,所以应该改为:
volumes: - /usr/local/mysql/data/callassure:/var/lib/mysql - type: bind source: ./initial-data target: /docker-entrypoint-initdb.d/
否则容器内的MySQL不会使用你挂载的目录,数据实际存在匿名卷中,这也是数据不一致的原因之一。
1. 使用NFS共享存储(推荐)
主电脑搭建NFS服务器
- 编辑
/etc/exports文件,添加:
(/usr/local/mysql/data/callassure -alldirs -mapall=你的UID:你的GID 192.168.x.0/24192.168.x.0/24替换为你的局域网网段,你的UID:你的GID可通过id命令查看) - 重启NFS服务:
sudo nfsd restart
所有设备的Docker Compose配置
修改db服务的volumes为NFS挂载:
volumes: - type: nfs source: nfs://主电脑局域网IP/usr/local/mysql/data/callassure target: /var/lib/mysql - type: bind source: ./initial-data target: /docker-entrypoint-initdb.d/
这样所有设备的Docker MySQL都会读写同一个NFS共享目录,保证数据一致。
2. MySQL主从复制
- 将主电脑的Docker MySQL设为主库,旧电脑的设为从库,配置自动同步:
- 主库配置:修改
my.cnf,添加server-id=1、log-bin=mysql-bin,重启MySQL;创建复制用户并授予REPLICATION SLAVE权限。 - 从库配置:修改
my.cnf,添加server-id=2,重启MySQL;执行CHANGE MASTER TO命令指向主库,启动同步:CHANGE MASTER TO MASTER_HOST='主电脑局域网IP', MASTER_USER='复制用户名', MASTER_PASSWORD='复制用户密码', MASTER_LOG_FILE='主库binlog文件名', MASTER_LOG_POS=主库binlog位置; START SLAVE;
- 主库配置:修改
内容的提问来源于stack exchange,提问作者irishcomputing
相关产品推荐
相关产品推荐

