Docker - Persistência com SQL Server, PostgreSQL, MySQL, MongoDB


 Neste artigo veremos como containerizar e acessar os principais bancos de dados do mercado usando o Docker.

O Docker não foi criado com persistência em mente, e um dos recursos mais atraentes dos contêineres é sua capacidade de ser iniciado e encerrado à vontade, assim, os dados no contêiner são transitórios e são apagados com o contêiner.

Por este motivo devemos ter cuidado ao usar serviços de banco de dados em containers em ambiente de PRODUÇÃO.

Se seu banco de dados não for um serviço crítico, talvez você possa testá-lo no Docker; caso contrário, você está entrando em uma zona perigosa que poderá te trazer muitos problemas.

Se você estiver implantando em uma nuvem, a melhor opção é usar serviços de banco de dados em nuvem (AWS Relational Database Service (RDS), Azure Databases, Google Cloud Databases, Managed Databases on Digital Ocean ou um serviço de banco de dados hospedado equivalente do seu provedor de nuvem).

Agora vejamos outro cenário onde temos alguns mecanismos de banco de dados diferentes em nossos projetos, ou temos versões diferentes de qualquer (ou todos) deles, ou onde temos equipes com outros sistemas operacionais ou com uma configuração diferente, ou você precisa preparar o ambiente para um novo membro da equipe.

Neste casos, para não sobrecarregar nossa máquina de trabalho com diferentes instalações e versões podemos fazer isso em um só lugar facilmente usando o Docker por meio dos comandos docker CLI ou de um docker-compose, e, podemos fazer isso adicionando e removendo recursos sem afetar o resto do sistema.

Como mencionado anteriormente, os contêineres não existem com persistência em mente, mas geralmente queremos ter dados mesmo se reiniciarmos nosso mecanismo de contêiner ou máquina de trabalho.

Felizmente, existem algumas maneiras de preservar os dados em um contâiner e o Docker trata com a persistência em geral de duas formas:

  1. Usando Bind mounts ou montagens de ligação;
  2. Usando Volumes;

Essas duas abordagens permitem que você monte uma localização na máquina host para armazenar os dados do container. Isso fornece armazenamento para os dados mesmo se o contêiner for encerrado e não há necessidade de se preocupar com a perda de dados.

Vejamos como funciona a primeira opção.

1- Usando Bind mounts

Na abordagem bind mounts será montado um arquivo ou diretório para o contêiner a partir da máquina host e, em seguida, ele poderá ser referenciado por meio de seu caminho absoluto.

Ele depende do sistema de arquivos da máquina host ter uma estrutura de diretório específica. Caso contrário, é necessário criar explicitamente um caminho para o arquivo ou pasta para colocar o armazenamento. Além disso, esta abordagem nos dá acesso a arquivos confidenciais e podemos alterar o sistema de arquivos do host por meio de processos executados em um contêiner, o que é considerado uma implicação de segurança.

Podemos usar os sinalizadores --mount e -v para usar montagens de ligação em um contêiner.

A diferença mais notável entre as duas opções é que --mount é mais explícito e detalhado, enquanto -v é mais um atalho para --mount. Ele combina todas as opções --mount em um único campo.

Vejamos um exemplo prático usando o banco de dados PostgreSQL:

docker run --rm --name pgdb -e POSTGRES_PASSWORD=numsey#2022 --mount type=bind,source="$(pwd)",target=/var/lib/postgresql/data -p 2000:5432 -d postgres

Nosso contêiner PostgreSQL está em execução e agora pode ser acessado a partir da ferramenta de banco de dados apropriada (como o DBeaver Community, pgAdmin, etc).

Estamos usando a porta 2000 e a senha numsey#2022 para conectar à nossa instância de banco de dados, conforme definimos anteriormente no comando da CLI do Docker.

2- Usando Volumes do Docker

Na abordagem onde usamos os volumes temos que o Docker gerencia totalmente os volumes do docker; portanto, eles não são afetados por nossa estrutura de diretórios ou pelo sistema operacional da máquina host. Quando utilizamos um volume, o Docker cria um novo diretório no diretório de armazenamento da máquina host e o Docker manipula seu conteúdo. Para volumes do Docker, o armazenamento não está associado ao ciclo de vida do contêiner e reside fora do contêiner.

Algumas das vantagens:

- Elimina os contêineres conforme necessário e ainda retém seus dados;
- Anexa os volumes a vários contêineres em execução ao mesmo tempo;
- Reutiliza o armazenamento em vários contêineres (por exemplo, um contêiner grava no armazenamento e outro lê no armazenamento)
- Os volumes não aumentam o tamanho dos contêineres do Docker que os utilizam;
- Podemos usar a CLI do Docker para gerenciar seus volumes (por exemplo, recuperar uma lista de volumes ou excluir volumes não utilizados).


a- Exemplo usando o SQL Server:

docker run --rm --name macmssql -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=numsey#2022" -e "MSSQL_PID=Express" --mount type=volume,source=custommssql,target=/var/opt/mssql -p 7000:1433 -d mcr.microsoft.com/mssql/server:2019-latest

Podemos fazer a conexão com o banco no container através do SQL Server Management Studio:

Informamos :

b- Exemplo usando o PostgreSQL:

docker run --rm --name macpostgresql -e POSTGRES_PASSWORD=numsey#2022 --mount type=volume,source=custompostgres,target=/var/lib/postgresql/data -p 7001:5432 -d postgres:latest

Vamos acessar o PostgreSQL no container usando o PgAdmin e criando a conexão:

Criamos uma nova conexão chamada docker_postgresql onde informamos:

c- Exemplo usando o MySQL:

docker run --rm --name macmysql -e MYSQL_ROOT_PASSWORD=numsey#2022 --mount type=volume,source=custommysql,target=/var/lib/mysql -p 7003:3306 -d mysql:latest

Podemos acessar o MySQL no container usando o MySq lWorkbench e criando uma conexão:

Para a conexão informamos:

d- Exemplo usando o MongoDB:

docker run --rm --name macmongo -e MONGO_INITDB_ROOT_USERNAME=macora -e MONGO_INITDB_ROOT_PASSWORD=numsey@2022 --mount type=volume,source=custommongo,target=/data/db -p 7004:27017 -d mongo:latest

A imagem usada também vai criar um volume para /data/configdb, portanto, você verá um volume de ID hexadecimal adicional em seus volumes do Docker.

Para conectar usamos a seguinte informação: URI - mongodb://macora:numsey@2022@localhost:7004

Usando o MongoDB Compass informamos:

Podemos conferir o nosso ambiente usando o dashboard do Docker Desktop for Windows onde temos:

1- As imagens usadas para o SQL Server, Mongo, MySQL e PostgreSQL

2- Os respectivos containeres criados em execução

3- Os volumes que foram montados para os respectivos banco de dados no host:

Visualizando os volumes usando o comando : docker volume ls

Ao invés de usar a linha de comando com a CLI do Docker também podemos usar um arquivo docker-compose para cada um dos banco de dados e assim definir a conexão.

Exemplo de docker-compose para o SQL Server:

version: '3.4'

services:
  db:
    image: mcr.microsoft.com/mssql/server:2019-latest
    restart: always
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=numsey#2022
      - MSSQL_PID=Express
    ports:
      - 7000:1433
    volumes:
      - custommssql:/var/lib/postgresql/data

volumes:
  custommssql:
    driver: local

Isso permite gerenciar de forma mais adequada cada conexão com cada banco de dados no seu ambiente.

De acordo com a documentação do Docker, o uso de volumes é a abordagem mais direta para iniciar a persistência de dados em seu contêiner do Docker. Em geral, a abordagem - bind mounts  ou  montagens de ligação - têm restrições adicionais de uso e deve ser evitada.

Dessa forma temos em nosso ambiente a execução e a persistência sendo usada para 4 banco de dados rodando em 4 containeres independentes e após a execução cada container será destruído sendo os dados persistidos nos volumes criados para cada banco.

Com isso nosso ambiente esta livre e conseguimos configurar o uso de cada banco para a nossa necessidade graças ao Docker

E estamos conversados

'Como, pois, invocarão aquele em quem não creram? e como crerão naquele de quem não ouviram? e como ouvirão, se não há quem pregue?'
Romanos 10:14

Referências:


José Carlos Macoratti