【问题标题】:Docker-Compose persistent data MySQLDocker-Compose 持久数据 MySQL
【发布时间】:2017-01-03 15:38:17
【问题描述】:

如果我使用以下 .yml 运行 $ docker-compose down,我似乎无法让 MySQL 数据持久化

version: '2'
services:
  # other services

  data:
    container_name: flask_data
    image: mysql:latest
    volumes:
      - /var/lib/mysql
    command: "true"

  mysql:
    container_name: flask_mysql
    restart: always
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: 'test_pass' # TODO: Change this
      MYSQL_USER: 'test'
      MYSQL_PASS: 'pass'
    volumes_from:
      - data
    ports:
      - "3306:3306"

我的理解是,在我的data 容器中,使用volumes: - /var/lib/mysql 将其映射到我的本地机器目录,mysql 在该目录中将数据存储到容器中,并且由于这种映射,即使容器被破坏,数据也应该保持不变。而mysql容器只是一个进入db的客户端接口,可以看到本地目录,因为volumes_from: - data

尝试了这个答案,但没有奏效。 Docker-Compose Persistent Data Trouble

编辑

如下所示更改了我的.yml 并创建了一个目录./data 但现在当我运行docker-compose up --buildmysql 容器不会启动时会抛出错误提示

  data:
    container_name: flask_data
    image: mysql:latest
    volumes:
      - ./data:/var/lib/mysql
    command: "true"

  mysql:
    container_name: flask_mysql
    restart: always
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: 'test_pass' # TODO: Change this
      MYSQL_USER: 'test'
      MYSQL_PASS: 'pass'
    volumes_from:
      - data
    ports:
      - "3306:3306"


flask_mysql | mysqld: Can't create/write to file '/var/lib/mysql/is_writable' (Errcode: 13 - Permission denied)
flask_mysql | 2016-08-26T22:29:21.182144Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
flask_mysql | 2016-08-26T22:29:21.185392Z 0 [ERROR] --initialize specified but the data directory exists and is not writable. Aborting.

【问题讨论】:

标签: docker docker-compose


【解决方案1】:

数据容器是一种多余的解决方法。 Data-volumes 会为您解决问题。将您的 docker-compose.yml 更改为:

version: '2'
services:
  mysql:
    container_name: flask_mysql
    restart: always
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: 'test_pass' # TODO: Change this
      MYSQL_USER: 'test'
      MYSQL_PASS: 'pass'
    volumes:
      - my-datavolume:/var/lib/mysql
volumes:
  my-datavolume:

Docker 将在/var/lib/docker/volumes 文件夹中为您创建卷。只要您不输入docker-compose down -v

,此音量就会一直存在

【讨论】:

  • 从 MySQL 5.7.6 开始,将(再次)使用 permission problemsmysql Docker 映像。您可以改为使用 mariadb Docker 映像、which works flawlessly 和 Docker 卷。
  • 你为什么要把它存储在var/lib/docker/volumes而不是像data/mysql这样的项目文件夹中?
  • @TheGodfather 我的猜测是,如果您不想将 MySQL 数据部署到生产机器上;否则,将所有内容放在一起是一个非常合理的想法。
  • @TheGodfather - 这并不能完全回答您的问题,但我对使用此解决方案持谨慎态度,因为我担心我会无意中执行docker-compose down 并失去我的音量。事实证明,您必须执行docker-compose down -v 才能永久失去音量,这让我对整个方法感觉好多了。我认为一个更好的问题可能是,当 docker 可以完全为您处理它时,为什么还要自己创建一个目录?
  • @louhow 我认为是因为当我的应用程序和数据的所有部分以某种方式存储在一起时,我感到自己更有信心,并且我不依赖于某个地方的某些卷跨度>
【解决方案2】:

有3种方式:

第一种方式

您需要在主机上指定存储mysql数据的目录。然后,您可以删除数据容器。您的 mysql 数据将保存在您的本地文件系统中。

Mysql 容器定义必须如下所示:

mysql:
  container_name: flask_mysql
  restart: always
  image: mysql:latest
  environment:
    MYSQL_ROOT_PASSWORD: 'test_pass' # TODO: Change this
    MYSQL_USER: 'test'
    MYSQL_PASS: 'pass'
volumes:
 - /opt/mysql_data:/var/lib/mysql
ports:
  - "3306:3306"

第二种方式

在输入docker-compose down之前提交数据容器:

docker commit my_data_container
docker-compose down

第三条路

你也可以使用docker-compose stop 代替docker-compose down(这样你就不需要提交容器了)

【讨论】:

  • 我不能只有volumes: - /var/lib/mysql,因为它映射HOST:CONTAINER,如果您不指定带冒号,它映射相同的目录?
  • 不是。不幸的是,在这种情况下,docker 将此容器目录映射到随机主机文件夹,例如 /var/lib/docker/volumes/ec3c543bc92f114c2c568733541e89381881e5a62996d7084e07793f86280535
  • 好吧,我认为volumes: - /var/lib/mysql 等同于volumes: - /var/lib/mysql:/var/lib/mysql
  • 您的第三种方法将不起作用,因为 docker 不会将数据从卷提交到映像。见github.com/moby/moby/issues/6999
  • 第一种方法,两个MySQL容器能否同时并行访问和工作在同一个卷上?
【解决方案3】:

您必须为 mysql 数据创建一个单独的卷。

所以它看起来像这样:

volumes_from:
  - data
volumes:
  - ./mysql-data:/var/lib/mysql

不,/var/lib/mysql 是 mysql 容器内的路径,与主机上的路径无关。您的主机甚至可能根本没有 mysql。所以目标是从 mysql 容器中持久化一个内部文件夹。

【讨论】:

  • 这与将我在数据容器下的volumes 更改为您放在volumes 下的内容并简单地将volumes_from: - data 换成mysql 一样吗?也尝试过这个并且出现了一个新错误。说 dir 存在但不可写,mysql 容器不会运行。
  • 当然你必须创建一个带有路径的本地文件夹
  • 查看我的编辑。在你评论之前没有得到它。但确实创建了本地目录。现在好像有权限问题。
  • 错误:服务“mysql”从“数据”挂载卷,这不是服务或容器的名称。
【解决方案4】:

实际上这是路径,您应该提及一个有效的路径以使其工作。如果您的数据目录在当前目录中,那么您应该提及./my-data 而不是my-data,否则它也会在mysqlmariadb 中给您该错误。

volumes:
 ./my-data:/var/lib/mysql

【讨论】:

  • 如果使用正确,两种方式都有效。第一个,没有路径符号实际上是一个命名卷,它应该在使用之前被初始化。在 docker-compose 文件中,我们可以有一个顶级卷部分来配置名称到主机上特定位置的映射。之后,该卷可以仅通过其名称来引用。
【解决方案5】:

除了@Ohmen 的答案之外,您还可以添加external 标志以在docker compose 之外创建数据卷。这样 docker compose 就不会尝试创建它。此外,您不必担心在$ docker-compose down -v 事件中丢失数据卷内的数据。 下面的例子来自official page

version: "3.8"

services:
  db:
    image: postgres
    volumes:
      - data:/var/lib/postgresql/data

volumes:
  data:
    external: true

【讨论】:

    【解决方案6】:

    首先,你需要删除所有旧的mysql数据使用

    docker-compose down -v
    

    然后在 docker-compose.yml 中添加两行

    volumes:
      - mysql-data:/var/lib/mysql
    

    volumes:
      mysql-data:
    

    你最终的 docker-compose.yml 看起来像

    version: '3.1'
    
    services:
      php:
        build:
          context: .
          dockerfile: Dockerfile
        ports:
          - 80:80
        volumes:
          - ./src:/var/www/html/
      db:
        image: mysql
        command: --default-authentication-plugin=mysql_native_password
        restart: always
        environment:
          MYSQL_ROOT_PASSWORD: example
        volumes:
          - mysql-data:/var/lib/mysql
    
      adminer:
        image: adminer
        restart: always
        ports:
          - 8080:8080
    volumes:
      mysql-data:
    

    之后使用这个命令

    docker-compose up -d
    

    现在您的数据将永久保存,即使使用此命令也不会被删除

    docker-compose down
    

    额外:- 但如果你想删除所有数据,那么你将使用

    docker-compose down -v
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      • 2021-09-06
      • 1970-01-01
      相关资源
      最近更新 更多