Представьте: вы написали программу. На вашем компьютере всё работает идеально. Вы отправляете код коллеге. Он скачивает, запускает — и получает:
ModuleNotFoundError: No module named 'flask'
Error: connect ECONNREFUSED 127.0.0.1:5432
python3: command not found
Три ошибки. Ни одна не связана с вашим кодом — он правильный. Проблема в другом: у коллеги не установлен Flask, нет базы данных, а Python называется python, а не python3. Его компьютер — это другая планета с другой атмосферой. Ваше приложение там задыхается.
«У меня на машине работает!» — самая бесполезная фраза в истории разработки.
Docker создан, чтобы эта фраза потеряла смысл. Он упаковывает приложение вместе со всем, что ему нужно — код, зависимости, настройки, нужную версию языка — в одну «коробку». Эта коробка запустится одинаково на любом компьютере: вашем ноутбуке, ноутбуке коллеги, тестовом сервере, облаке Amazon.
Эта «коробка» называется контейнер.
Аналогия из жизни. Вы заказываете еду с доставкой. Курьер привозит не просто котлету — а контейнер с готовым блюдом: котлета, гарнир, соус, приборы, салфетка. Вам не нужно иметь дома плиту, сковородку и рецепт. Открываете контейнер — и едите. Docker работает так же: контейнер приезжает на сервер со всем необходимым, и серверу не нужно ничего доустанавливать. Чтобы не изучать Docker на абстрактных примерах, мы будем строить реальный проект — постепенно, от урока к уроку. Знакомьтесь: TaskMaster — консольный менеджер задач на Python.
Вот как он работает:
$ python taskmaster.py add "Купить молоко"
Добавлено: Купить молоко
$ python taskmaster.py add "Написать отчёт"
Добавлено: Написать отчёт
$ python taskmaster.py list
[ ] 1. Купить молоко
[ ] 2. Написать отчёт
$ python taskmaster.py done 1
Задача 1 выполнена!
$ python taskmaster.py list
[x] 1. Купить молоко
[ ] 2. Написать отчёт
$ python taskmaster.py stats
Всего: 2, выполнено: 1, осталось: 1
Простой и понятный. Четыре команды: add, list, done, stats. Задачи хранятся в JSON-файле. Никаких фреймворков, никаких баз данных — чистый Python, 40 строк кода.
А вот и сам код:
import json, sys, os
from datetime import datetime
DATA_FILE = os.environ.get("TASKS_FILE", "tasks.json")
def load():
try:
with open(DATA_FILE) as f:
return json.load(f)
except FileNotFoundError:
return []
def save(tasks):
with open(DATA_FILE, "w") as f:
json.dump(tasks, f, indent=2, ensure_ascii=False)
def main():
if len(sys.argv) < 2:
print("TaskMaster — менеджер задач")
print("Команды: add | list | done | stats")
return
cmd = sys.argv[1]
tasks = load()
if cmd == "add" and len(sys.argv) > 2:
text = " ".join(sys.argv[2:])
tasks.append({"text": text, "done": False, "created": datetime.now().isoformat()})
save(tasks)
print(f"Добавлено: {text}")
elif cmd == "list":
if not tasks:
print("Задач нет.")
for i, t in enumerate(tasks, 1):
mark = "[x]" if t["done"] else "[ ]"
print(f" {mark} {i}. {t['text']}")
elif cmd == "done" and len(sys.argv) > 2:
n = int(sys.argv[2])
tasks[n - 1]["done"] = True
save(tasks)
print(f"Задача {n} выполнена!")
elif cmd == "stats":
total = len(tasks)
done = sum(1 for t in tasks if t["done"])
print(f"Всего: {total}, выполнено: {done}, осталось: {total - done}")
if __name__ == "__main__":
main()
Сохраните этот код в файл taskmaster.py — он нам понадобится уже через пару уроков. На протяжении курса мы будем развивать TaskMaster: сначала запустим его в контейнере, потом напишем Dockerfile, подключим базу данных, настроим Docker Compose, задеплоим на сервер. Каждая новая тема Docker — новая возможность для нашего приложения.
Теперь давайте посмотрим, почему TaskMaster — идеальный пример «проблемы окружений».
Вы написали этот скрипт на своём компьютере с Python 3.11. Всё работает. Отправили коллеге. А у коллеги:
— Сценарий 1: Python не установлен вообще. python: command not found. Нужно скачать, установить, настроить PATH. Полчаса.
— Сценарий 2: Python установлен, но версия 3.7. F-строки (f"Добавлено: {text}") работают, но вы использовали фичу из 3.9 — и код падает с загадочной ошибкой.
— Сценарий 3: На Windows Python называется py, на macOS — python3, на Linux — где как. Скрипт запуска не универсален.
А теперь представьте, что в проекте не 40 строк, а 40 000. Не чистый Python, а Flask + SQLAlchemy + Redis + Celery + десяток других библиотек конкретных версий. У коллеги другая ОС, другие системные библиотеки, другая кодировка по умолчанию. Каждое различие — потенциальная ошибка, а различий — десятки.
Docker решает это радикально: вместо инструкции «установи Python 3.11, потом pip install, потом...» вы говорите:
docker run taskmaster add "Купить молоко"
Одна команда. Python нужной версии, все зависимости, правильная кодировка — всё уже внутри контейнера. Коллеге не нужно ничего устанавливать, кроме самого Docker. Docker — не только про «запустить у коллеги». Вот ситуации, в которых вы окажетесь рано или поздно:
Пятница, 18:00. Нужно выкатить новую версию на сервер. Без Docker — вы заходите по SSH, обновляете код, ставите зависимости, правите конфиги, перезапускаете, проверяете... и понимаете, что на сервере другая версия библиотеки. Час убит. С Docker — одна команда, и новая версия работает. Потому что сервер запускает тот же контейнер, что и ваш ноутбук.
У вас два проекта: один на Python 3.9, другой на Python 3.11. Без Docker они конфликтуют — на компьютере может быть только один системный Python. С Docker каждый проект живёт в своём контейнере и не знает о существовании другого.
TaskMaster разрастётся: приложение, база данных, кэш, веб-сервер — четыре компонента, которые должны работать вместе. Docker Compose позволит описать их в одном файле и поднять одной командой. Мы дойдём до этого ближе к середине курса.
Docker решает проблему «у меня на машине работает» — упаковывает приложение со всеми зависимостями в контейнер, который работает одинаково везде.
Контейнер — изолированная среда с приложением и всем необходимым: кодом, библиотеками, настройками, нужной версией языка.
TaskMaster — наш сквозной проект на весь курс: консольный менеджер задач на Python. Начинаем с простого скрипта (40 строк), постепенно упаковываем в Docker, подключаем базу данных, настраиваем Compose, деплоим на сервер.
Типичные сценарии Docker: единое окружение для команды, изоляция проектов, развёртывание на серверах, CI/CD, микросервисы.