docker Информация с хабра

Теория

Немного терминов

Образ (Image)

Это шаблон, из которого  запускаются контейнеры. В нём уже есть всё, что нужно приложению: системные библиотеки, зависимости, код и настройки.

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

Контейнер (Container)

Это изолированная среда, в которой работает приложение. Контейнер можно запускать, останавливать и удалять, не затрагивая исходный образ.

Когда он удаляется, его данные исчезают — поэтому для постоянного хранения используется следующий механизм.

Том (Volume)

Это место для данных, которые должны сохраняться между перезапусками. Тома подключаются к контейнерам как внешние диски: всё, что записано в них, остаётся даже после удаления контейнера.

Так обычно хранят базы данных, логи и другие важные файлы.

Сеть (Network)

Отвечает за взаимодействие контейнеров между собой и с внешним миром. Docker автоматически создаёт bridge-сеть, где каждый контейнер получает свой IP-адрес.

Можно объединять контейнеры в собственные сети или, наоборот, изолировать их, если требуется полная автономность.

Реестр (Registry)

Реестр — это место, где хранятся Docker-образы. 

Публичный вариант — Docker Hub, в нём размещены миллионы готовых сборок, включая официальные (nginx, Redis, Python).  Если образы должны оставаться внутри компании, разворачивают собственный Docker Registry — тот же сервер хранения, но с ограниченным доступом.

Сеть

-p 8080:80 делает порт 80 контейнера доступным по адресу 8080 на хосте).

Кроме стандартной сети есть и другие режимы:

  • host — контейнер работает в сетевом пространстве хоста и использует его IP-адрес и интерфейсы. Режим без изоляции, зато с максимальной производительностью. Подходит, если сервису нужен прямой доступ к сети.

  • none — сеть полностью отключена. Контейнер не получает IP, не выходит в интернет и не принимает входящие запросы. Подходит для задач, которые работают изолированно и не используют сеть. 

  • overlay — объединяет контейнеры, запущенные на разных машинах, в одну виртуальную сеть. Такой тип используется, когда приложение развёрнуто на нескольких серверах и между ними нужно наладить связь.

  • macvlan — каждому контейнеру назначается собственный MAC-адрес, и в локальной сети он виден как отдельное устройство. Это удобно для тестирования сетевых сервисов или если контейнер должен работать наравне с другими машинами.

Логи

docker logs

В продакшене часто выбирают другие драйверы:

  • journald — чтобы писать логи в системный журнал Linux;

  • syslog — для отправки логов на внешний сервер;

  • fluentd — для сбора и анализа данных в распределённых системах.

Помимо логов Docker фиксирует события — всё, что происходит в системе: запуск или остановка контейнера, создание или удаление, загрузка образа, подключение тома. Эти данные доступны через API или команду docker events.

Практика?

База

Установка

apt install docker-io -y

Проверка работа докера

Должен скачать контейнер, после чего вывести приветственное сообщение.

docker run hello-world

Установка nginx

docker run -d -p 8080:80 nginx

Что здесь происходит:

  1. docker run — создаёт контейнер из указанного образа (в данном случае nginx);
  2. если образа нет локально, Docker автоматически скачает его с Docker Hub;
  3. флаг -d запускает контейнер в фоновом режиме (detached);
  4. -p 8080:80 пробрасывает порт 80 внутри контейнера на порт 8080 вашей машины.

Посмотреть контейнеры

docker ps -a

Зайти в контейнер

При создании

docker run -it ubuntu bash

После создания

docker exec -it <id> bash

Логи и т.д

Чтобы узнать подробнее, как запущен контейнер и какие у него настройки, выполните:

docker inspect <id>

Если нужно быстро понять, что происходит внутри контейнера, не заходя в него вручную (например, просмотреть вывод приложения), используйте команду:

docker logs <id>

Управление контейнерами

Если контейнер нужно приостановить, используйте:

docker stop <id>

Контейнер останется в списке и при желании его можно снова запустить командой:

docker start <id>

Когда контейнер больше не нужен, его можно удалить:

docker rm -f <id>

-f Это принудительное удаление ( даже если запущен)

Образы

Посмотреть список локальных образов можно так:

docker images

А удалить ненужные с помощью команды:

docker rmi <image>

Чтобы быстро очистить всё, что не используется (остановленные контейнеры, старые образы, неактивные сети), есть команда:

docker system prune

Создание своего образа

Пример простого Dockerfile:

FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

Что здесь происходит:

  • FROM — задаёт базовый образ, от которого наследуется ваш;
  • WORKDIR — создаёт рабочую директорию внутри контейнера;
  • COPY — копирует файлы проекта с компьютера в образ;
  • RUN — выполняет команды при сборке (например, установка библиотек);
  • CMD — указывает, что делать при запуске контейнера.

Важно: когда контейнер запускается, процессы внутри него по умолчанию работают с правами root. Чтобы снизить эти риски, в Dockerfile часто добавляют собственного пользователя и запускают приложение уже от его имени. Сделать это можно буквально в пару строк:

RUN useradd -m appuser
USER appuser

ENTRYPOINT: второй способ задать команду запуска

Чем отличаются:

  • CMD — это команда по умолчанию. Если при запуске контейнера (docker run) вы передаёте свои аргументы, Docker заменяет CMD на то, что вы указали.

  • ENTRYPOINT — это фиксированная основа команды. Она всегда выполняется, а аргументы из docker run просто добавляются к ней.

ENTRYPOINT ["python", "app.py"]
CMD ["--port", "8000"]

ENTRYPOINT задаёт программу, которую контейнер запускает всегда —
в нашем случае это python app.py. CMD добавляет аргументы по умолчанию. То есть Docker склеивает их и при обычном запуске выполнит:

python app.py --port 8000

Если при запуске указать свои параметры. Docker возьмёт ENTRYPOINT и добавит ваши аргументы, заменив CMD:

docker run myapp --port 9000

Примеры посложнее

Сначала в папке проекта должны лежать три файла:

myapp/
├─ app.py
├─ requirements.txt
└─ Dockerfile

В app.py напишем простейшее приложение на Python. Оно будет показывать строку “Hello from Docker!”, когда вы откроете страницу в браузере:

from http.server import HTTPServer, BaseHTTPRequestHandler

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b"Hello from Docker!")

if __name__ == "__main__":
    HTTPServer(("0.0.0.0", 8000), Handler).serve_forever()

Файл requirements.txt нужен, чтобы перечислить зависимости проекта. Если их нет — можно оставить его пустым.

Собираем образ

Теперь откройте терминал, перейдите в папку myapp и выполните:

docker build -t myapp .

Флаг -t задаёт имя образа, а точка в конце указывает путь к контексту сборки — папке, где лежит Dockerfile и файлы проекта. После выполнения команды Docker по шагам прочитает Dockerfile и соберёт новый образ.

Запускаем контейнер

Мы уже пробовали запускать контейнер с Nginx. Теперь сделаем то же самое, но с собственным образом:

docker run -d -p 8000:8000 myapp

Тег — это просто метка версии. Если его не указать, Docker присвоит latest, но лучше явно обозначать версии:

docker build -t myapp:1.0 .

Docker Hub

1. Создайте репозиторий на Docker Hub

Зайдите в свой аккаунт на https://hub.docker.com/ и вручную создайте новый репозиторий — так же, как создают новый проект на GitHub.

Название репозитория должно совпадать с тем, что вы будете использовать в команде docker push.

Это важный шаг: Docker не создаёт репозитории автоматически.

2. Переименуйте образ

Перед загрузкой образ нужно оформить в правильном формате:

username/repository:tag

где:

  • username — ваш логин на Docker Hub,

  • repository — имя проекта,

  • tag — версия образа (например, 1.0).

Пример:

docker tag myapp:1.0 username/myapp:1.0

3. Войдите в Docker Hub

Авторизуйтесь через команду:

docker login

Docker попросит ввести логин и пароль от вашего аккаунта. После успешного входа появится сообщение вроде Login Succeeded.

4. Отправьте образ в репозиторий

Выполните команду:

docker push username/myapp:1.0

Docker начнёт загружать образ в ваш репозиторий на Docker Hub.

Когда загрузка закончится, образ появится в вашем профиле и станет доступен другим (если репозиторий публичный).

5. Загрузите образ на другом компьютере

Чтобы использовать тот же образ на другой машине, выполните:

docker pull username/myapp:1.0

Docker скачает только нужные слои — если часть уже есть локально, она не будет загружаться заново.

После этого образ можно запустить как обычно:

docker run -d -p 8000:8000 username/myapp:1.0

Docker Compose

Docker Compose позволяет описать все нужные контейнеры и их настройки в одном файле — docker-compose.yml. После этого весь проект можно запустить одной командой.

Пример простого docker-compose.yml:  

services:
  web:
    build: .
    ports:
      - "8000:8000"
 
  redis:
    image: redis:alpine

Что здесь происходит:

  • services — список контейнеров, которые нужно запустить;

  • web — наш основной сервис, собирается из текущей директории (build: .) и открывает порт 8000;

  • redis — дополнительный контейнер, разворачивается из готового образа redis:alpine.

Как это работает

Сохраните файл и выполните команду:

docker compose up

Docker соберёт образы, создаст контейнеры, подключит сеть и запустит всё вместе.

Чтобы остановить проект, выполните команду: 

docker compose down