Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Legibl/docker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Лабораторная работа №1 "Введение в Docker"

Требования к окружению для выполнению л\р:

Перед выполнением л\р обязательно к прочтению: https://habr.com/en/post/346634/

Задание

Проверка работоспособности установленного docker daemon и изучение этого контейнера

выполните команду

docker run hello-world

вы увидите сначала такую ошибку:

Unable to find image 'hello-world:latest' locally

после чего начнется скачивание образа:

latest: Pulling from library/hello-world
1b930d010525: Pull complete 
Digest: sha256:92695bc579f31df7a63da6922075d0666e565ceccad16b59c3374d2cf4e8e50e
Status: Downloaded newer image for hello-world:latest

docker отрапортовал что начал скачивать и успешно скачал требуемый нами образ, также указал его hash. Затем мы увидим некоторое приветственное сообщение. Если у вас все получилось - значит все сделано правильно.

Давайте рассмотрим что же такое у нас сейчас произошло.

  1. Скачался запрашиваемый нами образ. По-умолчанию, если мы не указываем никакой адрес хранилища (docker registry), используется hub.docker.com
  2. Запросим у docker информацию о скачанном образе:
docker images hello-world

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

FROM scratch
COPY hello /
CMD ["/hello"]

Необходимым и достаточным условием для сборки контейнера является директива FROM (строка 1), которая используется для формировании основы нашего будущего контейнера. Классическим способом является использование уже готовых контейнеров, например, node, nginx, redis, debian, alpine, centos итп. Такие контейнеры уже содержат базовую файловую систему, опираясь на которую мы можем создавать свой сервис. В данном случае задача приветственного контейнера - просто вывести некоторое сообщение. Базовая файловая система - набор утилит, библиотек, конфигурационных и исполняемых файлов, расположенные в некоторых каталогах и подкаталогах. Весь этот набор нужен для функционирования необходимого нам дополнительного ПО, например, службы веб сервера, базы данных, итд итп, фактически здесь речь идет о любом софте в ОС linux. Однако, из коробки docker поддерживает работу скомпилированных файлов на языке С. Это достигается за счет изкоробочной поддержки библиотеки libc, и позволяет нам создавать практически невесомые контейнеры, которые будут состоять хоть из одного файла, который добавляется командой COPY (строка 2). Наконец, мы инструктируем docker запускать наш исполняемый файл hello при старте контейнера. Посмотрите его исходный код - в нем вы как раз найдете все строки, которые вывелись вам при старте контейнера. Следует понимать что старт контейнера это не какое-то абстрактное понятие - под стартом понимается именно запуск некоторой команды (команд), исполняемого файла или скрипта, указанного пользователем. В случае использования чьих-то контейнеров по-умолчанию строка запуска наследуется, но ее можно переопределить или как в данном случае - написать самим, поскольку контейнера-основы не существует.

Давайте посмотрим как docker хранит образы на вашей локальной машине:

docker inspect hello-world

В выводе вы увидите похожие строки:

"GraphDriver": {
    "Data": {
        "MergedDir": "/var/lib/docker/overlay2/e6b2f0a1bbafb09db96c5772113321e1bfc0e13b3292afe50b6c781e2f350060/merged",
        "UpperDir": "/var/lib/docker/overlay2/e6b2f0a1bbafb09db96c5772113321e1bfc0e13b3292afe50b6c781e2f350060/diff",
        "WorkDir": "/var/lib/docker/overlay2/e6b2f0a1bbafb09db96c5772113321e1bfc0e13b3292afe50b6c781e2f350060/work"
    },
    "Name": "overlay2"
},
"RootFS": {
    "Type": "layers",
    "Layers": [
        "sha256:af0b15c8625bb1938f1d7b17081031f649fd14e6b233688eea3c5483994a66a3"
    ]
}

docker использует свою файловую систему (а точнее одну из нескольких) overlayfs, в данном случае она записана как overlay2. Мы можем увидеть точку хранения файлов - /var/lib/docker/overlay2/e6b...; и если мы посмотрим содержимое поддиректории diff, мы увидим наш исполняемый файл hello.

Давайте более детально рассмотрим из чего состоит контейнер:

mkdir /tmp/hello && cd /tmp/hello && docker save hello-world -o hello.tar && \
tar xvf hello.tar 1>/dev/null && rm hello.tar && echo -e "\ncontents of container:\n" && ls

Изучите файлы метаданных которые "приезжают" вместе с контейнером. Укажите из какого файла берется информация о строке запуска CMD и прочая информация, которую вы видели в docker inspect. Найдите как хранятся слои с данными и расположение файла hello.

Напоследок в этом пункте давайте разберем что происходит в системе при запуске контейнера. Выполните команду:

docker run hello-world & while true; do ps aux | grep [h]ello | grep root ; done

Эта конструкция запускает наш контейнер, а затем в бесконечном цикле выводит список процессов, отфильтровывая их по ключевым словам root и hello. После заспуска вы увидите такой вывод (нажмите ctrl+c для выхода из цикла):

root     25796  0.0  0.0      0     0 ?        Ds   09:51   0:00 [hello]
root     25796  0.0  0.0      0     0 ?        Ds   09:51   0:00 [hello]
root     25796  0.0  0.0      0     0 ?        Ds   09:51   0:00 [hello]

А если посмотреть на дерево процессов, то мы увидим такую картину:

systemd(1)-+-containerd(787)-+-containerd-shim(25776)-+-runc(25784)-+-runc:[1:CHILD](25794)
                                                                    |-runc:[2:INIT](25796)-+-{runc:[2:INIT]}(25797)
                                                                    |                      `-{runc:[2:INIT]}(25800)
                                                                    |-{runc}(25786)
                                                                    `-{runc}(25792)

Происходит инициализация процесса

systemd(1)-+-containerd(787)-+-containerd-shim(25776)-+-runc(25784)-+-exe(25801)-+-{exe}(25803)
                                                                    |            `-{exe}(25807)
                                                                    |-runc:[1:CHILD](25794)
                                                                    |-runc:[2:INIT](25796)-+-{runc:[2:INIT]}(25797)
                                                                    |                      `-{runc:[2:INIT]}(25800)
                                                                    |-{runc}(25786)
                                                                    `-{runc}(25792)

И наконец его исполнение:

systemd(1)-+-containerd(787)-+-containerd-shim(25776)-+-hello(25796)

Т.е. наш исполняемый файл действительно запускался. Как вы уже знаете, docker использует методы изоляции процесса от хостовой системы, однако, поскольку изоляция != виртуализация, запускаемый процесс видно на хостовой ОС, он просто ограничен в своих возможностях. Поэтому все запускаемые процессы в контейнере всегда можно увидеть в списке процессов хостовой ОС, но помните, что они находятся в другом пространстве относительно их соседей. Такое отдельное пространство искуственно формируется средствами ядра ос linux - cgroups, linux namespaces.

Введение в запуск контенеров и подключение к ним

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

Как запускать?

  • docker run image:tag - передний план без взаимодействия из текущей консоли, работает до завершения процесса. Ярким примером является уже знакомый вам контейнер hello-world, который запускается без каких-либо аргументов. Внутри контейнера находится исполняемый файл, который будет запущен, а по окончанию всех инструкций этого файла будет завершен и используемый контейнер.
  • docker run -ti image:tag - передний план со взаимодействием из текущей консоли. Ключи ti означают проброс текущего input и tty, что как раз позволяет начать взаимодействовать с запущенным процессом в контейнере. Для контейнера по типу hello-world эти ключи безполезны, поведение контейнера от этого не изменится.
  • docker run -d image:tag (отсоединение контейнера от текущей консоли, перевод его в фоновый режим)

запустите контейнер nginx несколькими разными способами и с помощью команды docker ps посмотрите что у вас получилось.

Переопределение CMD

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

Как подключаться

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

  • docker attach - подключиться к самому запущенному процессу (используется довольно редко)
  • docker exec -ti <container_id> - запустить в работающем контейнере рядом какую-нибудь программу, например bash

Остановка, удаление

  • rmi - удалить образ
  • kill - остановить выполняющийся контейнер
  • system prune - системная команда запускающая автоматическую очистку мусора, остановленных контейнеров, сетей итп.

Просмотр состояния

  • ps [-a] - информация о запущенных контейнерах, -a показывает в том числе остановленные контейнеры

Скачивание, выгрузка

  • pull - скачать контейнер с репозитория
  • push - выгрузить контейнер в репозиторий
  • login - авторизоваться в репозитории

Сборка

Сборка происходит посредством инструкций, вписываемых в специальный файл: Dockerfile. Во время сборки docker daemon посылает все текущее содержимое каталога с Dockerfile демону docker, поэтому рекомендуется помещать Dockerfile в отдельную директорию и хранить только те файлы, которые необходимы на этапе сборки. Шпаргалка по командам Dockerfile

Для того чтобы собрать контейнер выполните команду, сформировав правильное имя в зависимости от ситуации. Для тестовых целей впринципе достаточно просто писать -t test:

docker build -t [repository][:port/]NAME:TAG .

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

Задание на самостоятельную работу с контейнером

В этом задании вы будете собирать собственный контейнер с веб-сервером и запустив его должны попасть на свой сайт. Для выполнения задачи следует запустить nginx где-то в сторонке, чтобы поизучать что у него внутри docker run -ti nginx bash а затем по необходимости устанавливать внутрь пакеты или тестировать конфигурации.

Таким образом задание предполагает работу с отдельным контейнером (К), докерфайлом (Д) и хостовым линуксом (Х). Последнее можно заменить на контейнер, а сам докер вообще установить под ОС Windows/Mac, ведь именно этим удобен docker - вы можете в кратчайшие сроки получить доступ к любому окружению, использовав в качестве хоста любую поддерживающий docker ОС.

Сдача отчетности

  1. Вам необходимо написать Dockerfile и создать в этой же директории согласно заданию необходимые файлы. Полученные файлы необходимо положить в свой git-репозиторий, например github.com/vpupkin/docker/lab1
  2. Собранный контейнер необходимо загрузить в докер-репозиторий, для этого следует зарегистрироваться на hub.docker.com а затем предоставить ссылку на него преподавателю

Задание

  1. Найти где находится директория sources.list.d (К)
  2. Зайти на сайт https://www.debian.org/mirror/list и выбрать любое понравившееся зеркало. (Х)
  3. Записать зеркало в файл с названием <REPO_NAME>.list, где repo_name заменить на имя репозитория. Зеркало должно поддерживать скачивание main и non free пакетов. (Х)
  4. Выполнить обновление apt-кеша (Д)
  5. Обновить все пакеты в контейнере (Д)
  6. Установить веб сервер nginx (Д)
  7. Очистить скачанный apt-cache (Д)
  8. Удалить содержимое директории /var/www/ (Д)
  9. Создать в директории /var/www/ директорию с именем вашего сайта и папку с картинками (company.com/img) (Д)
  10. Поместить из папки с докер файлом в директорию /var/www/company.com файл index.html. Файл нужно создать рядом с Dockerfile и поместить туда какую-нибудь строку приветствия (Х,Д)
  11. Поместить из папки с докер файлом в директорию /var/www/company.com/img файл img.jpg (поместить туда какую-нибудь картинку). (Х,Д)
  12. Задать рекурсивно на папку /var/www/company.com права "владельцу - читать, писать, исполнять; группе - читать, исполнять, остальным - только читать" (Д)
  13. С помощью команды useradd создать пользователя <ваше имя> (Д)
  14. С помощью команды groupadd создать группу <ваша фамилия> (Д)
  15. С помощью команды usermod поместить пользователя <ваше имя> в группу <ваша фамилия> (Д)
  16. Рекурсивно присвоить созданных пользователя и группу на папку /var/www/company.com (Д)
  17. Воспользоваться конструкцией (sed -i 's/ЧТО ЗАМЕНИТЬ/НА ЧТО ЗАМЕНИТЬ/g' имя_файла) и заменить в файле /etc/nginx/sites-enabled/default следующую подстроку (/var/www/html) так, чтобы она соответствовала (/var/www/company.com) (Д)
  18. С помощью команды grep найти в каком файле задается пользователь (user), от которого запускается nginx (К)
  19. С помощью команды sed проделать операцию замены пользователя в файле найденном в пункте 17 на вашего пользователя (Д)
  20. Соберите ваш контейнер: docker build -t test .
  21. Запустить собранный контейнер и проверить, что он запустился от вашего пользователя. Для этого необходимо выполнить Docker exec -ti <container_id> bash в соседеней консоли, предварительно узнав идентификатор запущенного контейнера. Назовите все идентификаторы процессов для родительского и порожденного процессов. (Выполнять после успешной сборки) (Х)
  22. Запустить ваш контейнер, но на этот раз передав аргументами нужные порты: docker run -ti -p 80:80 test
  23. Откройте в браузере(или curl) 127.0.0.1:80. Вы должны получить вашу приветственную страницу. Сделайте скриншот страницы в браузере на фоне команды запуска контейнера. Скриншот положить в репозиторий (Х)
  24. Выполните правильную постановку тега и загрузите ваш контейнер в docker hub. (Х)

docker

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published