Введение
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
Вывод
Как видно из данной публикации создание собственного образа не сложный процесс, на мой взгляд лучше использовать собственный образ, чем использовать уже созданные не официальные, в которых может находиться вредоносный софт.