MySQL + Docker Compose + Nodejs/Python— Um guia passo a passo
O MySQL é um dos bancos de dados relacionais mais populares de todos os tempos. Usar MySQL com Docker e docker-compose torna muito fácil e rápido testar qualquer alteração em qualquer aplicativo usando o MySQL como banco de dados. Neste tutorial, detalharemos como usar o MySQL com o Docker e o docker-compose passo a passo, mantendo as coisas fáceis de compreender.

Código TLDR aqui . Vamos rolar!
Por que usar MySQL com Docker para desenvolvimento local
Existem vários ótimos motivos para usar qualquer banco de dados, incluindo MySQL com Docker, para desenvolvimento local, alguns deles são os seguintes:
- Usar qualquer versão do MySQL como 5.6, 5.7 ou 8 conforme o projeto ou qualquer outro motivo é muito fácil.
- Normalmente, com o docker, se ele for executado em sua máquina, será executado na máquina de outro engenheiro de software, em um ambiente de preparação e também na produção, desde que alguma compatibilidade seja mantida.
- Um novo membro da equipe pode ser produtivo em horas, não em dias, desde que a janela de encaixe e outras ferramentas sejam configuradas de maneira eficiente.
Pré-requisitos
Antes de colocarmos a mão na massa com alguns códigos e comandos CLI, abaixo estão alguns pré-requisitos bons para se ter:
- O conhecimento básico do Docker e comandos relacionados, como docker build, run, execute, etc., serão úteis para este guia.
- Qualquer informação prévia sobre o Docker-compose será muito útil
- Uma compreensão geral de como os bancos de dados relacionais funcionam, especificamente o MySQL, será vantajoso.
Executar MySQL com Docker
Para este guia para iniciantes, usaremos a imagem oficial do MySQL Docker do DockerHub . A imagem oficial do MySQL Docker não possui uma versão Alpine Linux, ainda assim, a versão Debian também tem 147 MB, o que não é muito grande para uma imagem docker.
Para rodar o container MySQL 8.0 usando a imagem oficial, basta rodar o seguinte comando:
mkdir /tmp/mysql-data
docker run --name basic-mysql --rm -v /tmp/mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=ANSKk08aPEDbFjDO -e MYSQL_DATABASE=testing -p 3306:3306 -it mysql:8.0
--name
para nomear o recipientebasic-mysql
--rm
para remover o recipiente quando ele está parado-v /tmp/mysql-data:/var/lib/mysql
é adicionado para reter os dados quando o contêiner for reiniciado, ele desaparecerá quando a máquina host for reiniciada como está em/tmp
-e MYSQL_ROOT_PASSWORD=ANSKk08aPEDbFjDO -e MYSQL_DATABASE=testing
para definir a senha do usuário root e inicializar um banco de dados chamadotesting
-p 3306:3306
mapeia a porta 3306 do host para a porta 3306 do contêiner, a porta 3306 é a porta padrão do MySQL.-it mysql:8.0
- -mostrará todos os logs e estamos usando a imagem oficial do MySQL versão 8.0 que executará o sabor Debian.
2022-10-27 06:11:09+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.31-1.el8 started.
2022-10-27 06:11:10+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2022-10-27 06:11:10+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.31-1.el8 started.
2022-10-27 06:11:11+00:00 [Note] [Entrypoint]: Initializing database files
2022-10-27T06:11:11.957280Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
2022-10-27T06:11:11.957392Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.31) initializing of server in progress as process 80
2022-10-27T06:11:11.987130Z 0 [Warning] [MY-010159] [Server] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
2022-10-27T06:11:12.013548Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2022-10-27T06:11:16.919522Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2022-10-27T06:11:20.772591Z 6 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
2022-10-27 06:11:27+00:00 [Note] [Entrypoint]: Database files initialized
2022-10-27 06:11:27+00:00 [Note] [Entrypoint]: Starting temporary server
mysqld will log errors to /var/lib/mysql/729f35877b11.err
mysqld is running as pid 133
2022-10-27 06:11:40+00:00 [Note] [Entrypoint]: Temporary server started.
'/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'
Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/leapseconds' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/tzdata.zi' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it.
2022-10-27 06:11:44+00:00 [Note] [Entrypoint]: Creating database testing
2022-10-27 06:11:44+00:00 [Note] [Entrypoint]: Stopping temporary server
2022-10-27 06:11:48+00:00 [Note] [Entrypoint]: Temporary server stopped
2022-10-27 06:11:48+00:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up.
2022-10-27T06:11:48.661152Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
2022-10-27T06:11:48.670274Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.31) starting as process 1
2022-10-27T06:11:48.683339Z 0 [Warning] [MY-010159] [Server] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
2022-10-27T06:11:48.700826Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2022-10-27T06:11:51.317151Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2022-10-27T06:11:52.336910Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2022-10-27T06:11:52.336965Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
2022-10-27T06:11:52.352191Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2022-10-27T06:11:52.548249Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
2022-10-27T06:11:52.548394Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.31' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.
docker exec -it basic-mysql /bin/bash
#once inside the container
mysql -u root -p
#put/paste the password, ANSKk08aPEDbFjDO, and once inside MySQL CLI run
show databases;

Podemos parar o contêiner comdocker stop basic-mysql
Mesmo que não fosse muito difícil, eu não consideraria fácil, assim como os parâmetros do comando não eram simples de lembrar. Outro aspecto é que executamos o MySQL isoladamente, não há vínculo entre o aplicativo Quotes API Node.js e o contêiner MySQL. É aqui que a natureza declarativa do docker-compose é muito útil, como veremos na próxima seção.
Executando MySQL com docker-compose
Adicione os scripts de injeção inicial
mkdir basic-mysql && touch ./basic-mysql/init.sql
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';
USE testing;
DROP TABLE IF EXISTS `order`;
DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS coffee;
/*NEVER store passwords in clear text as it's done here!!!*/
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT NOT NULL,
password TEXT NOT NULL,
role ENUM('admin', 'consumer')
);
INSERT INTO
users (name, email, password, role)
VALUES
('test', '[email protected]', 'test', 'consumer'),
('admin', '[email protected]', 'admin', 'admin');
CREATE TABLE coffee (
id SERIAL PRIMARY KEY,
blend_name char(64),
origin char(64),
variety char(64),
notes char(64),
intensifier char(64),
price float
);
INSERT INTO
coffee (
blend_name,
origin,
variety,
notes,
intensifier,
price
)
VALUES
(
'Good-morning Symphony',
'Dipilto, Nicaragua',
'Kona',
'crisp, coating, concord grape, fresh wood, maple syrup',
'astringent',
23.7
),
(
'KrebStar Mug',
'Central Valley, Costa Rica',
'Yellow Bourbon',
'mild, tea-like, pineapple, barley, musty',
'delicate',
40.0
);
CREATE TABLE `order` (
id SERIAL PRIMARY KEY,
coffeeId BIGINT UNSIGNED NOT NULL,
userId BIGINT UNSIGNED NOT NULL,
quantity INT NOT NULL,
createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT fk_coffeeId FOREIGN KEY (coffeeId) REFERENCES coffee(id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT fk_userId FOREIGN KEY (userId) REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE
);
-- insert data into order table
INSERT INTO
`order` (coffeeId, userId, quantity)
VALUES
(1, 1, 2),
(2, 2, 1);
version: '3.8'
services:
basic-mysql:
container_name: basic-mysql
image: mysql:8.0
cap_add:
- SYS_NICE
restart: always
environment:
- MYSQL_DATABASE=testing
- MYSQL_ROOT_PASSWORD=ANSKk08aPEDbFjDO
ports:
- '3306:3306'
- '33060:33060'
command: --init-file /docker-entrypoint-initdb.d/init.sql
volumes:
- basic-mysql:/var/lib/mysql
- ./basic-mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
basic-mysql:
driver: local
- Ele usa o arquivo docker-compose versão 3.8 , um dos mais recentes.
- Consequentemente, definimos
db
como um serviço, cada serviço será equivalente a um novo comando docker run - Posteriormente, indicamos que o docker-compose use a imagem oficial do MySQL 8.0 para este serviço de banco de dados.
- O
cap_add
conjunto paraSYS_NICE
suprime algumas mensagens de erro não úteis. - Em seguida, pedimos ao docker-compose para sempre reiniciar este contêiner se ele falhar.
- Depois disso, adicionamos 2 variáveis de ambiente para o banco de dados MySQL e a senha do usuário root. Conforme a necessidade, podemos adicionar outro usuário para dar menos privilégios com outros env vars.
- Em seguida, mapeamos a porta do host
3306
para a porta do contêiner,3306
pois o servidor MySQL está sendo executado na porta do contêiner3306
. Dependendo da preferência, a porta do host pode ser alterada. - Em seguida, executamos o script de propagação para injetar dados iniciais em nosso banco de dados mysql
testing
- Em seguida, adicionamos 2 volumes, o primeiro é o volume do banco de dados mapeado para os volumes abaixo
basic-mysql
. O que basicamente diz ao docker e ao docker-compose para gerenciar o volume para nós. Em seguida, adicionamos uminit.sql
script que inicializará nossotesting
banco de dados com o arquivo SQL fornecido.
docker-compose up
[+] Running 1/1
⠿ Container basic-mysql Created 0.2s
Attaching to basic-mysql
basic-mysql | 2022-10-27 09:38:51+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.31-1.el8 started.
basic-mysql | 2022-10-27 09:38:51+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
basic-mysql | 2022-10-27 09:38:51+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.31-1.el8 started.
basic-mysql | '/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'
basic-mysql | 2022-10-27T09:38:52.620935Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
basic-mysql | 2022-10-27T09:38:52.628931Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.31) starting as process 1
basic-mysql | 2022-10-27T09:38:52.649308Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
basic-mysql | 2022-10-27T09:38:53.380032Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
basic-mysql | 2022-10-27T09:38:53.698374Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
basic-mysql | 2022-10-27T09:38:53.698422Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
basic-mysql | 2022-10-27T09:38:53.705214Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
basic-mysql | 2022-10-27T09:38:53.904655Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.31' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.
basic-mysql | 2022-10-27T09:38:53.904741Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock
Conectando-se ao banco de dados via UI, como o MySQL Workbench e verificando se nossas tabelas estão devidamente propagadas


Testar conexão via script python
Assegure-se de que a dependência esteja instalada. correr pip install pymysql
oupip3 install pymysql
# main.py
import pymysql.cursors
# Connect to the database
connection = pymysql.connect(
host='localhost',
user='root',
password='ANSKk08aPEDbFjDO',
database='testing',
cursorclass=pymysql.cursors.DictCursor
)
with connection:
with connection.cursor() as cursor:
# Read a single record
sql = "SELECT * FROM `users`"
cursor.execute(sql)
result = cursor.fetchall()
print(result)
Testando a conexão via script de nó
Assegure-se de que a dependência esteja instalada. Correnpm i mysql
// main.js
const mysql = require('mysql');
const con = mysql.createConnection({
host: "localhost",
user: "root",
password: "ANSKk08aPEDbFjDO",
database: "testing"
});
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
con.query("SELECT * FROM `users`", function (err, result, fields){
if (err) throw err;
console.log(result);
});
});
Chamado para ação
Se você achar o guia útil, sinta-se à vontade para bater palmas e me seguir. Junte-se ao meio através deste link para acessar todos os artigos premium meus e de todos os outros escritores incríveis aqui no meio.
Codificação de nível
Obrigado por fazer parte da nossa comunidade! Antes de você ir:
- Bata palmas para a história e siga o autor
- Veja mais conteúdo na publicação Level Up Coding
- Siga-nos: Twitter | Linkedin | Boletim de Notícias