MySQL + Docker Compose + Nodejs/Python — пошаговое руководство
MySQL — одна из самых популярных реляционных баз данных всех времен. Использование MySQL с Docker и docker-compose позволяет очень легко и быстро тестировать любые изменения в любом приложении, использующем MySQL в качестве базы данных. В этом руководстве мы подробно расскажем, как использовать MySQL с Docker и создавать докеры шаг за шагом, чтобы все было легко понять.

Код TLDR здесь . Поехали!
Зачем использовать MySQL с Docker для локальной разработки
Есть несколько веских причин для использования любой базы данных, включая MySQL с Docker, для локальной разработки, вот некоторые из них:
- Использование любой версии MySQL, такой как 5.6, 5.7 или 8, в соответствии с проектом или по любой другой причине очень просто.
- Обычно с докером, если он работает на вашем компьютере, он будет работать на компьютере другого инженера-программиста, в тестовой среде, а также в рабочей среде, при условии, что поддерживается некоторая совместимость.
- Новый член команды может быть продуктивным в течение нескольких часов, а не дней, если докер и другие инструменты настроены эффективно.
Предпосылки
Прежде чем мы запачкаем руки кодом и командами CLI, ниже приведены некоторые необходимые предварительные условия:
- Базовые знания Docker и связанных с ним команд, таких как сборка, запуск, выполнение и т. д., будут полезны для этого руководства.
- Любая предварительная информация о Docker-compose будет очень полезна.
- Общее понимание того, как работают реляционные базы данных, особенно MySQL, будет преимуществом.
Запустите MySQL с помощью Docker
Для этого руководства для начинающих мы будем использовать официальный образ MySQL Docker от DockerHub . Официальный образ MySQL Docker не имеет версии Alpine Linux, однако версия Debian также имеет размер 147 МБ, что не слишком много для образа докера.
Чтобы запустить контейнер MySQL 8.0 с использованием официального образа, просто выполните следующую команду:
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
назвать контейнерbasic-mysql
--rm
удалить контейнер, когда он остановлен-v /tmp/mysql-data:/var/lib/mysql
добавлен для сохранения данных при перезапуске контейнера, они исчезнут при перезапуске хост-компьютера , как и в/tmp
-e MYSQL_ROOT_PASSWORD=ANSKk08aPEDbFjDO -e MYSQL_DATABASE=testing
для установки пароля пользователя root и инициализации базы данных с именемtesting
-p 3306:3306
сопоставляет порт хоста 3306 с портом контейнера 3306, порт 3306 является портом MySQL по умолчанию.-it mysql:8.0
- - он покажет все журналы, и мы используем официальный образ MySQL версии 8.0, который будет работать под управлением 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;

Мы можем остановить контейнер с помощьюdocker stop basic-mysql
Хотя это было не слишком сложно, я бы не назвал это простым, так как параметры команды было непросто запомнить. Другой аспект заключается в том, что мы запускали MySQL изолированно, между приложением Quotes API Node.js и контейнером MySQL нет связи. Именно здесь декларативный характер docker-compose оказывается очень кстати, как мы увидим в следующем разделе.
Запуск MySQL с помощью docker-compose
Добавьте начальные скрипты инъекций
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
- Он использует файл docker-compose версии 3.8 , один из последних.
- Следовательно, мы определяем
db
как службу, каждая служба будет эквивалентна новой команде запуска докера. - Впоследствии мы указываем docker-compose использовать официальный образ MySQL 8.0 для этой службы БД.
- Установка подавляет
cap_add
некоторые бесполезные сообщения об ошибках.SYS_NICE
- Затем мы просим docker-compose всегда перезапускать этот контейнер в случае сбоя.
- После этого мы добавляем 2 переменные среды для базы данных MySQL и пароль пользователя root. При необходимости мы можем добавить другого пользователя, чтобы дать ему меньше привилегий с другими переменными env.
- Затем мы сопоставляем порт хоста
3306
с портом контейнера3306
, поскольку сервер MySQL работает на порту контейнера3306
. В зависимости от предпочтения хост-порт может быть изменен. - Затем мы запускаем скрипт заполнения для ввода исходных данных в нашу базу данных mysql.
testing
- Затем мы добавляем 2 тома, первый — это том БД, сопоставленный с нижеприведенными томами
basic-mysql
. Что в основном говорит docker и docker-compose управлять томом для нас. Затем мы добавляемinit.sql
скрипт, который будет инициализировать нашуtesting
базу данных с данным файлом SQL.
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
Подключение к базе данных через пользовательский интерфейс, например MySQL Workbench , и проверка правильности заполнения наших таблиц.


Тестовое соединение через скрипт python
Убедитесь, что зависимость установлена. Беги pip install pymysql
илиpip3 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)
Тестирование соединения через скрипт узла
Убедитесь, что зависимость установлена. Бегnpm 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);
});
});
Призыв к действию
Если вы найдете руководство полезным, не стесняйтесь хлопать и следовать за мной. Присоединяйтесь к среде по этой ссылке , чтобы получить доступ ко всем премиальным статьям от меня и всех других замечательных авторов здесь, на среде.
Повышение уровня кодирования
Спасибо, что являетесь частью нашего сообщества! Прежде чем ты уйдешь:
- Хлопайте за историю и подписывайтесь на автора
- Смотрите больше контента в публикации Level Up Coding
- Подписывайтесь на нас: Твиттер | Линкедин | Новостная рассылка