База данных и установка MySQL: таблицы, ключи, Docker и драйвер

Цели урока
  • Объяснить, зачем нужна база данных и в чём проблемы сохранения в файл JSON в настоящей системе
  • Определить таблицу, строку, столбец и первичный ключ (Primary Key) и распознавать их в примере
  • Знать базовые типы данных — INT, VARCHAR, DECIMAL — и NOT NULL
  • Переводить модель Python (класс или словарь) в проект таблицы
  • Объяснить, что такое сервер базы данных и почему его запускают в контейнере Docker
  • Запускать MySQL через docker run и снова запускать через docker start
  • Подключаться к базе из VS Code с помощью расширения Database Client и выполнять в нём SQL
  • Устанавливать драйвер, подключаться из Python и знать, почему пароль не пишут в коде

В этом уроке

Урок состоит из двух глав — в том же порядке, что и в презентации:

  1. Глава 1 — что такое база данных: таблица, строка, столбец, первичный ключ и типы данных
  2. Глава 2 — установка MySQL: Docker, Database Client и драйвер

Глава 1: Что такое база данных — таблица, строка, столбец, первичный ключ и типы данных

Что мы изучим?

  • Зачем нужна база данных (Database).
  • Что такое реляционная база данных (Relational Database).
  • Таблицу (Table), строку (Row), столбец (Column).
  • Первичный ключ (Primary Key).
  • Базовые типы данных (Data Types).
Чего мы здесь (намеренно) не изучим

Здесь мы изучаем только основы, необходимые для CRUD: подключение, одну таблицу и создание, чтение, обновление и удаление. Мы не будем изучать JOIN, GROUP BY, HAVING, подзапросы (Sub-Queries), продвинутую нормализацию, индексы или хранимые процедуры (Stored Procedures). Их вы глубоко изучите позже в треке.

Зачем это нужно?

В теме файлов мы сохраняли данные в файл JSON. Это работало для одной программы на нашем компьютере. На настоящем сервере это ломается:

Проблема файла JSONЧто происходит
Всё или ничего при чтенииЧтобы найти одного студента из миллиона, вы загружаете весь файл в RAM.
Всё или ничего при записиЧтобы изменить одно поле, вы снова записываете весь файл.
Два пользователя одновременноДва запроса читают файл, каждый что-то меняет, и каждый записывает. Изменение первого стирается.
Сбой посреди записиФайл остаётся наполовину записанным и испорченным.
Нет правилНичто не мешает двум студентам с одинаковым email или отсутствующему полю.
Запросы«Все студенты из Хайфы старше 20» = цикл в нашем коде по всем данным.

База данных решает всё это: чтение и запись ровно того, что нужно, работа многих пользователей одновременно, защита от сбоев, правила, которые обеспечивает сама база, и язык (SQL) для запросов.

Объяснение с основ

Что такое база данных?

База данных (Database) = система упорядоченного хранения данных, которая позволяет эффективно и надёжно их сохранять, находить, обновлять и удалять. Программа, которая ею управляет, называется СУБД (DBMS, Database Management System): MySQL, PostgreSQL, SQLite…

Реляционная база данных — таблицы

Самый распространённый вид — реляционная база данных: данные организованы в таблицы, как лист Excel со строгими правилами.

Table: students
┌────┬────────┬─────┬────────────────┐
│ id │ name   │ age │ email          │   ← columns (the structure)
├────┼────────┼─────┼────────────────┤
│  1 │ Dana   │  24 │ dana@mail.com  │   ← row = one student
│  2 │ Avi    │  31 │ avi@mail.com   │   ← row
│  3 │ Noa    │  22 │ noa@mail.com   │   ← row
└────┴────────┴─────┴────────────────┘
  ↑
  primary key
ТерминЧто этоВ Python (то, что мы уже знаем)
Таблица (Table)Коллекция записей одного видаКласс (шаблон) + список всех объектов
Столбец (Column)Одно поле с фиксированным именем и типомАтрибут
Строка (Row, запись)Один элементОдин объект / один словарь
Первичный ключ (Primary Key)Столбец, который однозначно идентифицирует каждую строкуstudent_id
Аналогия: картотека в офисе

База данных = шкаф. Таблица = один ящик («студенты»). Столбцы = печатная анкета, по которой построена каждая папка (имя, возраст, email), одинаковая для всех папок. Строка = одна папка, одного студента. Первичный ключ = номер на корешке папки: он никогда не повторяется, и по нему достают папку, не перебирая все.

Первичный ключ

Первичный ключ (Primary Key) = столбец (обычно id), значение которого:

  1. Уникально — нет двух строк с одинаковым значением.
  2. Не пусто — у каждой строки должно быть значение.
  3. Не меняется — идентификатор — на всю жизнь строки.

Почему не использовать имя? Потому что есть две «Даны». А email? Потому что люди меняют email. Числовой идентификатор, который база выдаёт сама, — безопасный выбор. (Помните Shop, который выдавал идентификаторы через max + 1? База делает это за нас, и надёжнее.)

И это ровно {student_id} в пути API: GET /students/7 = «принеси строку, первичный ключ которой 7».

Типы данных

У каждого столбца есть тип. В MySQL (базе, которую мы будем использовать) типов много, но нам понадобятся такие:

Тип SQLЧто хранитсяPythonПример
INTЦелое числоintid, age, quantity
DECIMAL(10, 2)Точное десятичное число — 2 знака после точкиDecimal (как float, но точное)price
VARCHAR(100)Текст — до 100 символовstrname, email
(настоящего BOOLEAN нет)Хранят 0/1 в INTboolis_active
NULL«Нет значения»NoneПустое необязательное поле

Базовые ограничения

Правила, которые обеспечивает база данных. Даже если в коде есть баг, база откажет:

Ограничение (Constraint)Значение
PRIMARY KEYУникальный идентификатор строки.
AUTO_INCREMENTБаза сама выдаёт id по возрастанию.
NOT NULLДолжно быть заполнено.
UNIQUEНет двух строк с одинаковым значением (например, email).

Это как проверка в __init__ (тема ООП), только её обеспечивает сама база — ещё один слой защиты.

SQL — язык

SQL (Structured Query Language, произносится «сиквел» или «эс-кью-эл») = язык, на котором общаются с реляционной базой данных. Запрос (Query) = одна команда на SQL. Мы встретим только четыре-пять команд:

CREATE TABLE   → create the structure      (day 3)
INSERT         → C - add a row             (day 3)
SELECT         → R - read rows             (day 3)
UPDATE         → U - change rows           (day 4)
DELETE         → D - remove rows           (day 4)

Синтаксис

Проект таблицы (результат этапа проектирования, до всякого кода). Так выглядит проект таблицы students:

Table: students
| column | type         | constraints                 |
|--------|--------------|-----------------------------|
| id     | INT          | AUTO_INCREMENT PRIMARY KEY  |
| name   | VARCHAR(100) | NOT NULL                    |
| age    | INT          | NOT NULL                    |
| email  | VARCHAR(100) | NOT NULL UNIQUE             |

А вот команда SQL, которая её создаёт (мы напишем и выполним её в следующих уроках; здесь — только чтобы увидеть, куда мы идём):

CREATE TABLE students (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    age INT NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE
);

Первый пример кода

От класса Python к проекту таблицы. Класс Product из темы ООП:

class Product:
    def __init__(self, sku, name, price, stock=0):
        ...

Перевод:

Атрибут в PythonСтолбецТипОграниченияПочему
—idINTAUTO_INCREMENT PRIMARY KEYСтабильный внутренний идентификатор
skuskuVARCHAR(20)NOT NULL UNIQUEУникальный, обязательный
namenameVARCHAR(100)NOT NULLОбязательный
pricepriceDECIMAL(10, 2)NOT NULLТочное десятичное число
stockstockINTNOT NULL DEFAULT 0Целое число, по умолчанию 0

Разбор кода построчно

РешениеОбоснование
Добавить id, хотя есть skusku — бизнес-идентификатор, который может измениться (ребрендинг). id — технический идентификатор, который никогда не меняется. Принято хранить оба.
sku с UNIQUEПравило «артикул уникален» обеспечивается в базе, даже если другой код забудет проверить.
price как DECIMAL(10, 2)Цена с агорот (копейками). DECIMAL хранит число точно — без проблем округления float (0.1 + 0.2).
Что не входит в таблицуМетоды (take, restock) — это поведение, и они живут в коде. База хранит только данные.

Ещё один пример

От словарей к таблице и «грязные» типы. Данные, которые пришли из файла JSON:

students = [
    {"name": "Dana", "age": 24, "email": "dana@mail.com", "phone": "050-1234567"},
    {"name": "Avi", "age": "31", "email": "avi@mail.com"},
    {"name": "Noa", "age": 22, "email": "dana@mail.com", "phone": None},
]

Вопросы проектирования:

  1. phone есть только в части строк. → столбец без NOT NULL. Когда значения нет, хранится NULL (None в Python).
  2. У Ави age — "31" (строка). → столбец INT. В коде мы преобразуем int(...) перед сохранением (или это сделает Pydantic в теме API студентов).
  3. У Ноа и Даны одинаковый email. → с UNIQUE на email база откажется сохранять Ноа. Именно этого мы и хотим (и обработаем эту ошибку в следующих уроках).
  4. Нет id. → AUTO_INCREMENT: база выдаст 1, 2, 3.
| column | type         | constraints                |
|--------|--------------|----------------------------|
| id     | INT          | AUTO_INCREMENT PRIMARY KEY |
| name   | VARCHAR(100) | NOT NULL                   |
| age    | INT          | NOT NULL                   |
| email  | VARCHAR(100) | NOT NULL UNIQUE            |
| phone  | VARCHAR(20)  | (nullable)                 |

Почему phone — VARCHAR, а не INT? Потому что 050-1234567 содержит дефис, а номер телефона, начинающийся с 0, потерял бы ноль в INT. Правило: «число», с которым не делают арифметики (телефон, индекс, номер удостоверения), → VARCHAR.

Типичная ошибка

Ошибка 1: «естественный» первичный ключ, который может измениться или повториться. Имя, email, номер телефона. В день, когда Дана сменит email, все, кто указывал на неё по email, её «потеряют». Числовой id от базы.

Ошибка 2: хранить список внутри одного столбца.

| id | name | grades     |
|  1 | Dana | "90,85,70" |

Нельзя посчитать среднее в SQL, нельзя найти «всех, кто получил 90», и трудно обновить одну оценку. В реляционном мире оценки — отдельная таблица (grades со student_id). Это вы глубоко изучите позже в треке (связи между таблицами и JOIN). Здесь мы будем работать с одной таблицей и простыми полями.

Ошибка 3: отказаться от NOT NULL и `UNIQUE», «потому что код проверяет». Код проверяет сегодня. Завтра кто-то напишет скрипт импорта, который обходит код, или появится баг. База — последняя линия обороны.

Ошибка 4: думать, что SQL — это «программа». SQL — декларативный язык: вы говорите, что хотите («все студенты из Хайфы»), а не как это найти (никаких циклов). База сама решает, как выполнить это эффективно.

Итоги

  • База данных решает проблемы файла JSON: точечное чтение и запись, много пользователей одновременно, устойчивость к сбоям, правила и запросы.
  • Реляционная база = таблицы. Таблица ≈ класс + все объекты. Столбец ≈ атрибут (с типом). Строка ≈ один объект.
  • Первичный ключ = уникальный идентификатор, не пустой и неизменный. Обычно id INT AUTO_INCREMENT PRIMARY KEY.
  • Типы в MySQL: INT, DECIMAL, VARCHAR и NULL (= None). bool хранится как 0/1. Телефон и индекс хранятся как VARCHAR.
  • Ограничения: NOT NULL, UNIQUE. База обеспечивает правила, даже когда код ошибается.
  • SQL = декларативный язык. Здесь: CREATE TABLE, INSERT, SELECT, UPDATE, DELETE — и всё.

Официальная документация

Глава 2: Установка MySQL — Docker, Database Client и драйвер

Что мы изучим?

  • Что такое сервер базы данных и почему мы будем работать с MySQL.
  • Что такое контейнер и как запустить MySQL в Docker — одной командой.
  • Как видеть базу из VS Code с помощью расширения Database Client.
  • Что такое драйвер (Driver) и как Python подключается к MySQL.
  • Где хранить данные для подключения — и почему не в коде.

Зачем это нужно?

Прежде чем написать хоть один INSERT, нужно ответить на «сантехнические» вопросы: где работает база? Как наш код до неё добирается? Каковы данные для подключения? В реальной работе первое, что вы получаете в новом проекте, — именно это: «вот данные для подключения к базе». Нужно знать, что с ними делать.

Объяснение с основ

База данных — это сервер

MySQL — сервер базы данных: отдельная программа (процесс — вспомните тему операционной системы!), которая работает всё время и слушает порт — в MySQL это порт 3306. Наш код не открывает файл — он подключается по сети к серверу, точно как браузер, который подключается к сайту (тема сетей: IP + порт).

MySQL (сервер базы данных)
ГдеОтдельный процесс, который слушает порт 3306
Как подключатьсяПо сети: хост, порт, пользователь, пароль и имя базы
Кто подключаетсяНесколько программ и серверов — одновременно
Где это в миреСайты и системы любого размера. PostgreSQL и SQL Server работают так же

Почему Docker?

Установка MySQL напрямую на компьютер — долгий процесс: мастер установки, пароли, служба, работающая в фоне, и настройки, которые различаются между Windows и Mac. И то, что работает у одного, не всегда работает у другого.

Docker (который мы установили в первую неделю) решает это: он запускает готовые программы внутри контейнера.

  • Образ (Image) — шаблон: «MySQL версии 8.4, готовый к работе». Его скачивают один раз.
  • Контейнер (Container) — работающая копия образа. Изолирован от остального компьютера и содержит всё, что нужно программе.
Аналогия: контейнер в порту

Грузовой контейнер выглядит одинаково на каждом корабле и в каждом порту — неважно, что внутри. Так и контейнер Docker: тот же MySQL с теми же настройками работает абсолютно одинаково у всех студентов, в любой операционной системе.

Database Client — база с интерфейсом

MySQL можно видеть и использовать без единой строки кода — с помощью расширения VS Code с именем Database Client (автор Weijan Chen). Оно показывает дерево баз и таблиц, открывает таблицу как электронную таблицу, выполняет SQL и показывает результат в виде таблицы. Мы будем использовать его во всех этих темах, чтобы видеть, что наш код сделал в базе.

Драйвер — переводчик

Наш код написан на Python. MySQL говорит на собственном «протоколе» (тема сетей: протокол = правила общения). Нужен посредник, который переводит: драйвер (Driver, его также называют Database Connector) = библиотека, которая умеет:

  1. Подключаться к серверу базы данных определённого вида.
  2. Отправлять ему команды SQL.
  3. Возвращать результаты в виде данных Python (tuple, int, str).

Для MySQL мы будем использовать официальный драйвер: mysql-connector-python. Его устанавливают через pip, а в коде пишут import mysql.connector.

Аналогия: переходник для розетки за границей

У вашего устройства (кода Python) израильская вилка, а розетка в стене (база данных) — американская. Драйвер = переходник. Для каждого вида розетки свой переходник, но само устройство не меняется.

Данные для подключения — и не в коде!

Чтобы подключиться к MySQL, нужны пять данных:

ДанныеУ насЧто это
hostlocalhostГде сервер — наш компьютер
port3306Порт MySQL
userrootИмя пользователя
passwordkodkodПароль, который мы задали в контейнере
databaseschoolКакая база внутри сервера

В настоящем проекте здесь настоящий пароль. Если он написан в коде, а код попал на GitHub, он утёк (вспомните секреты из темы Git!). Профессиональная практика:

  • Данные для подключения хранятся в переменных окружения (Environment Variables) или в файле .env, который находится в .gitignore.
  • Код читает их: os.environ.get("DB_PASSWORD").

Синтаксис

Запуск MySQL в контейнере — одна команда, один раз (в PowerShell; на Mac замените ` на \):

docker run --name kodkod-mysql `
  -e MYSQL_ROOT_PASSWORD=kodkod `
  -e MYSQL_DATABASE=school `
  -p 3306:3306 -d mysql:8.4
ЧастьЗначение
docker runСоздаёт и запускает новый контейнер
--name kodkod-mysqlИмя контейнера, чтобы к нему обращаться
-e MYSQL_ROOT_PASSWORD=kodkodПеременная окружения: пароль пользователя root
-e MYSQL_DATABASE=schoolПеременная окружения: база с именем school, которая создаётся автоматически
-p 3306:3306Порт 3306 на нашем компьютере ведёт к MySQL внутри контейнера
-dРаботает в фоне (detached), терминал остаётся свободным
mysql:8.4Образ: MySQL версии 8.4

Полезные команды:

docker ps                     # which containers are running now
docker start kodkod-mysql     # start it again (after a restart of the computer)
docker stop kodkod-mysql      # stop it (the data is kept)

Подключение из Python:

import mysql.connector

connection = mysql.connector.connect(
    host="localhost",
    port=3306,
    user="root",
    password="kodkod",
    database="school",
)
connection.close()
  • mysql.connector.connect(...) — открывает сетевое соединение с сервером. Если сервер не запущен — ошибка.
  • port=3306 — значение по умолчанию, его можно не указывать.

Первый пример кода

Настройка базы для этих тем, шаг за шагом.

1. Запустите MySQL (Docker Desktop должен быть открыт):

docker run --name kodkod-mysql `
  -e MYSQL_ROOT_PASSWORD=kodkod `
  -e MYSQL_DATABASE=school `
  -p 3306:3306 -d mysql:8.4
docker ps

При первом запуске Docker скачивает образ (несколько минут). docker ps показывает, что контейнер работает:

CONTAINER ID   IMAGE       STATUS         PORTS                    NAMES
ffaa661f5047   mysql:8.4   Up 10 seconds  0.0.0.0:3306->3306/tcp   kodkod-mysql

2. Подключитесь из VS Code:

  1. Вкладка Extensions → найдите Database Client (автор Weijan Chen) → Install.
  2. В боковой панели появится значок базы данных. Щёлкните по нему → + (Create Connection) → выберите MySQL.
  3. Заполните: Host 127.0.0.1, Port 3306, Username root, Password kodkod, Database school → Connect.
  4. Подключение появится в дереве, а внутри — база school, пока без таблиц.

3. Проект на Python:

mkdir ~\dev\kodkod6\week-4\school-db
cd ~\dev\kodkod6\week-4\school-db
git init
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install mysql-connector-python

.gitignore:

__pycache__/
.venv/
.env

setup_db.py:

import os

import mysql.connector

connection = mysql.connector.connect(
    host="localhost",
    port=3306,
    user="root",
    password=os.environ.get("DB_PASSWORD", "kodkod"),
    database="school",
)
print("Connected:", connection.is_connected())
print("Server version:", connection.server_info)
connection.close()
print("Connected after close:", connection.is_connected())

Вывод:

Connected: True
Server version: 8.4.11
Connected after close: False

Разбор кода построчно

КодОбъяснение
import mysql.connectorДрайвер. Устанавливается через pip install mysql-connector-python.
host="localhost", port=3306Где сервер: наш компьютер, на порту, который мы открыли через -p 3306:3306.
user="root"Главный пользователь MySQL.
os.environ.get("DB_PASSWORD", "kodkod")Пароль — из переменной окружения, если она задана, иначе значение по умолчанию учебной среды.
database="school"База, созданная через -e MYSQL_DATABASE=school.
connection.is_connected()True — соединение открыто.
connection.server_infoВерсия сервера MySQL. У вас номер может отличаться.
connection.close()Закрывает соединение (в следующем уроке — почему это важно).
Нет *.db в .gitignoreДанные находятся в контейнере, а не в папке проекта. В Git попадает только код, который создаёт структуру.

Ещё один пример

Контейнер после перезагрузки компьютера

После перезагрузки (Restart) Docker Desktop запускается — но контейнер не работает. Снова выполнить docker run? Нет — имя kodkod-mysql уже занято:

docker: Error response from daemon: Conflict. The container name "/kodkod-mysql" is already in use by container ...

Контейнер существует, он просто остановлен. Запустите его:

docker start kodkod-mysql

Все данные сохранились — таблицы и строки остаются в контейнере, пока вы его не удалите (docker rm).

Когда сервер не запущен

Если Docker Desktop закрыт или контейнер остановлен, подключение из Python не удаётся:

mysql.connector.errors.InterfaceError: 2003: Can't connect to MySQL server on 'localhost:3306' (Errno 10061: No connection could be made because the target machine actively refused it)

Can't connect = порт 3306 никто не слушает. Проверьте через docker ps и запустите через docker start kodkod-mysql.

Типичная ошибка

Ошибка 1: Docker Desktop не открыт.

failed to connect to the docker API ... The system cannot find the file specified.

Команды docker общаются с Docker Desktop. Откройте его, дождитесь окончания запуска и попробуйте снова.

Ошибка 2: порт занят.

Bind for 0.0.0.0:3306 failed: port is already allocated

На порту 3306 уже что-то работает — обычно MySQL, когда-то установленный прямо на компьютер. Можно использовать другой порт на нашем компьютере: -p 3307:3306, а затем подключаться с port=3307.

Ошибка 3: пароль от базы в коде, который попадает на GitHub.

connection = mysql.connector.connect(host="prod-db.company.com", user="admin", password="MyRealPassword123")

Даже если удалить его в следующем Commit, пароль остаётся в истории (вспомните тему Git!). Переменные окружения / .env в .gitignore. (Наш пароль kodkod — только для локальной учебной среды.)

Итоги

  • MySQL = сервер базы данных: процесс, который слушает порт 3306, и к нему подключаются по сети.
  • Docker запускает MySQL внутри контейнера — одной командой и одинаково у всех. docker run — один раз, а затем docker start kodkod-mysql.
  • Database Client (расширение VS Code) = интерфейс к базе: дерево таблиц, выполнение SQL и результаты в виде таблицы.
  • Драйвер = библиотека, которая переводит между Python и базой. Для MySQL: mysql-connector-python (import mysql.connector).
  • Пять данных для подключения: host, port, user, password, database.
  • Пароли не пишут в коде: переменные окружения или .env в .gitignore.

Официальная документация

Практика

Упражнения опираются только на то, что пройдено в этом уроке и в предыдущих. Сначала попробуйте сами, и только потом открывайте решение.

Упражнение 1: Таблица, строка, столбец

id | name | age | email
---+------+-----+---------------
 1 | Dana |  24 | dana@mail.com
 2 | Avi  |  31 | avi@mail.com
  1. Сколько в таблице строк и сколько столбцов?
  2. Что описывает каждая строка и что описывает каждый столбец?
  3. Какой столбец подходит на роль первичного ключа и почему не name?
Показать решение
  1. 2 строки и 4 столбца.
  2. Каждая строка (Row) — один студент, запись. Каждый столбец (Column) — одно поле с фиксированным типом, которое есть у всех студентов.
  3. id — он уникален, никогда не меняется и создаётся автоматически. name не подходит: может быть два студента по имени Дана, а имя может измениться.

Упражнение 2: Типы и ограничения

Напишите команду SQL, которая создаёт таблицу students с:

  • id — целое число, первичный ключ, создаётся автоматически;
  • name — текст, обязательный;
  • age — целое число, обязательное;
  • email — текст, обязательный и уникальный.
Показать решение
CREATE TABLE students (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    age INT NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE
);
  • INT / VARCHAR(100) — тип каждого столбца: целое число и текст до 100 символов.
  • NOT NULL — нельзя оставить пустым.
  • UNIQUE — нет двух студентов с одинаковым email.
  • AUTO_INCREMENT — база сама выбирает id.

Упражнение 3: Что поймала бы база?

students = [
    {"name": "Dana", "age": 24, "email": "d@x.com"},
    {"name": "Avi", "age": 24, "email": None},
    {"name": "Noa", "age": 22, "email": "d@x.com"},
]

Какие из этих данных отклонила бы таблица students из предыдущего упражнения и из-за какого ограничения? И почему их никто не остановил в списке Python?

Показать решение
  • Ави — email равен None → отклонено из-за NOT NULL.
  • Ноа — тот же email, что у Даны → отклонено из-за UNIQUE.
  • Дана — допустимо.

У списка Python нет правил: туда попадает любое значение. В базе данных правила определяются один раз, в таблице, и действуют для всех, кто в неё пишет, — из любой программы.

Упражнение 4: Запуск MySQL

  1. Что делает каждая часть следующей команды?
  2. Как проверить, что контейнер работает?
  3. Как запустить его снова после перезагрузки компьютера — не создавая новый?
docker run --name kodkod-mysql -e MYSQL_ROOT_PASSWORD=kodkod -e MYSQL_DATABASE=school -p 3306:3306 -d mysql:8.4
Показать решение
ЧастьЗначение
docker runСоздаёт и запускает новый контейнер
--name kodkod-mysqlИмя контейнера, чтобы к нему обращаться
-e MYSQL_ROOT_PASSWORD=kodkodПароль пользователя root
-e MYSQL_DATABASE=schoolБаза с именем school, которая создаётся автоматически
-p 3306:3306Порт 3306 на нашем компьютере ведёт к MySQL в контейнере
-dРаботает в фоне, терминал остаётся свободным
mysql:8.4Образ (Image): MySQL версии 8.4
  1. docker ps — показывает контейнеры, которые работают прямо сейчас.
  2. docker start kodkod-mysql — запускает существующий контейнер. Его данные сохраняются. Повторный docker run не сработал бы, потому что имя уже занято.

Упражнение 5: Первое подключение

Напишите код, который подключается к базе school в контейнере, печатает, активно ли соединение, закрывает его и печатает снова.

Ожидаемый вывод:

Connected: True
Connected after close: False
Показать решение
import mysql.connector

connection = mysql.connector.connect(
    host="localhost",
    port=3306,
    user="root",
    password="kodkod",
    database="school",
)
print("Connected:", connection.is_connected())
connection.close()
print("Connected after close:", connection.is_connected())
Connected: True
Connected after close: False

mysql.connector.connect открывает сетевое соединение с сервером MySQL в контейнере. Если контейнер не запущен — вы получите ошибку: Can't connect to MySQL server.