Docker for newbies

 · Mikhail K
Table of contents

Читать на Английском 🇬🇧


karpov_logo Несколько лет назад, когда я впервые познакомился с NAS, я открыл для себя классную технологию, которую раньше не использовал. Меня интересовали новые сервисы, умный дом, расширение функциональности NAS до 200%, и это было возможно только с помощью docker, потому что в встроенном центре приложений не так много нативных. Также docker позволил установить все, что я хочу, без ущерба для хост-системы. Этот факт позволяет проводить любые эксперименты, не боясь что-то сломать. Но в чем была проблема? ... Я совершенно не знал docker :)

Знания даром

Ребята с karpov.courses сделали отличный курс для всех. Вам не нужны навыки программирования, знание bash или чего-то еще, он подходит абсолютно всем. Тем не менее, он подробно описывает docker с разных сторон. Несмотря на то, что я уже знал docker, я открыл для себя некоторые моменты, например, как установить контейнер с отдельным IP-адресом. Я был бы рад найти этот ценный курс в начале моего пути обучения, потому что он рассказывает тему за темой в простой форме. Отдельное спасибо автору Антону Сидорину.

Основные моменты курса

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

Основное

1. Советы по Bash

Это не относится напрямую к функционалу docker, но показывает, как быстро можно остановить все запущенные контейнеры за 1 шаг.

docker stop $(docker ps -q)

Аналогично вы можете удалить все контейнеры

docker rm $(docker ps -qa)

Перенаправление логов в файл также актуально для bash через оператор > / >>, но я не думал об этом в таком контексте.

2. Команда ENTRYPOINT против CMD

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

Обе команды CMD и ENTRYPOINT определяют, какая команда будет выполнена при запуске контейнера. Есть несколько правил, которые описывают их взаимодействие.

  • В Dockerfile должна быть указана хотя бы одна из команд CMD или ENTRYPOINT.
  • ENTRYPOINT должна быть определена при использовании контейнера в качестве исполняемого файла.
  • CMD следует использовать как способ определения аргументов по умолчанию для команды ENTRYPOINT или для выполнения специальной команды в контейнере.
  • CMD будет переопределен при запуске контейнера с альтернативными аргументами.

3. Мультисборка

Хорошая возможность разделить сборку на несколько шагов для уменьшения размера конечного образа или для повторного использования этого шага на следующих этапах.

FROM <image> AS builder
. . .


FROM <image> 
. . .
COPY --from=builder <path_from_builder> <path_to_current_build>

5. Volumes difference

Существует 2 типа томов:

  • Bind mount
  • Volumes

До этого курса мне было непонятно, для чего могут использоваться Volumes. Но давайте снова обратимся к документации. У Volumes есть несколько преимуществ перед bind mounts:

  • Для Volumes легче создавать резервные копии или мигрировать данные, чем bind mounts.
  • Вы можете управлять Volumes с помощью команд Docker CLI или Docker API.
  • Volumes работают в контейнерах Linux и Windows.
  • Volumes можно безопаснее распределять между несколькими контейнерами.
  • Драйверы Volumes позволяют хранить их на удаленных узлах или у облачных провайдеров, шифровать содержимое Volumes или добавлять другие функции.
  • Содержимое новых Volumes может быть предварительно заполнено контейнером.
  • Volumes на Docker Desktop имеют гораздо более высокую производительность, чем bind mounts с хостов Mac и Windows.

Теперь мне легко сделать выбор, что использовать. Если это какие-то постоянные данные, генерируемые контейнером, которыми вы не планируете управлять самостоятельно - выбирайте тома, в противном случае bind mount лучше всего подходит для внешних файлов, которые должны быть в контейнере.

Флаг "только чтение" - еще одна классная особенность Volumes.

docker run -d \
  --name=nginxtest \
  -v nginx-vol:/usr/share/nginx/html:ro \
  nginx:latest

4. Создание образов из запущенного состояния другого контейнера

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

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

Сети

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

1. Обращение к контейнеру по имени при использовании пользовательской сети

Хочешь искать IP-адрес каждого контейнера каждый раз, чтобы установить его на другой? Я нет, и docker предоставляет встроенный DNS-резолвер. Просто задайте имя контейнера через атрибут --name <container_name> и обращайтесь к нему по имени. Очень круто, не правда ли?

2. Использование нескольких сетей одним контейнером

Неочевидная вещь, но она есть. Больше рассказывать не о чем.

3. Предоставление контейнеру внешнего IP-адреса

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

  • Использование инструментов блокировки рекламы (AdGuard, PiHole и т.д.) и внешний DNS-сервер не могут сосуществовать на одном хосте из-за конфликта портов. Но что же тогда использовать? Виртуальная машина помогла решить проблему раньше, но теперь я могу назначить внешний IP для контейнера.
  • Что если вы хотите использовать VPN или интернет-провайдер для отдельного контейнера, но не для всего хоста? Да, внешний IP для контейнера снова поможет.

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

docker network create -d macvlan \
  -подсеть=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=ovs_eth0 \
  my-macvlan-net

Обратите внимание, что вы будете использовать IP диапазоны вашей текущей сети, поэтому там могут быть конфликты. Вам также нужно указать родителя, то есть интерфейс, через который трафик будет физически проходить на хосте Docker (к сожалению, есть ошибка с MacOS). Найти подходящий можно с помощью команды ifconfig (смотрите те, где назначается реальный IP).

YAML нотация

Ранее я не думал о YAML как о формате. То есть, я не понимал его как формат с правилами. Это похоже на привычный текстовый файл, в котором можно писать все, что хочешь, почти. Например, другие форматы будут повреждены, если вы где-то ошибетесь, но YAML не похож на другие, как я думал, но я ошибался. В курсе были показаны основы, правила, структура и т.д. Было любопытно увидеть, как структуры данных, такие как список, были реализованы в нативном виде.

Еще одна особенность с якорями YAML была объяснена на файле Airflow docker compose, это идеальное попадание в яблочко. Реальный и практический пример для меня, потому что когда я открыл его в первый раз, я был в замешательстве, что это такое, и я попытался найти информацию в ... документации docker. Конечно там ничего нет.

Принцип DRY в действии: Якорь - &. Псевдоним - <<: *

определения: 
  шаги:
    - шаг: &build-and-test
        имя: Build and test
        сценарий:
          - mvn package
        артефакты:
          - target/**

конвейеры:
  ветви:
    develop:
      - step: *build-and-test
    master:
      - step: *build-and-test

Итог

В конце концов, возможно, я не так хорошо знаю docker, как думал, потому что в нем оказалось слишком много полезной информации для меня. И есть масса других возможностей, о которых я еще не знаю. Но я полагаю, что это все потому, что курс был действительно замечательным. Проверьте его сами!