Введение
Docker единственная система контейнерной виртуализации с которой мне еще не доводилось сталкиваться, по этому после изучения данной темы решил написать данную публикацию. В данной публикации пойдет речь о сборке собственного образа (с помощью dockerfile) на основе официальных образов системы от debian, монтировании различных файловых систем (nfs, btrfs, ext4), а также о различным параметрах dockerfile и командах управления контейнерами docker.
Создание образа
Перед создание образа необходимо установить некоторые зависимости для корректного добавления официальных GPG-ключ Docker:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release
Добавим ключи, а также репозитории
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Установим Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
После данных манипуляций можно приступать к сборке собственного образа, путем создания файла Dockerfile (данный файл можно создать, например, в каталоге пользователя), команду на создание образа необходимо выполнить из под sudo. На рисунке 1 представлен пример файла Dockerfile
FROM debian - указывает из какого образа из репозитория необходимо создать образ контейнера, произвести поиск доступных образов для загрузки можно командой sudo docker search debian
Официальные образы помечены ОК
MAINTAINER nemets - указать автора образа
RUN apt-get update - обновить список доступных пакетов
RUN apt-get install -y apache2 mc htop net-tools nfs-common && apt-get clean - установить apache2, а также дополнительные пакеты, при необходимости
VOLUME /etc/apach2 - создать точку монтирования
#WORKDIR /home - указывает текущий каталог для работы (например, если использовать директиву COPY test.txt user/test.txt, то файл будет скопирован в каталог /home/user)
COPY --chown=www-data:www-data test.txt /home/ - скопировать файл test.txt из каталога из которого была выполнена сборка образа в каталог /home, с правами www-data, если указанного пользователя не существует, то в этом случаи появится ошибка (можно указть uid и gid пользователя)
ADD --chown=www-data:www-data test.txt /home - команда аналагична команде copy
ENV MY_NAME="nemets" - создать постоянную переменную окружения для образа
ARG NAME="nemets" - создать временную переменную, данная переменная будет доступна только во время создания образа
EXPOSE 80/tcp - указать, что в образе используется 80 порт tcp (исключительно онформационная опция, при запуске контейнера в любом случаи необходимо явно указать порты)
EXPOSE 443/tcp - указать, что в образе используется 443 порт tcp
#EXPOSE 80/udp - указать, что в образе используется 80 порт udp
#EXPOSE 443/udp - указать, что в образе используется 443 порт udp
#USER root - указть от какого пользователя необходимо выполнять команды, в данном примере apache по умолчанию запускается от пользователя root, по этой причине данная деректива не обязательна, если например контейнер используется для запуска postgresql, то в директиве user необходимо использовать postgres, так как postgresql запускается от пользователя postgres
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"] - данная строка укажет образу, что необходимо выполнять apache с данными параметрами при запуске контейнера. В официальной документации данный способ запуска (exec) является предпочтительным, так как docker предпологается, что процес будет один и с pid 1, а также в этом случаи процес будет корректно принимать unix сигналы, но нужно учитывать, что при данном способе запуска не будут доступны переменные окружения, и по этой причине необходимо указать полный поть до apachectl
#ENTRYPOINT apachectl -D FOREGROUND - данный способ запуска apache происходит через shell, по этой причине в контейнере будет запущенно как минимум два процеса (/bin/bash и httpd), а также будут доступны переменные окружения
#CMD echo "Hello world" - данная команда дополнит команду ENTRYPOINT, но только если ENTRYPOINT выполняется в режиме exec, если ENTRYPOINT выполняется в режиме shell, то деректива CMD будет проигнорирована (также можно в дерективе указать запуск apache, как и в дерективе ENTRYPOINT)
После того как Dockerfile был создан, можно приступать к сборке образа, для этого необходимо выполнить команду
sudo docker build -t local/debian .
ключ -t добавит имя и "тэг" (формата name/tag) для созданного контейнера
при необходимости можно выгрузить созданный образ в репозитории (необходима регистрация)
docker push yourname/newimage
Команды для работы с образами и контейнерами
Для просмотра созданного образа используется команада
sudo docker images
Для удаления созданного образа используется команада
sudo docker rmi local/debian
Можно приступать к запуску контейнера, после его запуска, контейнеру будет присвоено имя а также CONTAINER ID, по которым можно обращаться к контейнеру
sudo docker run -d --restart=always --cpuset-cpus="0" --cpus=".5" --memory="1g" --memory-swap="1g" -p 80:80 -p 443:443 -v /home/user:/user --add-host=docker:10.180.0.1 local/debian
-d - запустит контейнер в фоновом режиме
--restart-always - поместить контейнер в автозапуск
--cpuset-cpus="0" - разрешить использовать только первое ядро процессора (можно указать ядра через запятую 0,3,5, или через тире 0-2)
--cpus=".5" - использовать процессор максимум на 50%
--memory="1g" - ограничить использование оперативной памяти в 1 ГБ
--memory-swap="1g" - ограничить использование swap в 1 ГБ
-p 80:80 -p 443:443 - пробросить 80 и 443 порты в контейнер
-v /home/user:/user - смонтировать каталог /home/user в папку /user контейнера
--add-host=docker:10.180.0.1 - добавить запись в файл /etc/hosts
local/debian - имя образа на основе которого будет создан и запущен контейнер
Список запущенных контейнером можно посмотреть командой
sudo docker ps
Список всех контейнеров, в том числе не запущенных, можно посмотреть командой
sudo docker ps -a
В данном примере имя созданного контейнера vibrant_pascal, а CONTAINER ID - 174fdcafd234, именно по этим параметрам можно обращаться к контейнеру
sudo docker stop vibrant_pascal #остановить выполнение контейнера
sudo docker start 174fdcafd234 #запустить контейнер
sudo docker pause 174fdcafd234 #поставить контейнер на паузу
sudo docker unpause 174fdcafd234 #запустить контейнер поставленный на паузу
sudo docker stats 174fdcafd234 #посмотреть использование ресурсов контейнером
sudo docker rm 174fdcafd234 #удалить контейнер
Для того что бы войти в контейнер необходимо выполнить команду
sudo docker exec -it vibrant_pascal bash
Иногда после каких либо изменений в контейнере, необходимо сохранить данные изменения в изначальный образ, для этого следует использовать команду
docker commit -m "added updates" -a "nemets" 174fdcafd234 local/debian
-m - коментарий с информацией о изменениях в образе
-a - имя автора изменений
Также можно указать другое имя образа (например local/debian1), если, например, необходимо сохранить изначальный образ
Для того что бы создать еще один контейнер из образа, достаточно еще раз выполнить команду
sudo docker run -d --restart=always --cpuset-cpus="0" --cpus=".5" --memory="1g" --memory-swap="1g" -p 8080:80 -p 4443:443 -v /home/user:/user --add-host=docker:10.180.0.1 local/debian
но при этом необходимо указать другой порт
Монтирование nfs "шары"
Первым делом необходимо поднять nfs сервер, для этого необходимо установить следующие пакеты
sudo apt install nfs-kernel-server nfs-common portmap
Внесем изменения в файл /etc/exports, а именно добавим строку
/mnt 192.168.1.0/24(rw,no_root_squash)
данная строка разрешит доступ к каталогу /mnt всем хостам из сети 192.168.1.0/24
Активируем и запустим nfs сервер
sudo systemctl enable nfs-server
sudo systemctl start nfs-server
После того как nfs сервер запущен, можно приступать к созданию сервиса volume для docker (в данном примере nfs сервер запущен на 192.168.1.103)
sudo docker volume create --driver local --opt type=nfs --opt o=addr=192.168.1.103,rw --opt device=:/mnt shara
После выполнения данной команды, в docker будет создан volume с именем shara, который можно монтировать во вновь созданные контейнеры. Для того что бы смонтировать созданную "шару" в контейнер в команду run необходимо добавить --mount source=shara,target=/mnt
sudo docker run -d --restart=always --cpuset-cpus="0" --cpus=".5" --memory="1g" --memory-swap="1g" -p 8080:80 -p 8443:443 --mount source=shara,target=/mnt -v /home/user:/user --add-host=docker:10.180.0.1 local/debian
При создании volume для параметра --opt type возможно использовать следующие параметры:
--opt type=cifs - монтировать smb "шару"
--opt type=btrfs - монтировать раздел btrfs
--opt type=ext4 - монтировать раздел ext4
также необходимо указать устройство с указанной файловой системой
--opt device=/dev/sda2
Команад для создания ext4 volume будет выглядеть так
sudo docker volume create --driver local --opt type=ext4 --opt device=/dev/sda2 shara
Вывод
Как видно из данной публикации создание собственного образа не сложный процесс, на мой взгляд лучше использовать собственный образ, чем использовать уже созданные не официальные, в которых может находится вредоносный софт.
Список источников, которые мне помогли в написании данной публикации
Install Docker Engine on Debian | Docker Documentation
docker build | Docker Documentation
Dockerfile reference | Docker Documentation
Use volumes | Docker Documentation
NFS Docker Volumes: How to Create and Use | phoenixNAP KB