You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker部署Flask+MySQL的跨设备数据同步与本地访问问题

问题描述

我用Flask和MySQL开发自动签到系统,已将应用和数据库部署在Docker中,主电脑(MacOS)本地还运行着MySQL。现在遇到两个问题:

  • 两台电脑上的Docker MySQL数据不一致
  • 主电脑本地MySQL与Docker中MySQL数据不一致

需求:开发时能通过命令行查询和使用MySQL,同时解决数据同步问题。希望得到两种方案之一:

  1. Docker中跨设备持久化运行数据库的最佳方案
  2. 让其他设备及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/24
    
    (192.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设为主库,旧电脑的设为从库,配置自动同步:
    1. 主库配置:修改my.cnf,添加server-id=1、log-bin=mysql-bin,重启MySQL;创建复制用户并授予REPLICATION SLAVE权限。
    2. 从库配置:修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 22:15:01