Skip to content

cucumberian/tutorial_docker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

docker build . - создание образа из текущей директории docker build -t hello_world . - создание образа из текущей директории(.) с (-t)именем. В текущей директории должен быть Dockerfile

Любая команда в докерфайле создает новый слой именджа. Поэтому иногда объединяют команды, чтобы уменьшить уоличество слоев.

Команда Описание
FROM задаёт базовый образ
ARG задаёт переменные, используемый при сборке образа
LABEL описывает метаданные, например, автора образа
ENV задаёт переменные среды в образе
RUN выполняет команду, например установку пакетов внутри образа
COPY копирует в контейнер файлы и папки
ADD копирует в контейнер файлы или папки
WORKDIR задаёт рабочую директорию
EXPOSE описывает с какими портами работает контейнер
VOLUME монтирует директории для хранения данных контейнера на хостовой ОС
ENTRYPOINT выполняет команду с аргументами после запуска контейнера. Команда и аргументы не перезаписываются в командной строке запуска контейнера.
CMD выполняет команду с аргументами после запуска контейнера. Команда и аргументы перезаписываются командой в командной строке запуска контейнера.
FROM python:3.10

RUN mkdir -p /usr/src/app/
WORKDIR /usr/src/app/
COPY . /usr/src/app/

CMD ["python", "app.py"]

FROM - базовый образ из которого начинается сборка

RUN - выполнение команды на стороне докера WORKDIR - установить директорию как рабочий каталог и начать выполнение всех команд оттуда COPY . /usr/src/app/ - копирование с локальной машины в контейнер

Если в докерфайле содержится несколько записей ENTRYPOINT и CMD:

ENTRYPOINT [ "php-fpm", "-c"]
CMD ["/var/www"]

то непосредственно исполняемой частью является первый элемент из ENTRYPOINT``, все остальные элементы будут являться параметрами команды. CMD``может перезаписаться через командную строку запуска контейнера.docker run -d <image_name> /var/www2- в этом случае останется`ENTRYPOINT`со значением`php-fpm -c`и к нему добавиться параметр`/var/www2`, т.о. при запуске контейнера будет выполняться команда `php-fpm -c /var/www2`.

docker run --name hello <image_name> - запуск контейнера c именем(--name) hello на основе образа image_name Контейнер работает до тех пор пока работает команда, которая выполняется при запуске

docker rm <container_id | container_name -удаление контейнера по id или его имени docker rm $(docker ps -a -q) - вывести id и передать их команде удаления контейнеров docker build --t hello-world docker run --name hello -d hello-world - запуск контейнера с именем(--name) hello из image (hello-world) в фоне (-d) docker stop <имя или id> - остановить контейнер c заданным именем или id docker run --rm hello-world - запуск контейнера из image, который удалится как отработает или будет остановлен

FROM python:3.10-alpine

RUN mkdir -p /usr/src/app/
WORKDIR /usr/src/app/

COPY app.py ./
COPY payload.json ./
COPY requirements.txt ./

RUN pip install -r --no-cache-dir requirements.txt

# декларация о том, что открываем порт
EXPOSE 8080

CMD ["python", "app.py"]

docker run --rm -p 8080: 1234

Переменные окружения

Указание переменной окружения в докерфайле

ENV TZ Europe/Moscow

Через параметр при запуске контейнера

docker run --rm -d --name web -e TZ=Europe/Moscow web-hello

Запуск с контейнером с заданно1 переменной окружения.

docker-compose

docker-compose -f ./docker-compose.yml up -d - стартовать все сервисы в контейнерах для указанного докер-компоуз файла docker-compose ps - запущенные контейнеры в рамках компоуза docker-compose logs service_name - логи сервиса docker-compose exec service_name bash - выполнить bash внутри сервиса docker-compose restart service_name - перезапустить контейнер для сервиса docker-compose stop service_name - остановить контейнер для сервиса docker-compose start service_name - запустить контейнер для сервиса docker-compose up --force-recreate --no-deps -d service_name - пересоздать контейнер для сервиса service_name, не трогая все зависимые контейнеры.

Внешние источники Volumes

1 - монтирование папки 2 - монтирование образа

Монтирование папки

docker run -v /host/path:/docker/path

Docker 1

Контейнеризация - это изоляция на уровне процессов. Фактически все процессы контейнеров работают на хостовой машине. Виртуализация:

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

Контейнеризация

  • легкие виртуальный процессы
  • изоляция на уровне встроенных механизмов в unix-live системах, cgroups, namespaces, и др Накладные расходы в докере на разных системах. На маке и винде - докер десктоп запускает виртуалку (wsl linux). А в линуксе на докере почти нулевые накладные расходы.
  • используется только одно ядро ос
  • возможны ограничения ресурсов по цпу, рам, сети и т.д. контейнера могут есть все ресурсы хоста
  • реализации
    • докер
    • LXC
    • OpenVZ (Virtuozzo)

Преимущеста

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

Микросервисная архитектура

Раньше были монолитные приложения. Сейчас микросервисная архитектура. Система разита на изолированные части. Они могут разрабатываться разными командами на разных языках. Чтобы спокойно деплоить микросервисы растер количество манипуляция для деплоя проекта в продакшен среде.

Архитектура докера

  • докер демон (сервер) docker-d
  • клиент (команда докер). команды по работе с образами и контейнерами.
  • клиент и сервер взаимодействую по rest api (можно посмотреть)

Чаще всего все микросервисы располагаются в одном кластере и задержки по цепочкам вызовов не оч большие. По типу взаимодействия - http вызовы и очереди. Например в асинхронном варианте, А запрашивает документ у Б. Б отвечает ид документа и начинает работать. Дальше А и Б взаимодействуют через очередь (Kafka, Rabbit) - брокеры сообщений. Либо они могут общаться напрямую через очередь

Компоненты

  • образы images - дистрибутивы для контейнеров
  • контейнеры containers - рабочие образы
  • сети networks - передача данных
  • тома volumes - хранение данных

Images Образы

  • готовы к использованию
  • есть открытый реестр register (есть и закрытые)
  • можно собирать новые на основе существующих
  • состоит из слоёв
    • что такое слои в докере и как они работают
    • каждая команда в докерфайле создает определенный слой - несколько команд, например при установке пакетов лучше минимизировать количество строк Чтобы экономить слои - схлопывают команды ран в одну длинную команду. Зачем экономить слои? Сам докер кэширует слои - создает на файловой системе хостовой машины определенные папки с названиями через хэш функцию Если что-то поменялось в слое, то все последующие слои обязаны будут пересобраться в 99.9% случаев

Монтирование файловой системы

Сети в Докер

  • bridge - режим по умолчанию, изоляция NAT
    • есть дефолтная сеть в рамках которой запускаются все контейнеры
    • можно создать свои сети docker run ubuntu У каждого контейнера появляется свой ip адрес.
  • host отсутствует изоляция, полный доступ к хосту docker run --network=host ubuntu Используется редко, например когда контейнер наружу выставляет много портов. Или когда нужно повысить производительность (нет сетевой абстракции (трансляции сетевых адресов) вряд ли и большой выигрыш) У контейнера нет своего ip адреса в рамках докера.
  • overlay - связь между контейнерами на разных хостах в единую сеть чтобы они имели сетевую связность два компьютера могут быть соединены между собой проводом - это называется сетевой доступностью (можно отправить пинг и есть сеть). Две остовые системы могут быть связаны и чтобы два контейнера на этих системах также могли между собой общаться придется лио плясать с бриджем, либо выбрать host и там и там и контейнеры будут в сетевой доступности. Но host убирает изоляцию, что неправильно. Поэтому придумали overlay
  • ipvalan - сеть на уровне IP (L2, 802.1q trunk L2, L3)
  • macvlan - создание отдельных интерфейсов с MAC-адресами (bridge, 802.1q trunk bridge) при старте контейнера он на хостовой системе создаёт виртуальное сетевое устройство
  • none - отсутствие доступа к сети из контейнера docker run --network=none ubuntu

Тома в докер

  • bind mount - подключение к ФС хоста Опасно. Нарушение изоляции. Любая программа может придти в ФС и попортить что-то.

  • volume - том в докер Выделяется некоторое пространство в файловой системе хоста докером. Именуется и туда имеем возможность записывать постоянные данные контейнер. Например при разработке приложения, можно подмонтировать папку src и процесс в докере может отслеживать изменения в этой папке и перезапускать сборку проекта при обнаружении изменений.

  • tmpfs mount- монтирование в RAM -

    • быстро
    • данные могут быстро пропасть

Логирование в докер

  • логи хранятся вне контейнера
  • локальное хранения (journald, syslog) - или централизованное (gelf, fluentd)
  • docker logs nginx
  • docker logs nginx --follow
    • автообновление логов с просмотром последних событий
  • docker logs --tail 100 nginx
    • последние 100 строк в логах
  • docker logs --until 10m nginx
    • не более 10 мегабайт логов
  • docker logs --since 2023-10-20T10:00:00 nginx
    • логи с определенного момента

Основные команды докер

  • docker info информация о докере
  • docker run hello-world
    • запуск контейнера из образа
  • docker run --rm -d --network host --name my_nginx nginx
    • запуск контейнера в фоне(-d) с именем (-name) в режиме автоудаления после выполнения(--rm) также в режиме сети хоста, когда все порты контейнера являются портами хоста
  • docker run -d --name nginx -p 80:80 -v /var/www/html/:/usr/share/nginx/html nginx
    • запуск nginx контейнера в режиме сети bridge(по-умолчанию) c с прикреплением к хостовой машине 80 порта и подключением папки хоста (-v) /var/ww/html/ как папки в докере /usr/share/nginx/html
  • docker search nginx
    • поиск всех именджов нгинкс и доступных регистрах
  • docker ps -a

Работа с контейнером

  • docker exec -ti nginx bash
    • выполнить (exec) в интерактивном режиме(-i) команду (bash) - откроется терминал. (провалиться внутрь терминала контейнера). Обычно залезание внутрь контейнера является плохой практикой. Т.к. после пересоздания контейнера все изменения затираются за исключением примонтированных volumes или прикрепленных папок.
  • docker start|stop|restart nginx запуск, остановка, перезапуск определенного контейнера команды похожие на systemctl
  • docker inspect nginx
    • информация по контейнеру - все конфиги
  • docker top nginx
    • показать процессы этого контейнера - аналог команды top
  • docker stats nginx | dockers stats
    • показать статистику в реальном времени - по контейнеру или по всем контейнерам статистика показывается применительно к контейнеру - например потребление cpu считается в процентах от cpu ядра контейнера, а не cpu ядра хоста - LIMIT - сколько контейнер может съест хостовой оперативки -
  • docker rm nginx удаление остановленного контейнера nginx
  • docker rm -f nginx - force remove - удаление даже работающего контейнера.

Работа с образами

  • docker images - список образов на хосте
  • docker pull nginx:1.20 - загрузить на хост из регистра образ nginx версии 1.20
  • docker rmi nginx - удалить образ nginx
  • docker build -t webserver . - собрать из докерфайла в текущей директории(.) имедж и назвать его (-t) webserver

Работа с томами

При работе с контейнерами флаг -v создается новый волюм со случайным именем. Если задать имя после флага -v, то подключится уже существующий волюм.

  • docker volume ls - список томов на хосте
  • docker volume crate storage1 - создание локального тома
  • docker volume rm storage1 - удаление тома

Работа с сетями

По-умолчанию при создании контейнера для него создается сеть bridge с именем как у контейнера.

  • docker network ls - список сетей на хосте
  • docker network create --driver bridge alpine-net - создание новой сети типа bridge
  • docker network create my-net - создание новой сети (типа bridge - по-умолчанию)
  • docker network rm my-net - удаление существующей сети
  • docker run -p 127.0.0.1:8080:80 nginx - запуск контейнера в сети типа bridge и прокинуть порт на локалхост портхоста:портдокера
  • docker run -p 8080:80 nginx - запуск контейнера с пробрасыванием порта с 0.0.0.0:8080 на 80 порт контейнера
  • docker network inspect bridge - инспекция настроек сети
  • docker run --network <network_name> <image> - запуск контейнера в определённой сети.

При использовании контейнеров с дефолтной сетью нельзя к ним обращаться по имени, а можно только по ip-адресу. Адрес можно узнать с помощью команды docker inspect <container>. Если использовать пользовтельскую сеть, то к контейнерам внутри сети можно будет обращаться по их имени. docker network create <network_name> - создание пользовтельской сети

Docker 2. Сборка образа. Dockerfile. Multistage образы.

Задача: развернуть приложение на Go

  1. Проинспектировать приложение

  2. Держим код в порядке:

    • отдельная папка для декерфайла Зачем нужна отельная папка для докерфайла?
      • для разных окружений (тест, дев), может у одного приложения, развёрнутого на разных клиентах могут быть разные докерфайлы
    • название Dockerfile
    mkdir docker
    cd docker
    vim Dockerfile
  3. Ищем базовый образ

    • Docker Hub
    • обращаем внимание на бейджи (офиц. версия)
    • смотрим на версии
    • docker pull golang:1.21 - качаем докерфайл
  4. Dockerfile

    FROM golang:1.21
    
    # копирование из текущей папки (из места сборки)
    # в терминале в папку по-дефолту внутри контейнера
    COPY . .
    
    
  5. Создание образа и его проверка Если докерфайл лежит не там, откуда будет происходить сборка, то необходимо указать путь к докерфайлу и место сборки (последний аргумент). Место сборки будет тем местом, из которого мы копируем файлы.

    • -t - флаг тега
    • -f - флаг файла
    • .. - указатель на директорию, в которой будет происходить сборка (у нас докерфайл лежит)
    docker build -t test -f ./docker/Dockerfile .

    Запуск контйенера из образа test и выполнение в нем bash в интерактивном режиме(-t)

    docker run -it test bash

    Билдим приложение на go внутри контейнера

    go build main.go

    Запускаем приложение внутри контейнера

    ./main
  6. Дописываем докерфайл полностью https://docs.docker.com/engine/reference/builder/#from

    FROM golang:1.21
    COPY . .
    RUN go build ./main.go
    CMD ["./main"]
    • CMD - говорит нам что именно будет являться нашим процессом с id=1. docker top - показывает процессы, которые будут запущены внутри контейнера. У каждого процесса внутри контейнера будет свой ид. Если процесс с ид=1 умрёт, свалится, остановится, то остановится и контейнер. Это позволяет определить жизненный цикл контейнера.
  7. Пересобираем образ из обновленного докерфайла

    docker build -t test -f ./docker/Dockerfile .

    Т.к. мы использовали такое же название, то предыдущий имедж с таким названием потерял свой тэг и стал <none>

  8. Запускаем контейнер и проверяем

    docker run --rm test
    • --rm - после остановки контейнера - удалить его и почистить все его артефакты. Best practice для недолгоиграющих контейнеров. По-умолчанию контейнер запускается в режиме сети bridge и хост не знает о том что работает докер контейнер с открытым портом.
    docker run --rm -p 8888:80 test

    Вот так привязываем локальный порт 80 к порту докера 8888. Некоторые флаги в докере работают без пробела.

  9. Проблема больших образов. Есть супер маленькие образы alpine.

    FROM golang:1.21 as build
    COPY . .
    RUN CGO_ENABLED=0 go build ./main.go
    
    FROM alpine:
    COPY ./static ./static
    COPY --from=build /app/main ./
    CMD ["./main"]

    as build - именование, говорит о том, что этот этап - шаг под именем build CGO_ENABLEd=0 - установка переменной окружения (специфична для го). Нужна для того, чтобы в образе альпайна хватило модулей для запуска го.

    Т.о. на первом этапе мф копируем исходники и компилируем. Шаг 2 - FROM alpine COPY ./static ./static - копируем каталог хоста COPY --from=build /go/main . - копируем бинарный файл main в базовую папку образа alpine/ CMD ['./main'] - устанавливаем 1й процесс контейнера как >/main

  10. Получившийся образ можно загрузить в локальный регистр образов.

Причёсываем образ

Hadolint - линтер для докерфайлов.

https://hadolint.github.io/hadolint - онлайн версия. Но лучше запускать его локальную версию - она дает больше подсказок.

docker run --rm -i hadolint/hadolint < docker/Dockerfile

Правим файл по подсказкам

FROM golang:1.21 as build
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build ./main.go

FROM alpine
WORKDIR /app
COPY ./static ./static
COPY --from=build /app/main ./
CMD ["./main"]

WORKDIR - указывает рабочую директорию

Удаляем всё лишнее

  • удаляем папку копирование докера на первой стадии
  • используем .dockerignore

.dockerignore

Не даёт копировать некоторые файлы при использовании команды COPY.

*ocker*
.idea
node_modules/
.env
WORKDIR /app
FROM golang:1.21 as build
COPY ./main.go ./
RUN CGO_ENABLED=0 go build ./main.go

FROM alpine:
WORKDIR /app
COPY ./static ./static
COPY --from build /app/main ./
CMD ["./main"]

Иногда можно встретить при сборке образа надпись CACHED - это значит что мы не выполнили реальную операцию из докерфайла, а взяли её результат из предыдущей операции (кэша).

В дистрибутиве альпина нет установленного bash, но есть sh: docker run --rm -it test /bin/sh - запуск в интерактивном режиме оболочки sh.

docker run --rm -d -p 8888:8888 test - запустить контейнер в фоновом режиме

Докер не может удалить имеджи на основе которых есть контейнеры, т.к. этот контейнер можем запустить. Можно использовать флаг -f или удалить контейнер.

docker exec -it nginx bash - запустить баш в работающем контейнере

Удаление

stackoverflow Докер не может удалить имеджи на основе которых есть контейнеры, т.к. этот контейнер можем запустить. Можно использовать флаг -f или удалить контейнер. Например в следующем примере создается на первом этапе сборка из react проекта, потом она копируется вместе с конфигом в образ с nginx:

FROM node:current-alpine3.19 as build
# задание метки созданному образу
LABEL stage=build
RUN mkdir /app/
WORKDIR /app/
COPY . .
RUN npm install && npm run build

FROM nginx:stable-alpine3.17
COPY nginx.conf /etc/nginx/conf.d/default.conf
RUN mkdir -p /www/site
COPY --from=build /app/dist/ /www/site/

В итоге получается промежуточный образ, который мы можем затем удалить с помощью команды docker image prune:

docker image prune --filter label=stage=build

Docker 3. Docker-compose. Обзор Cloud сервисов.

docker-compose

Докерфайл - для развертывание одного контейнера. Конечно можно в 1 контейнер запихнуть все. Но контейнеры должны быть легковесными, переносимыми. Идеально 1 процесс на контейнер. Чаще всего большое приложение содержит много процессов, которые должны между собой коммуницировать.

Docker-compose - это самое первое средство для оркестрации контейнеров.

Оркестрация - некое описания их взаимодействия, описание их разворачивания.

Docker - управляет одним контейнером, в идеале изолирует один процесс.

docker-compose - управляет набором контейнеров.

Dockerfile - описывает как построить образ. Dockerfile - среда приложения, docker-compose - сервисы приложения.

Отличие docker-compose от swarm и kubernetes. Говоря о docker-compose, мы достаточно часто имеем в виду dev среду и именно это про разработчиков. Чаще всего docker-compose не применяется в продакшене. На это есть некоторое кол-во причин. Docker Swarm и kubernetes более гибкие, более настраиваемые и дают некоторое количество преимуществ, например масштабирование с помощью docker-compose невозможно, а в kubernetes достаточно просто. Kubernetes = еше одно стороннее по, которое создает ещё один слой абстракции над контейнерами- оборачивает их в абстракцию - под. В зависимости от нагрузки может изменять количество подов.

При разработке это все не нужно. И docker-compose часто бывает достаточно. Docker-swarm - официальная утилита от докера. Припозднилась, приехала когда kubernetes уже был де факто стандартом.

Команды

https://docs.docker.com/compose/reference/

  • docker-compose up - builds, (re)create, starts and attaches to containers for a service Проходится по файлу docker-compose.yaml собирает пересоздает все контейнеры на основе определенных образов стартует их и связывает контейнер с сервисом. Появляется новая абстракция - сервис - составная часть приложения. Сервис это чуть более верхнеуровневая абстракция над контейнером.

  • docker compose down - stop containers and remove containers, networks, volumes and images Останавливает и удаляем все контейнеры, сети и volumes, которые были созданы во время docker-compose up

  • docker-compose start - start services

  • docker-compose stop - stop services - очищение памяти, временных файлов, логов, любых артефактов работы контейнера.

  • docker-compose pause - pause services - любые артефакты работы контейнера остаются на мсте после unpause

  • docker-compose unpause - unpause services

  • docker-compose logs -f [service name] - displays log output from service - логи конкретного сервиса

  • docker-compose ps - list containers - список контейнеров, из которых могут быть собраны сервисы в рамках изолированного compose.

  • docker-compose exec [service name] [command] - выполнить команду в запущенном контейнере - можем провалиться внутрь контейнера по его service_name. Сервис - абстракция над контейнером.

  • docker-compose images

Базовый пример docker-compose.yml

https://docs.docker.com/compose/compose-file/compose-file-v3/ Есть несколько версий - 2, 3...

В docker-compose файле мы описываем наше приложение. Приложение состоит из сервисов, может включать volumes и сети. Наше приложение состоит из следующих сервисов:

  • web
  • redis
# docker-compose.yml
version: "2"

services:
  web:
    build:
      # build from Dockerfile
      context: ./Path
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    volumes:
      - .:/code

  redis:
    image: redis

Список опций

https://docs.docker.com/compose/compose-file/05-services

service web

Сделан на базе контейнера. Мы получаем этот контейнера на шаге build на базе образа из Dockerfile. В контексте указываем путь до докерфайла и название докерфайла Dockerfile.

Указываем порты портхоста:портконтейнера. volumes - пробрасываем папку с хоста внутрь контейнера.

service redis

Более простой сервис. Строится на основе docker image redis.

build

Есть несколько вариантов билдится внутри сервиса

web:
    # build from dockerfile
    # из текущей папки
    build: .
    # пробрасывание аргументов в докерфайл
    args:   # add build args
        APP_HOME: app

    # build from custom Dockerfile
    # например если есть папка с фронтом, бэком и т.д.
    build:
        context: ./dir
        dockerfile: Dockerfile.dev

    # build from image
    image: ubuntu
    image: ubuntu:14.04
    image: tutum/influxdb
    image: example-registry:4000/postgresql
    image: a4bc65fd # билд по ид - не рекомендуется!!!

ports

ports:
  - "3000"
  - "8000:80" # host:container

# expose ports to linked services (not to host)
expose: ["3000"]
  • ports - проброс портов к хосту (хост:контейнер) если написана одна цифра, то это значит "3000:3000"
  • expose - если не хотим пробрасывать порты наружу в хост, но хотим, чтобы наши контейнеры общались по сети, то используется команда expose и далее передается список портов.

Env переменные окружения

Можно прокидывать по одной или передать сразу все в одном файле

environment:
    RACK_ENV: development
environment:
    - RACK_ENV=development

или передать сразу все через .env файл

env_file: .env
env_file: [.env, .development.env]

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

Чаще всего проект разворачивается во вне с помощью автоматизированного процесса, который называется pipeline, ci/cd. В пайплайнах также не должны быть прикопаны енв.

volumes

https://docs.docker.com/compose/compose-file/05-services/#volumes

Опция, которая перечисляет используемые докер-компоузом контейнеры. Если волюма не существует, до он буде создан.

volumes:
  elasticsearch:
  storage:
  postgres:

По-умолчанию docker-compose созадёт образ в своей системе, отличающийся от списка образов из docker. Можно использовать volume из docker, для этого образ объявляем, как внешний:

volumes:
  db-data:
    external:
      name: actual-name-of-volume

command

Контейнер после билда будет запускаться. Соответственно контейнер запускается с конкретной команды. Существует два способа передать команду. Второй способ с квадратными скобками является предпочтительнее.

Разница между CMD и ENTRYPOINT в докерфайле?

  • при определенных обстоятельствах никакой
  • при других обстоятельствах предпочтительнее ENTRYPOINT
  • при других обстоятельствах (совсем редко) предпочтительнее CMD.
command: bundle exec thin -p 3000
command: [bundle, exec, thin, -p, 3000]

# ovverrride the entrypoint
entrypoint: /app/start.sh
entrypoint: [php, -d, vendor/bin/phpunit]

Dependencies

# makes the `db` service available as the hostname database
# (implies depends_on)
links:
    - db:database
    - redis

# make sure `db` is alive before starting
depends_on:
    - db

# make sure `db` is healthy before starting
# and db-init completed without failure
depends_on:
    db:
        condition: service_healthy
    db_init:
        condition: service_completed_successfully

Линки - можно сделать доступным к обращению из других контейнеров с помощью линка. db - будет сервис, который теперь доступен к обращению из других сервисов как database. Сервис redis становится доступным для других сервисов на хосте как redis.

depends_on - одна из самых важных вещей в docker-compose файле. Секция внутри конкретного сервиса, которая рассказывает нам о том, от чего зависит запуск этого описываемого сервиса. Наш сервис зависит от сервиса db, который должен быть здоров (отвечать, доступен и т.д.). Также наш описываемый сервис зависит от другого сервиса db_init, который должен завершится успехом. Тогда при старте приложения, он создает внутри себя dependency_injection контейнер, в котором определенным образом прописывает коннекшн к базе, и если этого коннекшена нет, он упадет с ошибкой. Поэтому надо быть уверенными, что на момент запуска нашего сервиса уже будет развернута база данных. Это позволяет сделать секция depends_on.

Other options

  • extends - один сервис может базироваться ну другом, расширяя его Своеобразное наследование, используется не очень часто, но иногда, когда нужно на нескольких средах сделать немного разные вещи, то используется.
  • volumes - прокидывание хостовых папок и волюмов в докер.
  • restart - перезапуск контейнера при определенных условиях
    • unless_stopped
    • always - всегда - при завершении или падении, при перезапуске компоуза.
    • on_failure
    • no - значение по умолчанию
# make one service extend another
extends:
  file: common.yml # optionsl
  service: webapp

volumes:
  - /var/lib/mysql
  - ./_data:/var/lib/mysql

# automatically restart container
restart: unless_stopped
# always, on-failure, no (default)

healthcheck

Дергается когда прописан depends_on у сервиса со значением service_healthy. Мы выполняем команду тест, которая может быть успешной. Интервал - раз в 90 сек. timeout - сколько мы будем ждать выполнения этой команды. retries - сколько попыток сделать перед тем как сказать, что healthcheck провален.

# declare service healthy when test command succeed
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"]
  interval: 1m30s
  timeout: 10s
  retries: 3
  start_period: 40s

У postgresql своя система проверки при помощи crud запросов.

healthcheck:
  test: ["CMD-SHELL", "pg_isready -d $$POSTGRES_DB -U $$POSTGRES_USER"]
  interval: 10s
  timeout: 120s
  retries: 10

networks

Обычно есть одна сетка и все контейнеры, которые поднимаются в раках docker-compose взаимодействуют через эту сеть. Но мы можем задать свою сеть. Например по независящим от разработчика причинам, например эмулировать реальную инфраструктуру.

service1:
  network:
    - my_network
service2:
  network:
    - my_network

Использование сети типа host

build:
  context: .
  network: host

Отключение доступа к сети

build:
  context: .
  network: none

Миграции

Определенные изменения в базе данных. Иногда запускается сервис для миграций.Например может быть отдельный контейнер с некоторым количеством sql файлов, которые в определённом порядке запускается. При запуске сервиса миграции, этот набор скриптов определённым образом меняет базу. Это надо, например, для изменения базы данных. Механизм миграций нужен для возможности отката т.к. они позволяют восстановить состояние базы данных в любой конкретный момент времени.

Миграции могут быть вынесены в отдельный сервис.

пример docker-compose

https://github.com/reportportal/reportportal/blob/master/docker-compose.yml

ДЗ Проект

  • Облако
    • docker-compose
      • nginx
      • back
      • front

На выходе Докер компоуз файл в проекте в котором 3 папки: front, back, nginx, database. Внутри каждой папки должный быть свои докерфайлы. В докеркомпоузе должны быть описаны 4 сервиса. При изменениях в исходном коде должны пересобираться внутри приложения. Внутри приложения должен быть watch, чтобы видеть изменения, которые были внесены. Можно билдить приложение во фронте, собирать и закинуть в nginx. При этом нельзя будет разрабатывать, т.к. образ будет готовым. Но т.к. докер-компоуз нужен для разработки, то надо иметь возможность разрабатывать с ним. Внутри докер компоуза CMD должен быть не стандартным, а npm run dev .... Когда запускается эта команда, она запускается в watch моде, следит за изменениями файлов. Папка nginx помимо docker-файла должна иметь определённый конфиг, который прячет за собой фронт и бэк. У бэкэнда должна быть сетевая связность с базой данных.

У фронтэнда не должно быть сетевой связности с базой. Все .env через докер компоуз. Секретный данные не должны быть в докер-компоуз файле.

Cloud

Яндекс, ВК, АВС Digital Ocean - Azure - не оплатить из россии Amazon - оплачивается зарубежной картой

Облака. Yandex Cloud.

История. Особенности.

В основе любого облака заложены определенные принципы, вытекающие из определенных предпосылок.

Облако - метафора, олицетворяющая сложную инфраструктуру. Сетевую, спец. хранилища и т.п. В этом очень сложно разбираться. Раньше в начале 2000х было все намного проще. Сейчас настроить сервер бд и прикладного по и сервис elasticsearch - это 3 большие и три разных задачи в т.ч. и по требуемым навыкам. Компании столкнулись со сложностями. Одним из первых был амазон, - большой сайт на котором было много транзакций. Решение было найдено - было нанято много админов и они столкнулись с той же проблемой - поиск квалифицированных кадров. Поэтому упростили многое, чтобы можно было брать менее квалифицированных специалистов. Так и получили развитие AWS. AWS выглядят ужасно, т.к. это решение от инженеров для инженеров. Но это было настолько удачное решение, спрятавшее огромную сложность за кликами мыши за кнопками. Развернуть машину для базы данных стало очень просто.

Облачные платформы позволяют арендовать ИТ ресурсы:

  • серверы
  • базы данных
  • ип адреса
  • сетевую инфраструктуру
  • и т.п. (нейросети)

Плюсы:

  1. Разделение ответственности - пользуемся не беспокоясь за издержки владения
  2. Масштабируемость - гибкость в реагировании на изменение нагрузки
  3. Экономия - платим за то, что используем Минусы:
  4. Сложно уйти с облака - бизнес привыкает с этим услугам и отказаться от них сложно. Попытаться поднять у себя - долго, дорого и не всегда возможно вытащить виртаулки к себе с клауда. Иногда просто нет доступных ресурсов внутри сети.
  5. Хороший интернет - постоянный коннект. Обычно слабо выражено в современном мире.
  6. Иногда надежнее иметь у себя полноценную серверную. Иногда правильнее и быстрее решить проблему зайдя у себя в ЦОД. Да это дороже. Банки стараются по минимуму использовать клауд инфраструктуру. Включается также и юридический аспект. В россии банки и крупные компании пилят свои облака, т.к. высококвалифицированных инженеров немного и нужны простые решения.
  7. Доступность 99.95% - всегда можно попасть в 0.05%, или на убитые диски или на что-то еще. В итоге будет большой инцидент.

Yandex Cloud. IaaS

IaaS, PaaS, SaaS

IaaS - Infrastructure as a Service

  • Идентификация и безопасность
  • Виртуальные машины и контейнеры
  • Объектное и блочное хранилище
  • Сеть и доставка контента - LoadBalancer

PaaS - Platform as a Service Нам продают уже готовую преднастроенную виртуалку со специализированным ПО. Самый простой пример - S3 хранилище или СУБД.

  • Управление данными и аналитика Сервис управления базами данных, классические СУБД
  • Serverless / Cloud Native
  • ML & AI

SaaS - Software as a Service Это приложение, комплексное, которое разворачивается на нескольких серверах. Например это GitLab (который можно купить у GitLab - гит сервер с CI/CD раннерами). Тоже можно сказать про Jira. Раньше её можно было поставить на свои железки, но понемногу они мигрировала в облако.

  • Партнерские приложения и сервисы

YandexCloud

На данный момент ЯК предоставляет 9 разделов

  • Инфраструктура и сеть - инфраструктурные сервисы для обработки данных, безопасного доступа к ним и обработки данных. IaaS
  • Платформа данных - управление базами данных и кластерами, масштабируемое хранение данных, сбор и визуализация метрик и данных. PaaS. Модно поднять целый кластер без детальных настроек.
  • Контейнерная разработка - управление кластерами Kubernetes и Docker-образами. У многих рос облаков сейчас оч плохо с поддержкой докер контейнеров. Все больше концентрируются на кубере, а не на докер образах.
  • Инструменты разработчика - сервисы для оптимизации разработки и тестирования приложения. AWS и Azure имеют свою систему тикетов, аналогичную Jira. У яндекса есть доски для тикетов.
  • Безсерверные вычисления - serverless. Сервисы для хранения данных и разработки приложений без создания виртуальных машин. Мы можем написать кусок кода, который надо будет запускать по требованию, например при обращении их некого приложения. Можно вызвать одну функцию, которая вызовет определённые функции, обратиться к другим сервисам в облаке и после того завершит свою работу. Это будет не очень надёжно, зато супер дешево.
  • Безопасность - управление ключами шифрования и TLS сертификатами, защита от DDoS атака. Легко упустить в большом приложении. Клауды чаше всего очень хорошо справляются с DDoS.
  • Ресурсы и управление - идентификация и контроль доступа к облачным ресурсам, управление ресурсами в каталогах и облаках. Вокруг облачной инфраструктуры часто вырастает своя инфраструктура. в т.ч. связанная и с контролем ролей, доступов. Обычно это некая ролевая модель, лежащая в отдельном сервисе и позволяющая очень гибко настраивать доступ к личному кабинету кампании.
  • Машинное обучение - речевые технологии, анализ изображений и машинный перевод.
  • Бизнес-инструменты - визуализация и анализ данных, хранение базы знаний, трекеры задач для организации работы команды.

S3

В какой-то момент Amazon запустил свое облачное хранилище данных. Сейчас это используется повсеместно. Если мы в Москве, а пользователь в Хабаровске, то расстояние большое и задержки высокие. Плюс при передачи данных убудет загружен большой участок сети. Надо чтобы физическое расстояние минимально влияло на передачу данных. Было бы здорово, чтобы файл сам реплицировался на много географически распределенных серверов и пользователь будет его скачать с ближайшего сервера. Это первым и сделал Amazon. Это решение потом стало открытым, появились его реализации, в т.ч. OpenStorage в Yandex.

Application Load Balancer vs Network Load Balancer

Оба балансируют нагрузку по сети, но первый по транспортному уровню сети, второй по прикладному уровню сети.

  • прикладной - Application Load Balancer
  • представительский
  • сеансовый
  • транспортный - Network Load Balancer
  • сетевой
  • канальный
  • физический

Платформы данных

Postgresql Mysql Mongo Redis ElasticSearch MessageQueue - очереди для асинхронного взаимодействия.

Физическая инфрастуктура

У яндекса есть 3 цода (конец 2023 года)

  • ru-central1-a
  • ru-central1-b
  • ru-central1-c Каждая зона - отдельный датацентр. ДЦ полностью независимы друг от друга.

Иерархия ресурсов

Ресурсы в ЯК - это все сущности, которые вы можете создать (виртуальные машины, диски, виртуальные сети). Ресурсы объединены в группы - каталоги. Каталоги объединены в облако. Облако - самая крупная логическая структура в ЯО. Она изолирована - ресурсы из одного облака не могут взаимодействовать с ресурсами в другом облаке (только по сети интернет). Зачем и когда логически делить? Скорее всего у одной кампании есть одно облако. Если компания большая и у неё несколько направлений - туризм и машины - имеет смысл разделить на два облака

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

Роли

Сервис Yandex Resource Manager определяет ресурсную модель Yandex Cloud и позволяет структурировать ресурсы с помощью каталогов. Роли бывают двух типов:

  • Примитивные роли - содержат разрешения, действующие для всех типов ресурсов Yandex Cloud - роли admin, editor, viewer.
  • Сервисные роли - содержат разрешения только для определенного типа ресурсов в указанном сервисе. Например в контейнерах, чтобы получить доступ к образу, который хранится в хранилище образов, нужна определённая роль.

Платёжный аккаунт

Платёжный аккаунт используется для идентификации пользователя, оплачивающего услуги. Он хранит информацию о плательщике и может быть не связан с конкретным человеком. С точки зрения Resource Manager платежный аккаунт - это ресурс. К нему можно давать доступ обычным аккаунтам, используя роль billing.accounts.member.

Container Optimized Image

Это образ виртуальной машины, оптимизированной для запуска Docker контейнеров. Образ включает в себя Ubuntu LTS, Docker и демона для запуска докер-контейнеров.

Образ интегрирован с платформой ЯК, что позволяет:

  • запускать докер контейнеры сразу из консоли управления ЯК или YC-CLI
  • обновлять запущенный докер контейнер с минимальным временем простоя. Вручную приложение немного "моргнёт". А здесь определенным образом оптимизировано, чтобы не потерять пакеты во время перезапуска контейнера.
  • получить доступ к открытым сетевым портам докер контейнера без дополнительных настроек

Все контейнеры запускаются с использованием сетевого интерфейса хоста. Все порты открытые на докер контейнере будут открыты и на хосте.

Все порты хоста открыты в интернет, что позволяет автоматически получить доступ к портам запущенного докер-контейнера.

Это может создать некоторые дыры в безопасности. Не всегда нужно, чтобы все элементы инфраструктуры были доступны в сети. Т.к. образом это больше про разработку, чем под продакшен.

Инструкция

https://cloud.yandex.ru/docs/cos/tutorials/vm-create

Мониторинг приложений. Prometheus + Grafana

Мониторинг - сбор, обработка, агрегирование и отображение количественных показателей системы в реальном времени. Еще эти данные определённым образом обрабатываются, т.к. не всегда можно сделать выводы по "сырым" данным.

Минусы мониторинга:

  • стоит денег
  • требует поддержки
  • ложные срабатывания (тестовые)

Плюсы мониторинга:

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

Подходы к мониторингу:

  • WhiteИox - наблюдение показателей, доступных внутри системы. Это удобно для технического анализа. Наблюдение за использованием ресурсов и понимание того, как ведёт себя приложение и ретроспективный анализ.
  • BlackBox - наблюдение поведения системы со стороны пользователя. Удобно для предотвращения инцидента и оповещения команды разработки. Для этого надо смотреть на систему глазами пользователя. Например если увидим, что страница у пользователя начала грузиться не 300мс, а 3 секунды.

Всегда используются два подхода в одной системе мониторинга.

  • 4 golden signals Отправная точка

    • latency - как долго система реагирует на некоторые выбранные запросы. Редко когда имеет смысл мониторить все запросы.
    • traffic (объем трафика, rps, rpm) - чаще всего изменяются по rps. Важно за ним следить т.к. есть пики нагрузки, в которые иногда надо отмаштабироваться.
    • errors (любые) Можно все ошибки скидывать в graylog, оттуда графана будет отрисовывать ошибки на графике.
    • saturation (загруженность) Можно считать по разному. Например есть предел нагрузки на 1 сервер. Можно считать по загрузке потребляемых ресурсов. Нужно грамотно настроить и грамотно поставить alert. Часто бывает что даже после 65 - 70% загруженности могут появляться ошибки.

Производные от Golden Signals:

  • RED
    • Rate | Errors | Duration
  • USE
    • Utilization | Saturation | Errors

В мониторинге присутствует ещё огромное количество бизнесовых и дополнительных меток. Зачем нужны тогда стандартные метрики:

  • для отправной точки

Бизнесовые метрики, пример

  • количество платеже
  • успешные логины

Latency

  • не брать среднее Не дает реальную картину, т.к. проглатывает выбросы

  • берём квантиль

    • 99q = 972ms - 99% наших запросов уложились в 972ms
    • 95q = 860ms - 95% запросов в пределах 860ms

    Проблемы квантиля:

    • у удава толстый хвост ( почему вставшие 1% / 5% не попали в квантиль). Не знаем что не попало в квантиль.
    • мы не всегда знаем распределение внутри квантиля. Не знаем какие запросы попали, какая доля быстрых а какая доля медленных. Не знаем нормальность этого распределения. Решается путем выборки нескольких квантилей, из которых становится более или менее понятно.

Prometheus + Grafana

Prometheus изначально был написан для SoundCloud. Использует TimeSeriesDB Есть 2 файлика

  • prometheus.yml - настройки получения данных. Как получить метрики из конкретного приложения.

  • rules.yml - это настрйока предупреждений.

У прометеуса есть несколько дополнительных модулей, например это Alertmanager.

  • Prometheus работает по pull модели. Прометеус сам запрашивает метрики у приложения. Elastic - push стратегия.
  • В Pushgateway можно пушить метрики и Prometheus их соберёт. Данынй модель обходит ограничения pull модели прометеуса. Далее из этого модуля прометеус соберет метрики уже по pull модели. Данынй модуль может быть использован напрмиер для снятия метрик у определенных временных джобов, которые не постоянны, а запускаются по запросу.
  • Отображение в Grafana ( работает не толкьо с прометусом)

Grafana является веб интерфейсом для прометеуса, котоаря взаимодействует с прометеусом при помощи PromQL - свой язык Prometheus Query Language. Графана работает не только с Prometeusom, но и с другими источниками данных. Графана может сама выбирать данные.

Prometheus. Модель данных

  • Данные хранятся в виде временных рядов
  • Каждый ряд идентифицируется именем и набором лейблов http_request_total{method='GET', host='example.com'}
    • name: name
    • labels: - пара ключ-значение
      • method
      • host -не стоит злоупотреблять уникальными временными рядами

Иногда мы хотим сделать много временных рядов. Например хотим сделать еще один label - path, в который будем писать все, что после /. Это приведет к большому количеству временных рядов, что увеличит потребление ресурсов и тормознутость прометеуса. Количетсов запросов на разные эндпоинты лучше делать другим способом.

Prometheus. Типы метрик

  • Counter
    • Монотонно возрастает
    • сбрасывается при рестарте прометеуса Например это будет количество входов пользователей с момента работы сервиса. Или количество скачиваний файла.
  • Gaгge (шкала)
    • может как уменьшаться, так и возрастать Например это очередь задач которые в текущий момент на сервере.
  • Histogram
    • Распределяет значения по бакеном и считает их количество
    • по гистограмме можно посчитать квантиль
    • используется для замера задержки
  • Summary
    • похоже на гистограмму
    • сразу считает квантиль
    • используется редко

Grafana

Утилита для визуализации и анализа данных, получаемы в результате мониторинга различных систем и сервисов.

  • Может применяться не только в в ИТ, но и в других сферах:
    • вывод данных на ценные бумаги
    • построения состояние сети в телекоммуникациях
    • вывода статистики продаж в магазине

Графана в докере

docker run -d -p 3000:3000 --name grafana grafana/grafana

Grafana настройки

Конфиг файл лдя графаны лежит в рабочей директории ОС. Для убунты это /etc/grafana/grafana.ini.

Переопредеить расположение файла можно при помощи флага --config <path>

# defaul section
instance_name = ${HOSTANME}

[security]
admin_user = admin

[auth.google]
client_secret = Jrn24ogq24

[plugin.grafana_image_renderer]
rendering_ignore_http_errors = true

https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/

Karpov Course Docker

https://lab.karpov.courses/learning/102

Инструкция по установке докера на Linux

https://lab.karpov.courses/learning/102/module/1276/lesson/12125/35054/170854/

Ссылки:

В этом примере мы рассмотрим установку докера на самый распространенный дистрибутив линукса — Ubuntu. Инструкцию по установке на другие системы (Debian, CentOS, Fedora etc.) вы сможете найти в документации.

  1. Добавляем репозиторий докера (чтобы получить последнюю его версию)
sudo apt-get update
sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release -y
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  1. Устанавливаем docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io -y
  1. Устанавливаем docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.6.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
  1. Проверяем, что всё установилось

У вас должны работать следующие команды:

sudo docker -v
sudo docker ps
sudo docker images

и для docker-compose

docker-compose -v

Версии могут различаться, но должно получиться примерно следующее:

  1. Запуск докера не из-под суперпользователя

Это опциональный шаг, но в курсе докер будет запускаться имени так (т.е. без "sudo").

sudo groupadd docker
  • Может выдать groupadd: group 'docker' already exists. Это нормально.
sudo usermod -aG docker $USER

Затем выходим из терминала и заходим обратно.

После этого нужно проверить, что всё сработало:

id -nG
docker ps
docker images

Инструкция по установке докера на Windows

https://lab.karpov.courses/learning/102/module/1276/lesson/12125/35054/170856/

Как получить образ

  • скачать из репозитория docker pull <образ>
  • через Dockerfile
  • создать из контейнера docker commit <контейнер>.

Докер позволяет переиспользовать слои! Из слоев состоят образы. Если два образа отличаются только одним файлом, то второй образ будет собираться не с нуля а с точки различий.

Контейнер прекращает работать как только отработает кго основная программа с id = 1.

  • docker rmi <image> [image...] docker image rm <image> [image] - удаление образа
  • docker images docker image ls - список образов
echo $(pwd)

$(pwd) - выполнение команды в скобках и подстановка её результата

Если надо программа в контейнере ждёт ответа или интерактивного ввода с консоли, то можно запустить контейнер в интерактивном режиме -i

Dockerfile

https://lab.karpov.courses/learning/102/module/1276/lesson/12127/35057/171609/

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

Интерактивный режим - мы как бы оставляем поток ввода вывода между хостом и контейнером открытым.

echo hello-from-host.sh | docker run --rm -i my-ubuntu/entry

допишет команды в файле hello-from-host.sh к entrypoint

Иногда надо явно указать для bash что дальше команда, делается это с опцией -c:

bash -c 'bash'
docker run --rm -it my_ubuntu:entry -c 'bash'

Можно перезаписать entrypoint через ключ --entrypoint

docker run --rm -it --entrypoint=bash my-ubuntu/entry

разница между ADD и COPY

ADD позволяет копировать файлы с сетевых ресурсов и распаковывать архивы

FROM ubuntu:22.04

WORKDIR /zip
ADD archive.tar.xz .

WORKDIR /url
ADD https://airflow.apache.org/docs/apache-airflow/2.4.0/docker-compose.yaml .

Docker swarm

  • предоставляет готовую оверлейную сеть
  • шифрование внутри сети и взаимная TLS аутентификация
  • последовательные обновления сервисов

Все метаданные в кластере хранятся в распределённой базе данных etcd, расположенной на всех управляющих узлах.

Для оркестрации используются сервисы - отдельные задачи, выполняющиеся на узлах docker swarm.

Сервис - это определение желаемого состояния, которое надо достичь и задача. которую нужно выполнить.

Инициализация

Задание управляющего узла

docker swarm init --advertise-addr 192.168.0.10:2377 --listen-addr 192.168.0.10:2377
  • docker swarm init - инициализация docker swarm
  • --advertise-addr - адрес по которому другие узлы будут подключаться к управляющему узлу
  • --listen-addr - адрес и порт, используемый для прослушивания трафика swarm. Обычно совпадает с --advertise-addr, но могут быть и другие значения.

После этого будет выдан ключ доступа для подключения рабочего узла.

Узнать токен для подключения можно узнать командами:

  • docker swarm join-token manager - для получения токена управляющего узла
  • docker swarm join-token worker - для получения токена рабочего узла

Подключение рабочих узлов

docker swarm join --token <токен> <адрес для подключения>

docker node

Просмотр информации по узлам с управляющего узла

docker node ls
docker node inspect self --pretty
docker node inspect self
docker node inspect --pretty <воркер>
  • docker node ls - список узлов c управляющего узла
  • docker node inspect --pretty <self | нода> - просмотр информации узла

Консунсус

Команды в swarm могут поступать только от лидера (Leader). Если управляющих узлов несколько, то пассивный управляющий узел передаст запрос лидеру.

Обычно рекомендуется назначать нечётное количество управляющих узлов, но не больше пяти.

Алгоритм конcенсуса docker swarm Raft допускает потерю (N-1)/2 узла. Т.е. для пяти узлов, можно потерять 2, чтобы кластер продолжал существовать в согласованном состоянии.

В ситуации split-brain существущие задачи продолжат выполняться, но новые не будут назначаться.

split-brain - ситуация, которая возникает, когда управляющие узлы не могут достигнуть консенсуса. Может возникнуть при чётном количестве управляющих узлов.

Сервис

Приложение в docker swarm называется сервис. В ответ на создание сервиса оркестратор создаёт задачи или реплики.

docker service create --name myredis redis:latest
  • docker service ls - просмотр списка сервисов
  • docker service ps <имя сервиса> - просмотр информации о сервисе
  • docker sercive inspect --pretty myredis - доп информация о сервисе

Создание реплик

Запуск 5 реплик сервиса

docker service create --name myredis_replica --replicas=5 redis:latest

просмотр информации

docker service ps myredis_replica

Каждая реплика это задача, которая сопоставлена с контейнером.

Если остановить рабочий узел с запущенной репликой, то задачи с него перенесутся на рабочие узлы.

При возвращении в строй остановленного узла, перенесенные с него задачи не возвращаются обратно.

Масштабирование сервиса

docker service scale <имя сервиса>=3 - масштабирование количества реплик сервиса

docker service create --name mynginx --replicas=4 nginx:latest
docker service ls
docker service ps mynginx
docker service scale mynginx=7

Реплицированные и глобальные сервисы

В docker swarm есть два типа сервисов:

  • реплицированные
  • глобальные

Реплицированным сервисам можно задать количество реплик и управляющий узел сам распределит реплики по рабочим уззлам.

Для глобального сервиса управляющий узел размещает по одной реплике на каждом доступному узле. При добавлении нового узла, на нём также запускается реплика этого сервиса.

создание реплицируемого сервиса с 3 репликами

docker service create --name replicated --replicas=3 --mode replicated redis:latest

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

docker service create --name global --mode global nginx:latest

Очистка кластера swarm

По умолчанию узел при подключению к swarm подключается в режиме ACTIVE - узел получает и обрабатывает задачи от управляющего узла.

Узел можно перевести в режим DRAIN (очистка), чтобы он не получал новые задачи от управляющего узла swarm. При этом останавливаются запущенные задачи и переносятся на рабочий узел.

docker service --name myservice --mode replicated --replicas=2 nginx:latest
docker service ps myservice
docker node ls
docker node update --availability drain <node-02>
docker service ps myservice
docker node update --availability active <node-02>

Блокировка и разблокировка swarm

Когда в докер было сделано управление секретами журнал raft стал храниться в зашифрованном виде. Для всех управляющих узлов должен быть доступ к этому журналу, чтобы в случае потери лидера любой из управляющих узлов мог взять его роль.

С появлением секретов можно шифровать журнал Raft.

При перезапуске docker ключи для шифрования и дешифрования журналов Raft на диске и всё, что касается обеспечения безопасности коммуникация между узлами кешируется в памяти каждого управляющего узла.

Начиная с версии 1.13 эти ключи можно использовать чтобы блокировать swarm. При наличии автоблокировки управляющий узел после перезапуска должен предъявить ключ разблокировки кластера, чтобы вернуться в этот кластер.

При добавлении нового узла в кластер нет необходимости его разблокировать, т.к. ключ распространяется через взаимный TLS.

проверка на автоблокировку

docker info | grep Autolock

Блокировка кластера swarm. При этом создаётся ключ, который надо хранить в секрете и не потерять.

docker swarm update --autolock=true

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

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

Сети в docker swarm

  1. Создаётся мост docker_qwbridge для соединения контейнеров в кластере с внешним миром.

  2. По умолчанию создаётся оверлейная сеть ingress, которая используется для связи между контейнерами.

Можно создавать пользовательский оверлейные сети и сетевые мосты. И можно подключать сервисы и контейнеры к нескольким сетям одновременно.

Правила настройки файрволла для демонов докера

  • TCP 2377 (для управления коммуникациями кластера)
  • TCP и UDP 7946 (для коммуникации между узлами)
  • UDP 4789 (для трафика оверлейной сети)

Просмотреть сети

docker network ls

Создадим новую оверлейную сеть на управляющем узле

docker network create --driver overlay new_overlay

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

Создадим сервис и свяжем его с созданной оверлейной сетью:

docker service create --name test --replicas 4 --network new_overlay ubuntu:latest sleep infinity

После этого сеть станет доступной и на рабочих узлах.

Проверим свойства сети

docker network inspect new_overlay

Создание сервиса с опубликованным портом

Сервисы внутри оверлейной сти видят друг друга напрямую и предоставляют друг другу свои порты.

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

Для публикации порта его следует указать при помощи параметра -p или published.

Поддерживается как старый синтаксис с двоеточием, так и новый с запятой. Предпочтительнее более длительный вариант, как более читаемый.

docker service create --name myserv_ingress -p 8081:80 nginx
docker service create --name myservice1_ingress-p published=8080,target=80 nginx

Можно указать протоколы

docker service create --name myservice_ingress2 -p 8082:80/udp nginx
docker service create --name myservice_ingress3 -p 8083:80/udp -p 8083:80/tcp nginx
docker service create --name myservice_ingress4 -p published=8084,target=80,protocol=udp nginx
docker service create --name myservice_ingress5 -p published=8085,target=80,protocol=udp -p published=8085,target=80,protocol=tcp nginx

Обход маршрутизирущей mesh-сети в swarm

Маршрутизирующая mesh-сеть использует внутренний алгоритм для маршрутизации внутренних запросов в рабочим узлам. Когда клиент отправляет запрос, неизвестно, какой узел его обслуживает. Даже если мы создадим глобальный сервис, то всё равно будет использоваться маршрутизирующая mesh-сеть.

Если мы установим свой балансировщик нагрузки перед сервисом, необходимости в mesh-сети не будет. Для этого нужно запустить сервис DNS Round Robin (DNSRR) установив флаг --endpoint-mode в dnsrr.

Шифрование траффика в оверлейной сети и данных приложения

Весь управляющий траффик в оверлейной сети шифруется. Используется алгоритм AES. Управляющий удел Swarm меняет ключи каждые 12 часов.

Также можно зашифровать данные приложения.

Для шифрования данных приложения нужно при создании и обновления сети нужно указать флаг --opt encrypted чтобы включить шифрование IPSEC на уровне VXLAN. Докер создает туннели IPSec между всеми узлами, на которых запланированы задачи для сервисов, привязанных к оверлейной сети.

Устранение неполадок в Docker Swarm

По умолчанию Docker использует драйвер журналирования json-file. Журналы могут быть большими, поэтому рекомендуется использовать опции --follow или --tail.

Сети Docker

About

docker tutorial

Topics

Resources

Stars

Watchers

Forks

Contributors