Введение в docker

Что такое docker daemon, принцип работы docker, установка и удаление docker в linux, создание и запуск контейнера приложения в среде linux ubuntu.

    Общие сведения

    Docker - это среда для автоматизации развертывания, разработки, управления приложением в среде виртуализации операционной системы, доставки приложения
    С помощью docker можно упаковать приложение вместе с его окружением и зависимостями в виде контейнера.
    Контейнеры используют схожий с виртуальными машинами уровень изоляции, но не создают сильной нагрузки, что позволяет использовать ресурсы системы более эффективно.
    Docker предоставляет все необходимые инструменты и платформу для управления жизненным циклом контейнеров.
    Разработчики могут писать код локально и делиться своими работам со своими коллегами, используя docker
    Docker можно использовать для переноса своих приложений в тестовую среду для выполнения автоматических и ручных тестов
    Когда разработчики исправляют ошибки в среде разработки, они могут повторно загрузить свое приложение в тестовую среду используя контейнеры
    После завершения тестирования можно просто загрузить контейнер в production среду
    Docker контейнер можно развернуть на обычном ноутбуке, на виртуальном или физическом сервере, в облачной среде или дата центре
    Docker написан на языке GO и использует некоторые возможности ядра linux
    Docker использует технологию namespace для изолирования рабочего пространства, называемого контейнером

    Основные понятия

    Docker daemon ( dockerd ) - прослушивает запросы docker API и управляет объектами docker ( изображения, сети, контейнеры,сервисы, плагины ), кроме этого взаимодействует с другими демонами
    В качестве клиентов могут выступать docker run, docker build, docker pull
    Docker client ( docker ) - основной способ взаимодействия с docker. Например docker клиент отправляет команду демону dockerd, который в свою очередь эту команд выполняет
    Docker Desktop - это приложение которое содержит в себе как клиент, так и демон docker, Docker Compose, Docker Content Trust, Kubernetes, позволяет создавать и управлять контейнерами
    Docker registries - docker реестр хранит в себе образы docker.
    Docker Hub - общедостпный реестр, по умолчанию docker ищет образы именно там
    При запуске команд: docker run или docker pull, образы извлекаются из настроенного реестра или помещаются в реестр, есл используется команду docker push
    images - это шаблон доступный только для чтения, содержит инструкцию для создания контейнера
    images могут создаваться на основе других images с дополнительными настройками. Например можно создать образ на основе образа Ubuntu
    Можно создавать свои образы или использовать общедоступные образы из реестра
    Чтобы создать свой собственный образ, создается dockerfile который содержит инструкции необходимые для создания и запуска образа
    Containers - это доступный для запуска экземпляр образа, после запуска это изолированный процесс
    Запущенный контейнер имеет изолированную файловую систему
    Эта изолированная файловая система предоставляется образом контейнера, и образ контейнера должен содержать все необходимое для запуска приложения - все зависимости, конфигурации, скрипты, двоичные файлы и т.д.
    Образ также содержит другие конфигурации контейнера, такие как переменные окружения, команда для запуска по умолчанию и другие метаданные.
    Контейнер можно создать, запустить, остановить, или удалить используя docker API или CLI
    Контейнер можно подключить к одной или нескольким сетям, можно подключить к контейнеру хранилище или создать новый контейнер на основа образа существующего контейнера
    Можно контролировать уровень изоляции для контейнеров относительно других контейнеров, базовой системы, хранилища, сети
    Контейнер определяется его образом и параметрами конфигурации
    При запуске контейнера docker создает набор пространств имен для этого контейнера, эти пространства имен обеспечивают определенный уровень изоляции

    Принцип работы

    Если нет локального образа, он извлекается из реестра
    Создается docker контейне, как если бы он создавался вручную
    Далее docker выделяет файловую систему для чтения и записи
    Далее docker создает сетевой интерфейс и присваевает ip-адрес для контейнера, по умолчанию контейнер может подключаться к внешней сети используя сетевое подключения хоста на котором установлен docker
    Docker запускает созданный контейнер, возможно в интерактивном режиме

    Требования к установке

    Docker запускает VM поэтому должен быть включен модуль kvm-intel или kmv-amd в зависимости от модели процессора

    #Проверить kvm на Linux можно следующей командой lsmod | grep kvm #Проверить разрешения kmv для системного пользователя ls -la /dev/kvm #При необходимости можно добавить пользователя в группу kvm, после чего выйти и войти в систему sudo usermod -aG kvm $USER
    Установка и удаление

    #Полное удаление sudo apt remove docker-desktop rm -r $HOME/.docker/desktop sudo rm /usr/local/bin/com.docker.cli sudo apt purge docker-desktop rm ~/.config/systemd/user/docker-desktop.service rm ~/.local/share/systemd/user/docker-desktop.service #Для среды рабочего стола Gnome необходимы расширения https://extensions.gnome.org/extension/615/appindicator-support/ #Если среда отличается от GNOME тогда gnome-terminal sudo apt install gnome-terminal
    Установка

    Установить docker engine можно в комплекте с Docker Desktop, из apt, вручную или с помощью скрипта. Перед установкой необходимо удалить старые пакеты и зависимости, настроить и обновить репозитории, добавить официальный gpg-ключ
    Изображения, контейнеры, тома и сети, хранящиеся в /var/lib/docker/, не удаляются автоматически при удалении Docker.
    Docker Engine поставляется в комплекте с Docker Desktop для Linux.


    Сценарий после установки:
    Устанавливает в двоичном файле Docker Desktop возможность сопоставления привилегированных портов и установки ограничений ресурсов.
    Добавляет DNS-имя для Kubernetes в /etc/hosts.
    Создает символическую ссылку с /usr/local/bin/com.docker.cli на /usr/bin/docker. Это связано с тем, что классический интерфейс командной строки Docker установлен по адресу /usr/bin/docker. Установщик Docker Desktop также устанавливает двоичный файл Docker CLI, который включает возможности облачной интеграции и, по сути, является оболочкой для командной строки Compose по адресу/usr/local/bin/com.docker.cli. Символическая ссылка гарантирует, что оболочка сможет получить доступ к классической командной строке Docker.
    Пробный запуск можно сделать из приложения desktop или из командной строки

    systemctl --user start docker-desktop

    Создание контейнера

    Допустим есть приложение, прежде чем создать образ приложения, необходимо создать dockerfile. Dockerfile - это простой текстовый документ, который содержит скрипт ( инструкции ).
    Docker использует этот скрипт для создания образа.
    В корне каталога с файлами приложния необходимо создать файл и назвать его Dockerfile.

    cd /home/user/aplication touch Dockerfile vim Dockerfile #Содержимое файла dockerfile # syntax=docker/dockerfile:1 FROM node:18-alpine WORKDIR /app COPY . . RUN yarn install --production CMD ["node", "src/index.js"] EXPOSE 3000 #Создать образ docker build -t getting-started .

    Docker использует dockerfiel для создания образа
    Docker загрузил недостающие образы помимо того что создал сам образ
    yarn в dockerfile использовался для установки зависимостей
    CMD определяет команду, которая должна выполняться при запуске образа
    Флаг -t определяет короткое название образа
    . сообщает Docker в какой директории искать dockerfile
    Для запуска созданного контейнера используется команда docker run

    #Запуск контейнера docker run -dp 127.0.0.1:3000:3000 getting-started

    Флаг -d ( --detach ) запускает контейнер в фоновом режиме
    Флаг -p ( --publish ) сопоставляет порт контейнера и хоста
    Чтобы посмотреть используемые и запущенные контейнеры, можно использовать командную строку или интерфейс docker desktop #Посмотреть запущенные контейнеры docker ps

    Обновление, удаление контейнера

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

    #Посмотреть CONTAINER ID работающих контейнеров docker ps #Остановить работающий контейнер docker stop 48279e93089b #Удалить остановленный контейнер docker rm 48279e93089b #Можно остановить и удалить контейнер одной командой, используя флаг -f ( force ) docker rm -f 84b9d873f634
    Добавления приложения в Docker Hub

    Сначала необходимо создать репозиторий на Docker Hub
    Для доступа к личному репозиторию из консоли необходимо инициализировать pass с помощью ключа, подробнее об этом здесь

    # Авторизоваться через консоль docker login -u chich87 #Переименовать образ в соответствии с логином аккаунта в Docker Hub docker tag getting-started chich87/getting-started #Теперь можно отправить данные в репозиторий docker push chich87/getting-started
    Запуск контейнера из образа Ubuntu и выполнение команд

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

    #Запуск контейнера ubuntu и выполнение в нем команды через bash docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null" #Получить идентификатор созданного контейнера docker ps #Запустить команду в запущенном контейнере с помощью команды docker exec docker exec e36231027ac8 cat /data.txt #Теперь запустим контейнер из того же образа и убедимся, что созданный файл не доступен, так как был создан новый контейнер docker run -it ubuntu ls / #Удалить первый контейнер docker rm -f e36231027ac8
    Volumes

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

    #Создание volume docker volume create todo-db #Запуск контейнера с использованием опции mount docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started #Посмотреть где хранится volume docker volume inspect todo-db
    Использование bind mounts

    Bind mount тип монтирования, который позволяет совместно использовать каталог из файловой системы хоста в контейнере
    Контейнер сразу видит изменения после сохранения исходного кода в каталоге хоста
    Это означает, что процессы контейнера могут отслеживать изменения в файлах каталога хоста и реагировать на них

    #Перейти в директорию приложения cd /app/getting-started-app #Запустить docker run -it --mount type=bind,src="$(pwd)",target=/src ubuntu bash

    Параметр --mount указывает создать bind mount, где src= это рабочий каталог на хосте ( в данном случае каталог приложения getting-started-app )
    target=/src - это дирректория на хосте в контейнере ubuntu
    После запуска команды Docker запускает интерактивный сеанс bash в файловой системе контейнера

    #Далее можно перейти в каталог и убедиться в наличии привязанного каталога cd src; ls

    В следующем примере демонстрируется монтирование каталога хоста, установка зависимостей и запуск nodemon для отслеживания изменений в монтированном каталоге

    docker run -dp 127.0.0.1:3000:3000 \ -w /app --mount type=bind,src="$(pwd)",target=/app \ node:18-alpine \ sh -c "yarn install && yarn run dev"

    -dp 127.0.0.1:3000:3000 - запуск в фоновом режиме
    -w каталог из которого будет выполняться команда
    --mount type=bind,src="$(pwd)",target=/app - монтировать текущий каталог хоста в директорию контейнера
    node:18-alpine - образ который будет использоваться
    sh -c "yarn install && yarn run dev" - устанавливает и запускает сервер разработки
    Каждый раз, когда вносятся изменения в каталоге хоста, процесс nodemon автоматически перезапускает приложение внутри контейнера.

    #Просмотр логов контейнера docker logs -f 6892738e5194

    После завершения изменений в каталоге можно заново пересобрать образ используя следующую команду:

    docker build -t getting-started .

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

    Создание сети и подключение других контейнеров

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

    #Создать сеть docker network create todo-app # Старт контейнера MySql docker run -d \ --network todo-app --network-alias mysql \ -v todo-mysql-data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=secret \ -e MYSQL_DATABASE=todos \ mysql:8.0 #Выполнить команду в созданном контейнере mysq docker exec -it 9b00fa3f5f7f mysql -u root -p

    -e - создание нескольких переменных окружений для инициализации базы данных
    --network-alias - сетевой псевдоним
    -v todo-mysql-data:/var/lib/mysql \ - том todo-mesql-data который был подключен в директорию /var/lib/mysql, в нем mysql хранит свои данные, данный том создается автоматически
    В следующем примере используется nicolaka/netshoot - образ с инструментами для отладки сети.

    #Запуск контейнера с nicolaka/netshoot docker run -it --network todo-app nicolaka/netshoot #Поиск ip по ранее указанному псевдониму mysql dig mysql #Переход в директорию приложения cd app/getting-started-app #Теперь можно запустить приложение и указать переменные окружения для подключения к контейнеру mysql #При запуске указывается используемая сеть, подключается каталог app из текущей директории #Указывается образ node который будет использоваться, устанавливается и запускается сервер разработки docker run -dp 127.0.0.1:3000:3000 \ -w /app -v "$(pwd):/app" \ --network todo-app \ -e MYSQL_HOST=mysql \ -e MYSQL_USER=root \ -e MYSQL_PASSWORD=secret \ -e MYSQL_DB=todos \ node:18-alpine \ sh -c "yarn install && yarn run dev" #Подключиться к базе данных и убедиться, что элементы записались в базу docker exec -it 9b00fa3f5f7f mysql -p todos #Вывод данных в оболочке mysql select * from todo_items;
    Docker Compose

    Docker Compose - это инструмент, который помогает определять и делиться multi-conteiner приложениями
    С помощью compose создается yaml файл для определения необходимых сервисов и команд

    #Перейти в директорию приложения cd app/getting-started-app #Создать файл compose.yaml vim compose.yaml #В первых строках определяется имя образа который будет использоваться как часть приложения services: app: image: node:18-alpine #Данное имя также будет определять ip адрес для подключения к контейнеру #Добавить команду для установки и запуска сервера разработки command: sh -c "yarn install && yarn run dev" #Следующая команда определяет порты для службы ports: - 127.0.0.1:3000:3000 #Далее определяется рабочая директория working_dir: /app #И каталог для volumes в директории приложения volumes: - ./:/app #С помощью ключа environment определяются переменные окружения environment: MYSQL_HOST: mysql MYSQL_USER: root MYSQL_PASSWORD: secret MYSQL_DB: todos #Далее необходимо определить сервер mysql и установить для нее соответствующий псевдоним services: app: # The app service definition mysql: image: mysql:8.0 #Определить каталог для volume и указать переменные окружения volumes: - todo-mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: todos

    В целом код внутри файла compose.yaml должен выглядить так

    services: app: image: node:18-alpine command: sh -c "yarn install && yarn run dev" ports: - 127.0.0.1:3000:3000 working_dir: /app volumes: - ./:/app environment: MYSQL_HOST: mysql MYSQL_USER: root MYSQL_PASSWORD: secret MYSQL_DB: todos mysql: image: mysql:8.0 volumes: - todo-mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: todos volumes: todo-mysql-data:

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

    #Запуск docker compose с флагом -f для запуска в фоновом режиме docker compose up -d

    В процессе запуска docker composer автоматически создаст сеть по умолчанию для стека приложений

    #Просмотр логов docker compose docker compose logs -f #Чтобы увидить лог конкретной службы, необходимо в конце команды добавить название службы docker compose logs -f mysql #Остановить приложение запущенной с помощью compose docker compose down #Чтобы удалить volumes, используется дополнительный флаг --volumes docker compose down --volumes
    Image-building
    #Используя image history можно просмотреть команду, которая использовалась для создания каждого слоя в образе #В выхлопе каждая строка это слой образа или команда docker image history getting-started #Более подробный выхлоп можно получить с помощью дополнительной опции --no-trunc docker image history --no-trunc getting-started

    Если в определенном слое, все последующие слои также будут воссозданы заново.
    Чтобы сократить время сборки нужно реструктурировать ваш Dockerfile для кеширования зависимостей
    Например для приложений, основанных на nodejs эти зависимости определены в файле package.json
    Необходимо воссоздать зависимости yarn только в том случае, если в package.json были внесены изменения.
    Для этого необходимо обновить Dockerfile для копирования в package.json, установить зависимости, а затем скопировать все остальное.
    Создайте файл с именем .dockerignore в той же папке, что и Dockerfile, со следующим содержимым.
    node_modules
    файлы .dockerignore - это простой способ выборочно скопировать только файлы, которые относятся к образу
    В этом случае папка node_modules должна быть опущена на втором шаге копирования, поскольку в противном случае, возможно, были бы перезаписаны файлы, которые были созданы командой на шаге ЗАПУСКА.
    После внесения изменений необходимо пересобрать образ

    docker build -t getting-started .

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


    Источники
    Последнее изменение: 10.10.2024 04:21


    Здесь пока нет комментариев
    Добавлять комментарии могут только авторизованные пользователи

    Авторизоваться
    Я буду рекламой
    Я тоже буду рекламой
    И я
    ВВЕРХ