Dados persistentes do Docker-Compose MySQL

156

Não consigo obter dados do MySQL para persistir se executar $ docker-compose downcom o seguinte.yml

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"

Meu entendimento é que, no meu datacontêiner, o volumes: - /var/lib/mysqlmapeia para o diretório de máquinas locais, onde o mysql armazena dados no contêiner e, por causa desse mapeamento, os dados devem persistir, mesmo que os contêineres sejam destruídos. E o mysqlcontêiner é apenas uma interface do cliente no banco de dados e pode ver o diretório local por causa devolumes_from: - data

Tentativa de resposta e não funcionou. Problema persistente de dados do Docker-Compose

EDITAR

Alterei o meu .ymlcomo mostrado abaixo e criou um dir, ./datamas agora quando executo docker-compose up --buildo mysqlcontêiner não começará a lançar erro dizendo

  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.
Adão
fonte

Respostas:

222

O contêiner de dados é uma solução alternativa supérflua. Os volumes de dados fariam o truque para você. Altere o seu docker-compose.ymlpara:

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:

O Docker criará o volume para você na /var/lib/docker/volumespasta. Esse volume persiste enquanto você não estiver digitandodocker-compose down -v

Oh cara
fonte
18
A partir do MySQL 5.7.6 (novamente) haverá problemas de permissão com a mysqlimagem do Docker. Você pode usar a mariadbimagem do Docker, que funciona perfeitamente com os volumes do Docker.
Peterino
Esta solução funcionou para mim. Algumas notas / precisões: 1. quando você usa a configuração acima no docker-compose.yml e implanta sua pilha de serviços usando "docker stack deploy -c docker-compose.yml mystack", não há necessidade de criar o manualmente, ele será criado como / var / lib / docker / volumes / mystack_my-datavolume automaticamente para você (observe que ele anexa "mystack_" ao nome do volume). 2. Não precisei alterar as permissões no meu diretório. Mesmo se eu tiver arquivos pertencentes ao mysql: root no meu contêiner, eles foram criados como 27: root no meu host do Docker sem problemas.
Joey Cote
10
Por que você deseja armazená-lo em var/lib/docker/volumesvez de ter um diretório na pasta do projeto data/mysql?
The Godfather
@TheGodfather Meu palpite seria se você não deseja implantar dados MySQL na sua máquina de produção; caso contrário, é uma ideia muito boa manter tudo junto.
Duncan
1
@louhow Acho que é porque eu me sinto mais confiante quando todas as partes do meu aplicativo e os dados são armazenados de alguma forma, em conjunto, e não tenho nenhuma dependência em algum volume de algum lugar
The Godfather
53

Existem 3 maneiras:

Primeira maneira

Você precisa especificar o diretório para armazenar dados mysql em sua máquina host . Você pode remover o contêiner de dados. Seus dados mysql serão salvos no seu sistema de arquivos local.

A definição de contêiner do Mysql deve ser assim:

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"

Segunda via

Seria confirmar o contêiner de dados antes de digitar docker-compose down:

docker commit my_data_container
docker-compose down

Terceira via

Também é possível usar em docker-compose stopvez de docker-compose down(então você não precisa confirmar o contêiner)

Bukharov Sergey
fonte
Não posso simplesmente volumes: - /var/lib/mysqlporque ele mapeia HOST:CONTAINERe, se você não especificar com dois pontos, mapeia o mesmo diretório?
Adam
Não. Infelizmente, neste caso, docker mapear este directório recipiente para pasta de host aleatório como/var/lib/docker/volumes/ec3c543bc92f114c2c568733541e89381881e5a62996d7084e07793f86280535
Bukharov Sergey
Pensamento Ok, eu volumes: - /var/lib/mysqlera equivalente avolumes: - /var/lib/mysql:/var/lib/mysql
Adam
o seu thrid way não funcionará porque o docker não confirma dados de volumes na imagem. consulte github.com/moby/moby/issues/6999
Ohmen
13

Você precisa criar um volume separado para dados mysql.

Então será assim:

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

E não, /var/lib/mysqlé um caminho dentro do seu contêiner mysql e não tem nada a ver com um caminho na máquina host. Sua máquina host pode até não ter nenhum mysql. Portanto, o objetivo é manter uma pasta interna de um contêiner mysql.

Dmitry Malyshenko
fonte
Isso não seria nenhum diferente do que mudar a minha volumessob o contêiner de dados para que você colocar sob o seu volumese simplesmente tinha volumes_from: - datapara mysql? Também tentou isso e gerou um novo erro. Diz que o diretório existe, mas não é gravável e o mysqlcontêiner não será executado.
Adam
Claro que você tem que criar uma pasta local com um ./mysql-data caminho (ou o que você iria colocar antes de ponto e vírgula)
Dmitry Malyshenko
Veja minha edição. Não recebi antes de comentar. Mas criou o diretório local. Parece que há um problema de permissão agora.
Adam
ERRO: O serviço "mysql" monta volumes de "dados", que não são o nome de um serviço ou contêiner.
Massimiliano Arione
10

Na verdade, esse é o caminho e você deve mencionar um caminho válido para que isso funcione. Se seu diretório de dados estiver no diretório atual, em vez de my-datavocê mencionar ./my-data, caso contrário, ele fornecerá esse erro mysqle mariadbtambém.

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