DockerAlt: различия между версиями

Материал из wiki.nntc.nnov.ru
Перейти к навигации Перейти к поиску
(Вручную)
(Загрузка образов Docker из архивного файла)
 
(не показано 36 промежуточных версий этого же участника)
Строка 1: Строка 1:
=Лабораторные работы по Docker=
+
=DOCKER_IN_ESPD=
  
==Подготовка рабочего места==
+
==Прокси сервер==
  
Для выполнения всех работ достаточно установить в виртуальную машину ОС Альт Рабочая Станция 10.
+
В ЕСПД каждой организации существует адрес прокси-сервера для доступа в централизованно-ограниченный провайдером интернет.
  
Ссылка на загрузку установочного образа: https://download.basealt.ru/pub/distributions/ALTLinux/p10/images/workstation/x86_64/alt-workstation-10.0-x86_64.iso
+
Например, это может быть адрес и порт:
  
После установки нужно обновить систему
+
10.0.52.52:3128
  
su -
+
==Настройка сервиса для работы с прокси-сервером в ОС Альт==
  
apt-get update
+
Для настройки сервиса docker в ОС Альт на доступ к образам с
  
  apt-get dist-upgrade
+
  hub.docker.com
  
update-kernel -f
+
необходимо:
  
открыть терминал и установить Docker командой
+
Импортировать сертификат (подробнее об этом здесь [https://www.altlinux.org/%D0%95%D0%A1%D0%9F%D0%94 здесь]):
  
apt-get install docker-engine
+
Переходим в каталог
  
Затем добавить текущего пользователя в группу docker командой
+
cd /etc/pki/ca-trust/source/anchors/
  
usermod -a -Gdocker student
+
Скачиваем сертификат
  
затем включить сервис и поставить его в автозагрузку
+
wget --no-check-certificate https://espd.rt.ru/docs/ca-root.crt
  
systemctl start docker
+
Приминяем
  
  systemctl enable docker
+
  update-ca-trust
  
перезагрузиться
+
Далее предполагается что Docker в ОС Альт уже установлен и необходимо добавить в окружение сервиса инициализацию переменных окружения
  
  reboot
+
  HTTP_PROXY
  
==[Практическая работа №1] Создание простого контейнера==
+
и
  
===Вручную===
+
HTTPS_PROXY
  
Откройте терминал хостовой машины
+
Для этого необходимо отредактировать файл
  
На базе официального стандартного Docker-образа
+
/etc/sysconfig/docker
  
alt:p10
+
Было:
 +
<pre>
 +
cat /etc/sysconfig/docker
 +
OPTIONS=""
 +
</pre>
  
Только получить образ на компьютер можно командой:
+
Стало:
 +
<pre>
 +
cat /etc/sysconfig/docker
 +
HTTP_PROXY=http://10.0.52.52:3128
 +
HTTPS_PROXY=http://10.0.52.52:3128
 +
OPTIONS=""
 +
</pre>
  
docker pull altlinux/base:p10
+
Важно! Адрес и порт прокси сервера могут быть другими!
  
создайте и запустите Docker-контейнер:
+
Затем необходимо перезапустить сервис
  
  docker run -it --name=my_first_container --hostname=my-first-container altlinux/base:p10 /bin/bash
+
  systemctl restart docker
  
 +
Теперь можно пробовать получить образ
  
В случае успешного создания Docker-контейнера в эмуляторе терминала приглашение должно смениться на такое:
+
docker pull alt:p10
  
root@my-first-container:/#
+
В случае успешной настройки в ответ должно быть что-то вроде этого
  
Внимание! Сейчас вы внутри Docker-контейнера и можете командовать им! Если скомандовать
+
<pre>
 +
p10: Pulling from library/alt
 +
8d0b964d5817: Pulling fs layer
 +
529c2ffbf4d6: Download complete
 +
8d0b964d5817: Pull complete
 +
529c2ffbf4d6: Pull complete
 +
Digest: sha256:1a4f3803dee404126c6947ea9f791eb781e25b541477dc242ef188e4e7734bef
 +
Status: Downloaded newer image for alt:p10
 +
docker.io/library/alt:p10
 +
</pre>
  
exit
+
=Лабораторные работы по Docker=
  
, то контейнер завершит свою работу и найти и запустить его можно таким образом:
+
==Подготовка рабочего места==
  
Найти:
+
Для выполнения всех работ достаточно установить в виртуальную машину ОС Альт Рабочая Станция 10.
  
docker ps -a
+
Ссылка на загрузку установочного образа: https://download.basealt.ru/pub/distributions/ALTLinux/p10/images/workstation/x86_64/alt-workstation-10.0-x86_64.iso
  
в ответе среди возможных прочих контейнеров должен быть такой:
+
После установки нужно обновить систему
  
  f0a3cc6a8b63        altlinux/base:p10                "/bin/bash"              15 seconds ago      Exited (0) 5 seconds ago                                my_first_container
+
  su -
  
Имя его в данном случае:
+
apt-get update
  
  my_first_container
+
  apt-get dist-upgrade
  
Идентификатор его в данном случае:
+
update-kernel -f
  
f0a3cc6a8b63
+
открыть терминал и установить Docker командой
  
Запустить:
+
apt-get install docker-engine docker-compose-v2
  
docker start my_first_container
+
Затем добавить текущего пользователя в группу docker командой
  
или:
+
usermod -a -Gdocker student
  
docker start f0a3cc6a8b63
+
затем включить сервис и поставить его в автозагрузку
  
Естественно, в конкретном случае идентификатор будет другой.
+
systemctl start docker
  
 +
systemctl enable docker
  
Подключиться к терминалу Docker-контейнера:
+
перезагрузиться
  
  docker attach my_first_container
+
  reboot
  
или
+
==[Практическая работа №1] Создание простого контейнера==
  
docker attach f0a3cc6a8b63
+
===Вручную===
  
 +
Откройте терминал хостовой машины
  
Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать
+
На базе официального стандартного Docker-образа
  
  exit
+
  alt:p10
  
, то контейнер завершит свою работу придётся опять читать выше по тексту как его запускать...
+
Только получить образ на компьютер можно командой:
  
 +
docker pull alt:p10
  
Однако есть способ отключиться от терминала и не завершить Docker-контейнер:
+
создайте и запустите Docker-контейнер:
  
Для этого нужно последовательно нажать сочетания клавиш:
+
docker run -it --name=my_first_container --hostname=my-first-container alt:p10 /bin/bash
  
Ctrl + P
 
  
затем
+
В случае успешного создания Docker-контейнера в эмуляторе терминала приглашение должно смениться на такое:
  
  Ctrl + Q
+
  root@my-first-container:/#
  
 +
Внимание! Сейчас вы внутри Docker-контейнера и можете командовать им! Если скомандовать
  
После этого приглашение командной строки контейнера должно заменить приглашение хостовой системы.
+
exit
  
 +
, то контейнер завершит свою работу и найти и запустить его можно таким образом:
  
На этом этапе мы научились запускать контейнер на базе образа. Однако наша цель -- создать собственный образ, поведение контейнеров, запущенных на базе которого который будет отличаться от поведения только что созданного нами контейнера.
+
Найти:
  
Для создания собственного образа вручную необходимо внести изменения внутри нашего контейнера, а затем выполнить операцию по "превращению" нашего контейнера в образ.
+
docker ps -a
  
====Задача====
+
в ответе среди возможных прочих контейнеров должен быть такой:
  
  Создать образ, содержащий стартовый сценарий, который будет считывать переменную окружения с именем пользователя и приветствовать пользователя по имени.
+
  f0a3cc6a8b63        altlinux/base:p10                "/bin/bash"              15 seconds ago      Exited (0) 5 seconds ago                                my_first_container
  
====Ход работы====
+
Имя его в данном случае:
  
Запустите контейнер my_first_container и подключитесь к его терминалу (как это сделать - описано выше)
+
my_first_container
  
Установите внутри контейнера текстовый редактор
+
Идентификатор его в данном случае:
  
  apt-get update
+
  f0a3cc6a8b63
apt-get install nano
+
 
 +
Запустить:
  
Создайте с помощью установленного редактора nano файл сценария
+
docker start my_first_container
  
bootstrap.sh
+
или:
  
со следующим содержимым:
+
docker start f0a3cc6a8b63
  
#!/bin/bash
+
Естественно, в конкретном случае идентификатор будет другой.
echo "Hello, $USER_NAME"
 
  
Сделайте файл исполняемым
 
  
chmod +x /bootstrap.sh
+
Подключиться к терминалу Docker-контейнера:
  
Проверьте работоспособность командой:
+
docker attach my_first_container
  
USER_NAME=Ivan /bootstrap.sh
+
или
  
в результате в терминал должна быть выдана строка
+
docker attach f0a3cc6a8b63
  
Hello, Ivan
 
  
Завершите контейнер, выйдя из него:
+
Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать
  
 
  exit
 
  exit
  
Создайте новый образ на базе изменённого контейнера командой:
+
, то контейнер завершит свою работу придётся опять читать выше по тексту как его запускать...
  
docker commit -a Vasya -m "My first own image" my_first_container my_first_image
 
 
Образ будет доступен в списке образов
 
  
docker images
+
Однако есть способ отключиться от терминала и не завершить Docker-контейнер:
  
Выполните запуск контейнера с автоматическим удалением его после завершения, передавая в команду запуска различные значения переменной окружения
+
Для этого нужно последовательно нажать сочетания клавиш:
  
  USER_NAME
+
  Ctrl + P
  
Примеры команды:
+
затем
  
  docker run --rm -e USER_NAME=Ivan -it my_first_image /bootstrap.sh
+
  Ctrl + Q
  
docker run --rm -e USER_NAME=Maria -it my_first_image /bootstrap.sh
 
  
docker run --rm -e USER_NAME=Petr -it my_first_image /bootstrap.sh
+
После этого приглашение командной строки контейнера должно заменить приглашение хостовой системы.
  
docker run --rm -e USER_NAME=Ekaterina -it my_first_image /bootstrap.sh
 
  
===Автоматически (посредством файла Dockerfile)===
+
На этом этапе мы научились запускать контейнер на базе образа. Однако наша цель -- создать собственный образ, поведение контейнеров, запущенных на базе которого который будет отличаться от поведения только что созданного нами контейнера.
  
Откройте терминал хостовой машины и создайте рабочий каталог
+
Для создания собственного образа вручную необходимо внести изменения внутри нашего контейнера, а затем выполнить операцию по "превращению" нашего контейнера в образ.
  
mkdir pr01
+
====Задача====
  
Перейдите в рабочий каталог
+
Создать образ, содержащий стартовый сценарий, который будет считывать переменную окружения с именем пользователя и приветствовать пользователя по имени.
  
cd pr01
+
====Ход работы====
  
====Создание файлов====
+
Запустите контейнер my_first_container и подключитесь к его терминалу (как это сделать - описано выше)
  
В рабочем каталоге создайте файл
+
Установите внутри контейнера текстовый редактор
  
  Dockerfile
+
  apt-get update
 +
apt-get install nano
  
по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):
+
Создайте с помощью установленного редактора nano файл сценария
  
<pre>
+
bootstrap.sh
FROM altlinux/base:p10
 
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 
RUN echo '#!/bin/bash' > /bootstrap.sh
 
RUN echo 'echo "Hello, $USER_NAME"' >> /bootstrap.sh
 
RUN chmod +x /bootstrap.sh
 
CMD /bootstrap.sh
 
</pre>
 
  
 +
со следующим содержимым:
  
В конце этого этапа в рабочем каталоге должен быть один файл:
+
#!/bin/bash
 +
echo "Hello, $USER_NAME"
  
Dockerfile
+
Сделайте файл исполняемым
  
====Создание образа контейнера====
+
chmod +x /bootstrap.sh
  
Для создания Docker-образа (image) выполните команду:
+
Проверьте работоспособность командой:
  
  docker build -t 'my_second_image:latest' .
+
  USER_NAME=Ivan /bootstrap.sh
  
Для проверки существования созданного контейнера выполните команду:
+
в результате в терминал должна быть выдана строка
  
  docker images
+
  Hello, Ivan
  
Среди текста ответа должна появиться строчка с новым контейнером:
+
Завершите контейнер, выйдя из него:
  
  my_second_image        latest              add5d00c3dc0        7 seconds ago      72.9MB
+
  exit
  
====Запуск контейнера на базе образа====
+
Создайте новый образ на базе изменённого контейнера командой:
  
Запуск контейнеров на базе созданного образа (за исключением имени образа и отсутствием необходимости указывать исполняемый скрипт (он указан непосредственно в Dockerfile)) ни чем не будет отличаться от запуска контейнеров в ходе создания образа вручную:
+
docker commit -a Vasya -m "My first own image" my_first_container my_first_image
 +
 +
Образ будет доступен в списке образов
  
  docker run --rm -e USER_NAME=Ivan -it my_second_image
+
  docker images
  
docker run --rm -e USER_NAME=Maria -it my_second_image
+
Выполните запуск контейнера с автоматическим удалением его после завершения, передавая в команду запуска различные значения переменной окружения
  
  docker run --rm -e USER_NAME=Petr -it my_second_image
+
  USER_NAME
  
docker run --rm -e USER_NAME=Ekaterina -it my_second_image
+
Примеры команды:
  
==[Практическая работа №2] Создание контейнера для разработки приложения на языке Java==
+
docker run --rm -e USER_NAME=Ivan my_first_image /bootstrap.sh
  
Откройте терминал хостовой машины и создайте рабочий каталог
+
docker run --rm -e USER_NAME=Maria my_first_image /bootstrap.sh
  
  mkdir pr02
+
  docker run --rm -e USER_NAME=Petr my_first_image /bootstrap.sh
  
Перейдите в рабочий каталог
+
docker run --rm -e USER_NAME=Ekaterina my_first_image /bootstrap.sh
  
cd pr02
+
===Автоматически (посредством файла Dockerfile)===
  
===Создание файлов===
+
Откройте терминал хостовой машины и создайте рабочий каталог
  
Скачайте в рабочий каталог JDK версии 19.0.1. Это можно сделать командой (рекомендуется использовать в локальной сети колледжа)
+
mkdir pr01
  
wget https://wiki.nntc.nnov.ru/download/openjdk-19.0.1_linux-x64_bin.tar.gz
+
Перейдите в рабочий каталог
  
или командой (при работе вне локальной сети колледжа)
+
cd pr01
  
wget https://download.java.net/java/GA/jdk19.0.1/afdd2e245b014143b62ccb916125e3ce/10/GPL/openjdk-19.0.1_linux-x64_bin.tar.gz
+
====Создание файлов====
 
 
Распакуйте загруженный файл командой
 
 
 
tar -xzpf openjdk-19.0.1_linux-x64_bin.tar.gz
 
 
 
В результате будет доступен каталог
 
 
 
jdk-19.0.1
 
 
 
На этом этапе архив можно удалить командой
 
 
 
rm openjdk-19.0.1_linux-x64_bin.tar.gz
 
  
 
В рабочем каталоге создайте файл  
 
В рабочем каталоге создайте файл  
  
  Dockerfile_dev
+
  Dockerfile
  
 
по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):
 
по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):
  
 
<pre>
 
<pre>
FROM altlinux/base:p10
+
FROM alt:p10
 
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
RUN apt-get update -q -y && apt-get install nano git libX11 libX11-devel libXxf86vm libXxf86vm-devel libGL xorg-dri-swrast fonts-ttf-dejavu mate-calc -q -y
+
RUN echo '#!/bin/bash' > /bootstrap.sh
RUN mkdir /opt/jdk-19.0.1
+
RUN echo 'echo "Hello, $USER_NAME"' >> /bootstrap.sh
COPY jdk-19.0.1 /opt/jdk-19.0.1
+
RUN chmod +x /bootstrap.sh
RUN echo PATH="$PATH:/opt/jdk-19.0.1/bin" > /root/.bashrc
+
CMD /bootstrap.sh
RUN source /root/.bashrc
 
 
</pre>
 
</pre>
  
В конце этого этапа в рабочем каталоге должны быть файл:
 
  
Dockerfile_dev
+
В конце этого этапа в рабочем каталоге должен быть один файл:
 
и каталог
 
  
  jdk-19.0.1
+
  Dockerfile
  
===Создание образа контейнера===
+
====Создание образа контейнера====
  
Далее в этом разделе будем исходить из условия, что ваш логин на https://hub.docker.com/ будет
+
Для создания Docker-образа (image) выполните команду:
  
  vpupkin
+
  docker build -t 'my_second_image:latest' .
  
а пароль
+
Для проверки существования созданного контейнера выполните команду:
  
  ну, вы сами знаете...
+
  docker images
  
 +
Среди текста ответа должна появиться строчка с новым контейнером:
  
 +
my_second_image        latest              add5d00c3dc0        7 seconds ago      72.9MB
  
! Также стоит помнить, что в эмуляторе терминала находиться нужно в рабочем каталоге !
+
====Запуск контейнера на базе образа====
  
 +
Запуск контейнеров на базе созданного образа (за исключением имени образа и отсутствием необходимости указывать исполняемый скрипт (он указан непосредственно в Dockerfile)) ни чем не будет отличаться от запуска контейнеров в ходе создания образа вручную:
  
Для создания Docker-образа (image) выполните команду:
+
docker run --rm -e USER_NAME=Ivan my_second_image
  
  docker build -t 'vpupkin/java_dev:latest' -f Dockerfile_dev .
+
  docker run --rm -e USER_NAME=Maria my_second_image
  
 +
docker run --rm -e USER_NAME=Petr my_second_image
  
Для проверки существования созданного образа выполните команду:
+
docker run --rm -e USER_NAME=Ekaterina my_second_image
  
docker images
+
==[Практическая работа №2] Создание контейнера для разработки приложения на языке Java==
  
Среди текста ответа должна появиться строчка с новым образом:
+
Откройте терминал хостовой машины и создайте рабочий каталог
  
  vpupkin/java_dev  latest              fa1a63896356        9 seconds ago      2.42GB
+
  mkdir pr02
  
 +
Перейдите в рабочий каталог
  
===Запуск контейнера на базе образа===
+
cd pr02
  
mkdir /home/student/pr02/src
+
===Создание файлов===
  
На базе полученного образа запустите контейнер, пробросив внутрь контейнера локальный каталог хостовой машины:
+
Скачайте в рабочий каталог JDK версии 19.0.1. Это можно сделать командой (рекомендуется использовать в локальной сети колледжа)
  
  docker run -it --mount source=/home/student/pr02/src,target=/root/src,type=bind --name=java_dev --hostname=java-dev vpupkin/java_dev /bin/bash
+
  wget https://wiki.nntc.nnov.ru/download/openjdk-19.0.1_linux-x64_bin.tar.gz
  
Также в этой команде запуска задаются: имя контейнера, имя хоста, команда, которую выполнит контейнер при запуске и указаны ключи, которые автоматически подключают терминал к контейнеру.
+
или командой (при работе вне локальной сети колледжа)
  
В случае успешного создания контейнера в эмуляторе терминала приглашение должно смениться на такое:
+
wget https://download.java.net/java/GA/jdk19.0.1/afdd2e245b014143b62ccb916125e3ce/10/GPL/openjdk-19.0.1_linux-x64_bin.tar.gz
  
root@java-dev:/#
+
Распакуйте загруженный файл командой
  
Проверка версии Java RE и компилятора должны возвращать примерно следующее:
+
  tar -xzpf openjdk-19.0.1_linux-x64_bin.tar.gz
  
<pre>
+
В результате будет доступен каталог
bash-4.4# java -version
 
openjdk version "19.0.1" 2022-10-18
 
OpenJDK Runtime Environment (build 19.0.1+10-21)
 
OpenJDK 64-Bit Server VM (build 19.0.1+10-21, mixed mode, sharing)
 
bash-4.4#
 
bash-4.4# javac -version
 
javac 19.0.1
 
</pre>
 
  
Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать
+
jdk-19.0.1
  
exit
+
На этом этапе архив можно удалить командой
  
, то контейнер завершит свою работу и найти и запустить его можно таким образом:
+
rm openjdk-19.0.1_linux-x64_bin.tar.gz
  
Найти:
+
В рабочем каталоге создайте файл
  
  docker ps -a
+
  Dockerfile_dev
  
в ответе среди возможных прочих контейнеров должен быть такой:
+
по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):
  
8e5f4fd0a99b        vpupkin/java_dev  "/bin/bash"        3 minutes ago      Exited (0) 6 seconds ago                      java_dev
+
<pre>
 +
FROM alt:p10
 +
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 +
RUN apt-get update -q -y && apt-get install nano git libX11 libX11-devel libXxf86vm libXxf86vm-devel libGL xorg-dri-swrast fonts-ttf-dejavu mate-calc -q -y
 +
RUN mkdir /opt/jdk-19.0.1
 +
COPY jdk-19.0.1 /opt/jdk-19.0.1
 +
RUN echo PATH="$PATH:/opt/jdk-19.0.1/bin" >> /root/.bashrc
 +
RUN source /root/.bashrc
 +
</pre>
  
Имя его в данном случае:
+
В конце этого этапа в рабочем каталоге должны быть файл:
  
  java_dev
+
  Dockerfile_dev
 +
 +
и каталог
  
Идентификатор его в данном случае:
+
jdk-19.0.1
  
8e5f4fd0a99b
+
===Создание образа контейнера===
  
Остальное пока не важно, однако можно догадаться за что отвечают остальные параметры...
+
Далее в этом разделе будем исходить из условия, что ваш логин на https://hub.docker.com/ будет
  
 +
vpupkin
  
Запустить:
+
а пароль
  
  docker start java_dev
+
  ну, вы сами знаете...
  
или:
 
  
docker start 8e5f4fd0a99b
 
  
Естественно, в конкретном случае идентификатор будет другой.
+
! Также стоит помнить, что в эмуляторе терминала находиться нужно в рабочем каталоге !
  
  
Подключиться к терминалу:
+
Для создания Docker-образа (image) выполните команду:
  
  docker attach java_dev
+
  docker build -t 'vpupkin/java_dev:latest' -f Dockerfile_dev .
  
или
 
  
docker attach 8e5f4fd0a99b
+
Для проверки существования созданного образа выполните команду:
  
 +
docker images
  
Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать
+
Среди текста ответа должна появиться строчка с новым образом:
  
  exit
+
  vpupkin/java_dev  latest              fa1a63896356        9 seconds ago      2.42GB
  
, то контейнер завершит свою работу придётся опять читать выше по тексту как его запускать...
 
  
 +
===Запуск контейнера на базе образа===
  
Однако есть способ отключиться от терминала и не завершить контейнер:
+
mkdir /home/student/pr02/src
  
Для этого нужно последовательно нажать сочетания клавиш:
+
На базе полученного образа запустите контейнер, пробросив внутрь контейнера локальный каталог хостовой машины:
  
  Ctrl + P
+
  docker run -it --mount source=/home/student/pr02/src,target=/root/src,type=bind --name=java_dev --hostname=java-dev vpupkin/java_dev /bin/bash
  
затем
+
Также в этой команде запуска задаются: имя контейнера, имя хоста, команда, которую выполнит контейнер при запуске и указаны ключи, которые автоматически подключают терминал к контейнеру.
  
Ctrl + Q
+
В случае успешного создания контейнера в эмуляторе терминала приглашение должно смениться на такое:
  
 +
root@java-dev:/#
  
После этого приглашение командной строки контейнера должно заменить приглашение хостовой системы.
+
Проверка версии Java RE и  компилятора должны возвращать примерно следующее:
  
 +
<pre>
 +
root@java-dev:/# java -version
 +
openjdk version "19.0.1" 2022-10-18
 +
OpenJDK Runtime Environment (build 19.0.1+10-21)
 +
OpenJDK 64-Bit Server VM (build 19.0.1+10-21, mixed mode, sharing)
 +
bash-4.4#
 +
bash-4.4# javac -version
 +
javac 19.0.1
 +
</pre>
  
На этом этапе мы научились создавать образ контейнера и запускать контейнер на его базе.
+
Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать
  
===Сборка приложения на языке Java в docker-контейнере===
+
exit
  
Перейдём в каталог
+
, то контейнер завершит свою работу и найти и запустить его можно таким образом:
  
cd /root/src/
+
Найти:
  
Склонируем проект приложения на Java
+
docker ps -a
  
git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter
+
в ответе среди возможных прочих контейнеров должен быть такой:
  
Перейдём в проект
+
8e5f4fd0a99b        vpupkin/java_dev  "/bin/bash"        3 minutes ago      Exited (0) 6 seconds ago                      java_dev
  
cd simple-counter
+
Имя его в данном случае:
  
Исходя из рекомендаци в файле README.md выполним сборку проекта
+
java_dev
  
bash mvnw install
+
Идентификатор его в данном случае:
bash mvnw dependency:copy-dependencies
 
  
В случае успешной сборки в терминале котейнера долждно быть написано что-то похожее на это:
+
8e5f4fd0a99b
  
<pre>
+
Остальное пока не важно, однако можно догадаться за что отвечают остальные параметры...
[INFO] ------------------------------------------------------------------------
 
[INFO] BUILD SUCCESS
 
[INFO] ------------------------------------------------------------------------
 
</pre>
 
  
На этом этам сборки приложения заврешён.
 
  
Теперь наша задача - запустить приложение прямо на хостовой машине (но выполняться оно будет в контейнере).
+
Запустить:
  
===Запуск собранного приложения в docker-контейнере на базе образа с JDK===
+
docker start java_dev
  
Запустим новый контейнер командой:
+
или:
  
  docker run --rm -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --mount source=/home/student/pr02/src,target=/root/src,type=bind --name=java_test --hostname=java-test vpupkin/java_dev /bin/bash
+
  docker start 8e5f4fd0a99b
  
Для успешного запуска графического приложения, работающего в контейнере, с возможностью отображения графического интерфейса, в этой команде сделано две вещи:
+
Естественно, в конкретном случае идентификатор будет другой.
  
Первая: установлена (внутрь контейнера) переменная окружения
 
  
DISPLAY
+
Подключиться к терминалу:
  
равная значению аналогичной переменной окружения хостовой системы.
+
docker attach java_dev
  
Вторая: проброшено устройство
+
или
  
  /tmp/.X11-unix
+
  docker attach 8e5f4fd0a99b
  
из хостовой системы в контейнер.
 
  
Также добавлено монтирование каталога src для обмена файлами межу контейнером и хостовой системой, а также добавлена опция
+
Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать
  
  --rm
+
  exit
  
которая уничтожает контейнер после его завершения (за данные мы не переживаем, они же лежат локально в каталоге src, который каждый раз монтируется при старте в новый контейнер).
+
, то контейнер завершит свою работу придётся опять читать выше по тексту как его запускать...
  
  
Эта опция сюда добавлена, поскольку сама команда старта контейнера содержит в себе цель запускать именно оболочку /bin/bash для ручного тестирования запуска собранного приложения.
+
Однако есть способ отключиться от терминала и не завершить контейнер:
  
Предполагается, что после такого тестирования контейнер не нужен и при выходе из него его логичнее всего автоматически удалять.
+
Для этого нужно последовательно нажать сочетания клавиш:
  
 +
Ctrl + P
  
Когда работа собранного приложения протестирована и есть понимание, что всё работает корректно, можно приступать к сборке образа для production-контейнера, в котором необходимо оставить необходимое и достаточное количество библиотек, необходимых только для запуска уже собранного приложения, а пакеты и утилиты, необходимые для сборки, не включать в результирующий образ.
+
затем
  
Важный момент: В некоторых операционных системах может потребоваться выполнить команду
+
Ctrl + Q
  
xhost +
 
  
для разрешения подключения контейнера к графической оболочке X-сервера.
+
После этого приглашение командной строки контейнера должно заменить приглашение хостовой системы.
  
Тестовый запуск приложения можно выполнить командами:
 
  
cd /root/src/simple-counter/
+
На этом этапе мы научились создавать образ контейнера и запускать контейнер на его базе.
java --module-path=target/dependency/ --add-modules javafx.controls,javafx.fxml -cp target/demo_up04-1.0-SNAPSHOT.jar com.example.demo_up04.DemoApplication
 
  
===Отвечаем на главный вопрос?===
+
===Сборка приложения на языке Java в docker-контейнере===
  
Вопрос звучит так:
+
Перейдём в каталог
  
  Если мы уже собрали приложение, то нужно ли конечному пользователю инструменты для сборки приложения, которые были нужны в сборочном контейнере, и исходный код приложения?
+
  cd /root/src/
  
 +
Склонируем проект приложения на Java
  
Не нужны по нескольким причинам:
+
git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter
  
# Исходный чаще всего остаётся интеллектуальной собственностью компании-разработчика и не должен оказаться у заказчика
+
Перейдём в проект
# Наличие на Production-системе компилятора какого-либо языка и/или каких-либо средств разработки является потенциальной уязвимостью системы
 
# Инструменты сборки и тестирования никогда не понадобятся конечному пользователю на  Production-системе, но всегда будут занимать место на файловой системе контейнера
 
  
Поэтому для конечного пользователя целесообразно создать новый образ, исключив оттуда всё лишнее и оставив лишь непосредственно готовое приложение.
+
cd simple-counter
  
Как это сделать -- см. в следующей практической работе.
+
Исходя из рекомендаци в файле README.md выполним сборку проекта
  
==[Практическая работа №3] Создание контейнера для запуска Java-приложения==
+
bash mvnw install
Откройте терминал хостовой машины. Создайте рабочий каталог
+
bash mvnw dependency:copy-dependencies
  
mkdir pr03
+
В случае успешной сборки в терминале котейнера долждно быть написано что-то похожее на это:
  
Перейдите в рабочий каталог
+
<pre>
 +
[INFO] ------------------------------------------------------------------------
 +
[INFO] BUILD SUCCESS
 +
[INFO] ------------------------------------------------------------------------
 +
</pre>
  
cd pr03
+
На этом этам сборки приложения заврешён.
  
===Создание файлов===
+
Теперь наша задача - запустить приложение прямо на хостовой машине (но выполняться оно будет в контейнере).
  
В рабочем каталоге создайте файл
+
===Запуск собранного приложения в docker-контейнере на базе образа с JDK===
  
Dockerfile_prod
+
Запустим новый контейнер командой:
  
по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):
+
docker run --rm -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --mount source=/home/student/pr02/src,target=/root/src,type=bind --name=java_test --hostname=java-test vpupkin/java_dev /bin/bash
  
<pre>
+
Для успешного запуска графического приложения, работающего в контейнере, с возможностью отображения графического интерфейса, в этой команде сделано две вещи:
FROM altlinux/base:p10
 
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 
RUN apt-get update -q -y \
 
    && apt-get install nano su libX11 libX11-devel libXxf86vm libXxf86vm-devel libGL xorg-dri-swrast fonts-ttf-dejavu mate-calc -q -y \
 
    && apt-get autoclean \
 
    && apt-get autoremove
 
  
RUN adduser app
+
Первая: установлена (внутрь контейнера) переменная окружения
  
RUN mkdir /opt/jdk-19.0.1
+
DISPLAY
COPY jdk-19.0.1 /opt/jdk-19.0.1
 
  
RUN mkdir /opt/app
+
равная значению аналогичной переменной окружения хостовой системы.
COPY app /opt/app
 
COPY startup.sh /
 
RUN chmod +x /startup.sh
 
  
RUN echo "PATH=$PATH:/opt/jdk-19.0.1/bin" > /home/app/.bashrc
+
Вторая: проброшено устройство
RUN echo "export JAVA_HOME=/opt/jdk-19.0.1" >> /home/app/.bashrc
 
  
USER app
+
/tmp/.X11-unix
  
CMD /startup.sh
+
из хостовой системы в контейнер.
</pre>
 
  
Создайте каталог app в рабочем каталоге
+
Также добавлено монтирование каталога src для обмена файлами межу контейнером и хостовой системой, а также добавлена опция
 
mkdir app
 
  
Скопируйте исполняемый файл, полученный в предыдущей работе в рабочий каталог
+
--rm
  
/bin/cp -rf ../pr02/src/simple-counter/target app/
+
которая уничтожает контейнер после его завершения (за данные мы не переживаем, они же лежат локально в каталоге src, который каждый раз монтируется при старте в новый контейнер).
  
Скачайте в рабочий каталог JDK версии 19.0.1. Это можно сделать командой (рекомендуется использовать в локальной сети колледжа)
 
  
wget https://wiki.nntc.nnov.ru/download/openjdk-19.0.1_linux-x64_bin.tar.gz
+
Эта опция сюда добавлена, поскольку сама команда старта контейнера содержит в себе цель запускать именно оболочку /bin/bash для ручного тестирования запуска собранного приложения.
  
или командой (при работе вне локальной сети колледжа)
+
Предполагается, что после такого тестирования контейнер не нужен и при выходе из него его логичнее всего автоматически удалять.
  
wget https://download.java.net/java/GA/jdk19.0.1/afdd2e245b014143b62ccb916125e3ce/10/GPL/openjdk-19.0.1_linux-x64_bin.tar.gz
 
  
Распакуйте загруженный файл командой
+
Когда работа собранного приложения протестирована и есть понимание, что всё работает корректно, можно приступать к сборке образа для production-контейнера, в котором необходимо оставить необходимое и достаточное количество библиотек, необходимых только для запуска уже собранного приложения, а пакеты и утилиты, необходимые для сборки, не включать в результирующий образ.
 +
 
 +
Важный момент: В некоторых операционных системах может потребоваться выполнить команду
  
  tar -xzpf openjdk-19.0.1_linux-x64_bin.tar.gz
+
  xhost +
  
На этом этапе архив можно удалить командой
+
для разрешения подключения контейнера к графической оболочке X-сервера.
  
rm openjdk-19.0.1_linux-x64_bin.tar.gz
+
Тестовый запуск приложения можно выполнить командами:
  
Создайте в рабочем каталоге файл
+
cd /root/src/simple-counter/
 +
java --module-path=target/dependency/ --add-modules javafx.controls,javafx.fxml -cp target/demo_up04-1.0-SNAPSHOT.jar com.example.demo_up04.DemoApplication
  
startup.sh
+
===Отвечаем на главный вопрос?===
  
со следующим содержимым
+
Вопрос звучит так:
  
<pre>
+
Если мы уже собрали приложение, то нужно ли конечному пользователю инструменты для сборки приложения, которые были нужны в сборочном контейнере, и исходный код приложения?
#!/bin/bash
 
source /home/app/.bashrc
 
cd /opt/app
 
java --module-path=target/dependency/ --add-modules javafx.controls,javafx.fxml -cp target/demo_up04-1.0-SNAPSHOT.jar com.example.demo_up04.DemoApplication
 
</pre>
 
  
В конце этого этапа в рабочем каталоге должно быть два файла:
 
  
Dockerfile_prod
+
Не нужны по нескольким причинам:
startup.sh
 
  
И два каталога:
+
# Исходный код чаще всего остаётся интеллектуальной собственностью компании-разработчика и не должен оказаться у заказчика;
 +
# Наличие на Production-системе компилятора какого-либо языка и/или каких-либо средств разработки является потенциальной уязвимостью системы;
 +
# Инструменты сборки и тестирования никогда не понадобятся конечному пользователю на Production-системе, но всегда будут занимать место на файловой системе контейнера.
  
jdk-19.0.1
+
Поэтому для конечного пользователя целесообразно создать новый образ, исключив оттуда всё лишнее и оставив лишь непосредственно готовое приложение.
app
 
  
===Создание образа контейнера===
+
Как это сделать -- см. в следующей практической работе.
  
Далее в этом разделе будем исходить из условия, что ваш логин на https://hub.docker.com/ будет
+
==[Практическая работа №3] Создание контейнера для запуска Java-приложения==
 +
Откройте терминал хостовой машины. Создайте рабочий каталог
  
  vpupkin
+
  mkdir pr03
  
а пароль
+
Перейдите в рабочий каталог
  
  ну, вы сами знаете...
+
  cd pr03
  
 +
===Создание файлов===
  
 +
В рабочем каталоге создайте файл
  
  ! Также стоит помнить, что в эмуляторе терминала находиться нужно в рабочем каталоге !
+
  Dockerfile_prod
  
 +
по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):
  
Для создания Docker-образа (image) выполните команду:
+
<pre>
 +
FROM alt:p10
 +
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 +
RUN apt-get update -q -y \
 +
    && apt-get install nano su libX11 libX11-devel libXxf86vm libXxf86vm-devel libGL xorg-dri-swrast fonts-ttf-dejavu mate-calc -q -y \
 +
    && apt-get autoclean \
 +
    && apt-get autoremove
  
docker build -t 'vpupkin/java_prod:latest' -f Dockerfile_prod .
+
RUN adduser app
  
 +
RUN mkdir /opt/jdk-19.0.1
 +
COPY jdk-19.0.1 /opt/jdk-19.0.1
  
Для проверки существования созданного контейнера выполните команду:
+
RUN mkdir /opt/app
 +
COPY app /opt/app
 +
COPY startup.sh /
 +
RUN chmod +x /startup.sh
  
docker images
+
RUN echo "PATH=$PATH:/opt/jdk-19.0.1/bin" > /home/app/.bashrc
 +
RUN echo "export JAVA_HOME=/opt/jdk-19.0.1" >> /home/app/.bashrc
  
Среди текста ответа должна появиться строчка с новым контейнером:
+
USER app
  
vpupkin/java_prod  latest              20bb2900074d        16 seconds ago      217MB
+
CMD /startup.sh
 +
</pre>
  
 +
Создайте каталог app в рабочем каталоге
 +
 +
mkdir app
  
! Обратите внимание на размер контейнера !
+
Скопируйте исполняемый файл, полученный в предыдущей работе в рабочий каталог
Сравните размер контейнера с размером контейнера java_dev из предыдущей работы
 
  
===Запуск контейнера на базе образа===
+
/bin/cp -r ../pr02/src/simple-counter/target app/
  
Создадим каталог для обмена данными с контейнером
+
Скачайте в рабочий каталог JDK версии 19.0.1. Это можно сделать командой (рекомендуется использовать в локальной сети колледжа)
  
  mkdir $HOME/data
+
  wget https://wiki.nntc.nnov.ru/download/openjdk-19.0.1_linux-x64_bin.tar.gz
  
На базе полученного образа запустите контейнер, пробросив внутрь контейнера локальный каталог хостовой машины:
+
или командой (при работе вне локальной сети колледжа)
  
  docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --mount source="$HOME/data",target=/home/app/data,type=bind --name=java_prod --hostname=java-prod vpupkin/java_prod
+
  wget https://download.java.net/java/GA/jdk19.0.1/afdd2e245b014143b62ccb916125e3ce/10/GPL/openjdk-19.0.1_linux-x64_bin.tar.gz
  
 +
Распакуйте загруженный файл командой
  
При запуске контейнера таким образом не указывается команда, т.к. она задаётся в файле
+
tar -xzpf openjdk-19.0.1_linux-x64_bin.tar.gz
  
Dockerfile_prod
+
На этом этапе архив можно удалить командой
  
строчкой
+
rm openjdk-19.0.1_linux-x64_bin.tar.gz
  
CMD /bin/su -c "/startup.sh" app
+
Создайте в рабочем каталоге файл
  
Результатом запуска контейнера должно стать запущенное внутри контейнера графическое приложение с отображением графического интерфейса на хостовой машине.
+
startup.sh
  
При закрытии окна графического приложения контейнер будет завершён и будет доступен среди списка контейнеров
+
со следующим содержимым
  
docker ps -a
+
<pre>
 +
#!/bin/bash
 +
source /home/app/.bashrc
 +
cd /opt/app
 +
java --module-path=target/dependency/ --add-modules javafx.controls,javafx.fxml -cp target/demo_up04-1.0-SNAPSHOT.jar com.example.demo_up04.DemoApplication
 +
</pre>
  
Повторный запуск уже существующего контейнера можно осуществить по имени контейнера командой:
+
В конце этого этапа в рабочем каталоге должно быть два файла:
  
  docker start java_prod
+
  Dockerfile_prod
 +
startup.sh
  
==[Практическая работа №4] Взаимодействие двух контейнеров по сети (ручной запуск)==
+
И два каталога:
  
Задача: Запустить Java-приложение в контейнере с именем c2, который взаимодействует с базой данных Mariadb, запущенной в контейнере с именем c1
+
jdk-19.0.1
 +
app
  
===Загрузка образа для контейнера с mariadb===
+
===Создание образа контейнера===
  
docker pull mariadb
+
Далее в этом разделе будем исходить из условия, что ваш логин на https://hub.docker.com/ будет
  
===Создание сетевого моста===
+
vpupkin
  
docker network create net_c1_c2
+
а пароль
  
Проверить список сетевых мостов можно командой
+
ну, вы сами знаете...
  
docker network list
 
  
===Запуск контейнера c1 и подготовка базы данных===
 
  
Создать контейнер с базой данных Mariadb и задать пароль пользователя root через переменную окружения
+
! Также стоит помнить, что в эмуляторе терминала находиться нужно в рабочем каталоге !
  
docker run --name=c1 --hostname=c1 -e MARIADB_ROOT_PASSWORD=123321 -e MARIADB_DATABASE=java_app_db -e MARIADB_USER=java_app_user -e MARIADB_PASSWORD=java_app_password --network net_c1_c2 -d mariadb
 
  
Проверить корректность подключения к Mariadb с созданным пользователем к созданной базе данных (подключиться к консоли контейнера c1 и воспользоваться клиентом mysql)
+
Для создания Docker-образа (image) выполните команду:
  
  docker exec -it c1 /bin/bash
+
  docker build -t 'vpupkin/java_prod:latest' -f Dockerfile_prod .
  
Внутри контейнера запустить клиент mysql с параметрами подключения к бд:
 
  
mysql -u java_app_user -pjava_app_password -h localhost java_app_db
+
Для проверки существования созданного контейнера выполните команду:
 
Выход из mysql и из контейнера
 
  
  exit
+
  docker images
exit
 
  
===Запуск контейнера c2 с Java-приложением===
+
Среди текста ответа должна появиться строчка с новым контейнером:
  
Запуск контейнера с Java-приложением производится аналогично запуску, подробно описанному в практической работе №3 с учётом ряда нюансов:
+
vpupkin/java_prod  latest              20bb2900074d        16 seconds ago      217MB
  
1. Необходимо учитывать, что имя запускаемого контейнера должно быть
 
  
  с2
+
  ! Обратите внимание на размер контейнера !
 +
Сравните размер контейнера с размером контейнера java_dev из предыдущей работы
  
2. Необходимо учитывать, что имя хоста запускаемого контейнера должно быть
+
===Запуск контейнера на базе образа===
  
с2
+
Создадим каталог для обмена данными с контейнером
  
3. Необходимо учитывать, что для корректного подключения Java-приложения к базе данных, доступной в контейнере с именем_контейнера=именем_хоста=с1 необходимо при запуске контейнера с2 передать набор переменных окружения для настройки Java-приложения на работу с базой данных в контейнере c1
+
mkdir $HOME/data
  
DB_HOST=c1
+
На базе полученного образа запустите контейнер, пробросив внутрь контейнера локальный каталог хостовой машины:
DB_PORT=3306
 
DB_NAME=java_app_db
 
DB_USER=java_app_user
 
DB_PASS=java_app_password
 
  
Пример команды для запуска контейнера c2 (запуск контейнера осуществляется на базе образа, созданного в практической работе №3)
+
docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --mount source="$HOME/data",target=/home/app/data,type=bind --name=java_prod --hostname=java-prod vpupkin/java_prod
  
docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --name=c2 --hostname=c2 -e DB_HOST=c1 -e DB_PORT=3306 -e DB_NAME=java_app_db -e DB_USER=java_app_user -e DB_PASS=java_app_password --network net_c1_c2 vpupkin/java_prod
 
  
При необходимости монтирования директорий хостовой машины в контейнер также могут быть использованы дополнительные параметры, как было показано в примере запуска контейнера в практической работе №3 с параметром
+
При запуске контейнера таким образом не указывается команда, т.к. она задаётся в файле
  
  --mount source="$HOME/data",target=/home/app/data,type=bind
+
  Dockerfile_prod
  
В данном примере этот параметр опущен, т.к. тестовое приложение не имеет функций чтения и записи файлов.
+
строчкой
  
===Самостоятельное задание===
+
CMD /bin/su -c "/startup.sh" app
  
====Подготовка====
+
Результатом запуска контейнера должно стать запущенное внутри контейнера графическое приложение с отображением графического интерфейса на хостовой машине.
  
Придумать уникальный префикс для именования названий, завязанный на фамилию и инициалы обучающегося.
+
При закрытии окна графического приложения контейнер будет завершён и будет доступен среди списка контейнеров
  
Например, для обучающегося
+
docker ps -a
  
Иванов Иван Иванович
+
Повторный запуск уже существующего контейнера можно осуществить по имени контейнера командой:
  
Префикс (<prefix>) будет состоять из фамилии и инициалов
+
docker start java_prod
  
ivanov_ii
+
==[Практическая работа №4] Взаимодействие двух контейнеров по сети (ручной запуск)==
  
Тогда в приведённых ниже примерах необходимо
+
Задача: Запустить Java-приложение в контейнере с именем c2, который взаимодействует с базой данных Mariadb, запущенной в контейнере с именем c1
  
<prefix>
+
===Загрузка образа для контейнера с mariadb===
  
заменять на
+
docker pull mariadb
  
ivanov_ii
+
===Создание сетевого моста===
  
Например
+
docker network create net_c1_c2
  
ivanov_ii_container_db
+
Проверить список сетевых мостов можно командой
  
 +
docker network list
  
====Выполнение задания====
+
===Запуск контейнера c1 и подготовка базы данных===
  
Используя справку по docker и набор выполненных практических работ запустить тестовое Java-приложение в двух контейнерах, аналогичных контейнерам с1 и с2, исходя из следующих параметров:
+
Создать контейнер с базой данных Mariadb и задать исходные параметры работы СУБД (название базы данных, логин и пароль для базы данных, пароль пользователя root) через переменные окружения
  
0. Сетевой мост должен иметь имя
+
docker run --name=c1 --hostname=c1 -e MARIADB_ROOT_PASSWORD=123321 -e MARIADB_DATABASE=java_app_db -e MARIADB_USER=java_app_user -e MARIADB_PASSWORD=java_app_password --network net_c1_c2 -d mariadb
  
net_<prefix>
+
Проверить корректность подключения к Mariadb с созданным пользователем к созданной базе данных (подключиться к консоли контейнера c1 и воспользоваться клиентом mariadb)
  
1. Контейнер с базой данных должен иметь имя
+
docker exec -it c1 /bin/bash
  
<prefix>_container_db
+
Внутри контейнера запустить клиент mariadb (ранее это был клиент mysql) с параметрами подключения к бд:
  
и хостовое имя
+
mariadb -u java_app_user -pjava_app_password -h localhost java_app_db
 +
 +
Выход из mariadb и затем из контейнера
  
  <prefix>-container-db
+
  exit
 +
exit
  
2. Контейнер с Java-приложением должен иметь имя
+
===Запуск контейнера c2 с Java-приложением===
  
<prefix>_container_app
+
Запуск контейнера с Java-приложением производится аналогично запуску, подробно описанному в практической работе №3 с учётом ряда нюансов:
  
и хостовое имя
+
1. Необходимо учитывать, что имя запускаемого контейнера должно быть
  
  <prefix>-container-app
+
  с2
  
3. База данных должна иметь название
+
2. Необходимо учитывать, что имя хоста запускаемого контейнера должно быть
  
  <prefix>_application_db
+
  с2
  
имя пользователя
+
3. Необходимо учитывать, что для корректного подключения Java-приложения к базе данных, доступной в контейнере с именем_контейнера=именем_хоста=с1 необходимо при запуске контейнера с2 передать набор переменных окружения для настройки Java-приложения на работу с базой данных в контейнере c1
  
  <prefix>_application_user
+
  DB_HOST=c1
 +
DB_PORT=3306
 +
DB_NAME=java_app_db
 +
DB_USER=java_app_user
 +
DB_PASS=java_app_password
  
пароль
+
Пример команды для запуска контейнера c2 (запуск контейнера осуществляется на базе образа, созданного в практической работе №3)
  
<prefix>_applicationPassw0rd123
+
Не забудем про
  
Ход работы отразить в отчёте по практической работе №4
+
xhost +
  
==[Практическая работа №5] Взаимодействие двух контейнеров по сети (docker-compose)==
+
docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --name=c2 --hostname=c2 -e DB_HOST=c1 -e DB_PORT=3306 -e DB_NAME=java_app_db -e DB_USER=java_app_user -e DB_PASS=java_app_password --network net_c1_c2 vpupkin/java_prod
  
===Предисловие===
+
При необходимости монтирования директорий хостовой машины в контейнер также могут быть использованы дополнительные параметры, как было показано в примере запуска контейнера в практической работе №3 с параметром
  
Решаемая в данной практической работе задача аналогична задаче из практической работы №4. Отличия состоят лишь в том, что в практической работе №4 запуск двух контейнеров, взаимодействующих между собой внутри изолированной сети, осуществляется вручную, путём выполнения команд:
+
--mount source="$HOME/data",target=/home/app/data,type=bind
  
docker run ...
+
В данном примере этот параметр опущен, т.к. тестовое приложение не имеет функций чтения и записи файлов.
  
Для автоматизации запуска приложений, компоненты которых разделены по контейнерам (их (приложения в контейнерах) ещё называют микросервисами) может быть использован инструмент:
+
===Самостоятельное задание===
  
docker-compose
+
====Подготовка====
  
Инструмент docker-compose (смысл названия можно перевести как "композиция из докер контейнеров") предназначен для того, чтобы автоматически запустить несколько docker-контейнеров в одном контексте (как правило, под контекстом подразумевается общая сеть, изолированная от хостовой системы но доступная для всех контейнеров композиции (как говорят DevOps-инженеры -- "композы")).
+
Придумать уникальный префикс для именования названий, завязанный на фамилию и инициалы обучающегося.
  
В практической работе №2 мы изучали два способа создания docker-образа: ручной и автоматический.
+
Например, для обучающегося
  
Ручной способ подразумевал создание контейнера на базе стандартного образа, выполнение ряда действий внутри этого контейнера вручную, с последующим созданием образа на базе изменённого вручную контейнера. В результате получался новый образ, на базе которого можно запускать новые контейнеры.
+
Иванов Иван Иванович
  
Автоматический способ подразумевал решение аналогичной задачи, но без участия пользователя. Т.е. пользователь один раз описывал файл (Dockerfile), который включал в себя все необходимые команды (которые в ручном режиме пользователь выполнял вручную) и директивы, которых минимально необходимо и достаточно для сборки образа в автоматическом режиме. После того, как был подготовлен Dockerfile, на его базе командой:
+
Префикс (<prefix>) будет состоять из фамилии и инициалов
  
  docker build...
+
  ivanov_ii
  
производилась сборка образа
+
Тогда в приведённых ниже примерах необходимо
  
 +
<prefix>
  
Между ручным запуском двух контейнеров, описанным в практической работе №4, и автоматическим запуском композиции из докер контейнеров (композы), описываемой в этой практической работе, можно провести такую же аналогию, как между созданием образа контейнера вручную и созданием образа контейнера автоматически. Два этих способа (ручной и автоматический) объединяет наличие специального конфигурационного файла. В случае с автоматической сборкой docker-образа это файл:
+
заменять на
  
  Dockerfile
+
  ivanov_ii
  
, в случае же с автоматическим запуском нескольких контейнеров в композе -- это файл:
+
Например
  
  docker-compose.yaml
+
  ivanov_ii_container_db
  
Для того, чтобы запустить любую композицию контейнеров, необходимо:
 
  
1. Сконфигурировать файл
+
====Выполнение задания====
  
docker-compose.yaml
+
Используя справку по docker и набор выполненных практических работ запустить тестовое Java-приложение в двух контейнерах, аналогичных контейнерам с1 и с2, исходя из следующих параметров:
  
2. Выполнить запуск композы командой
+
0. Сетевой мост должен иметь имя
  
  docker-compose up ...
+
  net_<prefix>
  
===Установка docker-compose===
+
1. Контейнер с базой данных должен иметь имя
  
В хостовой системе откройте терминал и выполните команду для получения доступа под суперпользователем root
+
<prefix>_container_db
  
su -
+
и хостовое имя
  
Введите пароль от суперпользователя. Приглашение должно смениться на суперпользовательское и заканчиваться символом решётки. В этом режиме выполните команду установки пакета из репозитория:
+
<prefix>-container-db
  
apt-get install docker-compose -y
+
2. Контейнер с Java-приложением должен иметь имя
  
При необходимости, перед выполнением этой команды можно выполнить команду обновления базы данных пакетов в репозитории:
+
<prefix>_container_app
  
apt-get update
+
и хостовое имя
  
===Практика===
+
<prefix>-container-app
  
Создайте рабочий каталог и перейдите в него
+
3. База данных должна иметь название
 +
 
 +
<prefix>_application_db
 +
 
 +
имя пользователя
 +
 
 +
<prefix>_application_user
 +
 
 +
пароль
  
  mkdir compose_с1_с2
+
  <prefix>_applicationPassw0rd123
cd compose_с1_с2
 
  
Создайте файл
+
Ход работы отразить в отчёте по практической работе №4
  
docker-compose.yaml
+
==[Практическая работа №5] Взаимодействие двух контейнеров по сети (docker compose)==
  
со следующим содержимым
+
===Предисловие===
  
<pre>
+
Решаемая в данной практической работе задача аналогична задаче из практической работы №4. Отличия состоят лишь в том, что в практической работе №4 запуск двух контейнеров, взаимодействующих между собой внутри изолированной сети, осуществляется вручную, путём выполнения команд:
version: '3.9'
 
  
services:
+
docker run ...
  c1:
+
 
    container_name: "c1"
+
Для автоматизации запуска приложений, компоненты которых разделены по контейнерам (их (приложения в контейнерах) ещё называют микросервисами) может быть использован инструмент:
    hostname: "c1"
 
    image: "mariadb"
 
    restart: "always"
 
    environment:
 
      MARIADB_ROOT_PASSWORD: "123321"
 
      MARIADB_DATABASE: "java_app_db"
 
      MARIADB_USER: "java_app_user"
 
      MARIADB_PASSWORD: "java_app_password"
 
    networks:
 
      - net_c1_c2
 
  
  c2:
+
docker compose
    container_name: "c2"
 
    hostname: "c2"
 
    image: "vpupkin/java_prod"
 
    restart: "no"
 
    environment:
 
      DISPLAY: "$DISPLAY"
 
      DB_HOST: "c1"
 
      DB_PORT: "3306"
 
      DB_NAME: "java_app_db"
 
      DB_USER: "java_app_user"
 
      DB_PASS: "java_app_password"
 
    volumes:
 
      - /tmp/.X11-unix:/tmp/.X11-unix
 
    networks:
 
      - net_c1_c2
 
  
networks:
+
Инструмент docker compose (смысл названия можно перевести как "композиция из докер контейнеров") предназначен для того, чтобы автоматически запустить несколько docker-контейнеров в одном контексте (как правило, под контекстом подразумевается общая сеть, изолированная от хостовой системы но доступная для всех контейнеров композиции (как говорят DevOps-инженеры -- "композы")).
  net_c1_c2:
 
    name: net_c1_c2
 
</pre>
 
  
 +
В практической работе №2 мы изучали два способа создания docker-образа: ручной и автоматический.
  
В результате в рабочем каталоге должен быть файл:
+
Ручной способ подразумевал создание контейнера на базе стандартного образа, выполнение ряда действий внутри этого контейнера вручную, с последующим созданием образа на базе изменённого вручную контейнера. В результате получался новый образ, на базе которого можно запускать новые контейнеры.
  
docker-compose.yaml
+
Автоматический способ подразумевал решение аналогичной задачи, но без участия пользователя. Т.е. пользователь один раз описывал файл (Dockerfile), который включал в себя все необходимые команды (которые в ручном режиме пользователь выполнял вручную) и директивы, которых минимально необходимо и достаточно для сборки образа в автоматическом режиме. После того, как был подготовлен Dockerfile, на его базе командой:
  
Для запуска композиции выполните в рабочем каталоге команду
+
docker build...
  
docker-compose up -d
+
производилась сборка образа
  
В результате по описанной в файле docker-compose.yaml схеме сервисов будут запущены два контейнера: с1 и с2. В том числе из контейнера с2 будет запущено графическое приложение, которое будет работать с базой данных, запущенной в контейнере с1.
 
  
====Возможные проблемы и их решения====
+
Между ручным запуском двух контейнеров, описанным в практической работе №4, и автоматическим запуском композиции из докер контейнеров (композы), описываемой в этой практической работе, можно провести такую же аналогию, как между созданием образа контейнера вручную и созданием образа контейнера автоматически. Два этих способа (ручной и автоматический) объединяет наличие специального конфигурационного файла. В случае с автоматической сборкой docker-образа это файл:
  
Проблема №1: не запускается графический интерфейс Java-приложения.
+
Dockerfile
Решение: Открыть терминал хостовой системы и выполнить в нём команду для разрешения подключения к графической системы извне (в частности -- из контейнера):
 
  
xhost +
+
, в случае же с автоматическим запуском нескольких контейнеров в композе -- это файл:
  
Проблема №2: Java-приложение не может подключиться к базе данных.
+
docker-compose.yaml
Решение: Повторно запустить контейнер c2. При первом запуске композы в контейнере c1 сервис базы данных не успевает запуститься к моменту, когда в контейнере c2 стартует Java-приложение. Поэтому приложение показывает ошибку. Когда окно приложение закрывается -- контейнер c2 прекращает свою работу, однако контейнер c1 по прежнему работает (и в нём с высокой долей вероятности уже запустилась СУБД). Поэтому повторный запуск контейнера c2 запустит Java-приложение, в котором уже не будет ошибки подключения к базе данных (конечно, при условии, что всё верно настроено).
 
  
====Работа с контейнерами в контексте docker-compose====
+
Для того, чтобы запустить любую композицию контейнеров, необходимо:
  
Если мы находимся в каталоге с файлом (Это важно! Все команды этого раздела актуальны, если соблюдается простое правило -- мы стоим в каталоге с этим файлом):
+
1. Сконфигурировать файл
  
 
  docker-compose.yaml
 
  docker-compose.yaml
  
то для упрощения работы с контейнерами (сервисами микросервисной архитектуры), входящими в состав композы, можно вместо команды
+
2. Выполнить запуск композы командой
  
  docker
+
  docker compose up ...
  
использовать команду
+
===Практика===
  
docker-compose
+
Создайте рабочий каталог и перейдите в него
  
В случае с нашей композой сервисы имеют названия c1 и с2, следовательно, для их остановки можно применять команды:
+
mkdir compose_с1_с2
 +
cd compose_с1_с2
  
docker-compose stop c1
+
Создайте файл
  
или
+
docker-compose.yaml
  
docker-compose stop c2
+
со следующим содержимым
  
а для остановки всей композы -- команду:
+
<pre>
 +
version: '3.9'
  
docker-compose stop
+
services:
 
+
  c1:
а для запуска, соответственно
+
    container_name: "c1"
 
+
    hostname: "c1"
docker-compose start c1
+
    image: "mariadb"
 
+
    restart: "always"
или
+
    environment:
 +
      MARIADB_ROOT_PASSWORD: "123321"
 +
      MARIADB_DATABASE: "java_app_db"
 +
      MARIADB_USER: "java_app_user"
 +
      MARIADB_PASSWORD: "java_app_password"
 +
    networks:
 +
      - net_c1_c2
  
docker-compose start c2
+
  c2:
 +
    container_name: "c2"
 +
    hostname: "c2"
 +
    image: "vpupkin/java_prod"
 +
    restart: "no"
 +
    environment:
 +
      DISPLAY: "$DISPLAY"
 +
      DB_HOST: "c1"
 +
      DB_PORT: "3306"
 +
      DB_NAME: "java_app_db"
 +
      DB_USER: "java_app_user"
 +
      DB_PASS: "java_app_password"
 +
    volumes:
 +
      - /tmp/.X11-unix:/tmp/.X11-unix
 +
    networks:
 +
      - net_c1_c2
  
а для запуска всей композы -- команду:
+
networks:
 +
  net_c1_c2:
 +
    name: net_c1_c2
 +
</pre>
  
docker-compose start
 
  
 +
В результате в рабочем каталоге должен быть файл:
  
Для развёртывания (поднятия -- up) композы выше использовалась команда:
+
docker-compose.yaml
  
docker-compose up -d
+
Для запуска композиции выполните в рабочем каталоге команду
  
 +
docker compose up -d
  
Существует обратная операция, которую условно можно назвать свёртыванием (опускания -- down) композы. Для этого может быть использована команда:
+
В результате по описанной в файле docker-compose.yaml схеме сервисов будут запущены два контейнера: с1 и с2. В том числе из контейнера с2 будет запущено графическое приложение, которое будет работать с базой данных, запущенной в контейнере с1.
  
docker-compose down
+
====Возможные проблемы и их решения====
  
Выполнение этой команды приводит к остановке и удалению всех контейнеров композы. При этом образы остаются в системе.
+
Проблема №1: не запускается графический интерфейс Java-приложения.
 +
Решение: Открыть терминал хостовой системы и выполнить в нём команду для разрешения подключения к графической системы извне (в частности -- из контейнера):
  
После операции свёртывания композы в системе остаются занятые виртуальные диски, которые резервируются для контейнеров в момент запуска композы. Для очистки этих дисков, а следовательно для увеличения свободного места на диске, можно выполнить команду:
+
xhost +
  
docker volume prune
+
Проблема №2: Java-приложение не может подключиться к базе данных.
 +
Решение: Повторно запустить контейнер c2. При первом запуске композы в контейнере c1 сервис базы данных не успевает запуститься к моменту, когда в контейнере c2 стартует Java-приложение. Поэтому приложение показывает ошибку. Когда окно приложение закрывается -- контейнер c2 прекращает свою работу, однако контейнер c1 по прежнему работает (и в нём с высокой долей вероятности уже запустилась СУБД). Поэтому повторный запуск контейнера c2 запустит Java-приложение, в котором уже не будет ошибки подключения к базе данных (конечно, при условии, что всё верно настроено).
  
Эта команда удалит все не занятые контейнерами виртуальные диски (volumes) подсистемы docker.
+
====Работа с контейнерами в контексте docker compose====
  
 +
Если мы находимся в каталоге с файлом (Это важно! Все команды этого раздела актуальны, если соблюдается простое правило -- мы стоим в каталоге с этим файлом):
  
Также посредством команды
+
docker-compose.yaml
  
docker-compose
+
то для упрощения работы с контейнерами (сервисами микросервисной архитектуры), входящими в состав композы, можно вместо команды
  
помимо остановки и запуска контейнеров можно выполнять другие действия над контенерами композы. Например, просмотр журналов (логов) и другие.
+
docker
  
 +
использовать команду
  
Изучите справочную систему команды
+
docker compose
  
docker-compose
+
В случае с нашей композой сервисы имеют названия c1 и с2, следовательно, для их остановки можно применять команды:
  
для ознакомления с другим её функционалом.
+
docker compose stop c1
  
===Самостоятельное задание===
+
или
  
====Подготовка====
+
docker compose stop c2
  
Придумать уникальный префикс для именования названий, завязанный на фамилию и инициалы обучающегося.
+
а для остановки всей композы -- команду:
  
Например, для обучающегося
+
docker compose stop
  
Иванов Иван Иванович
+
а для запуска, соответственно
  
Префикс (<prefix>) будет состоять из фамилии и инициалов
+
docker compose start c1
  
ivanov_ii
+
или
  
Тогда в приведённых ниже примерах необходимо
+
docker compose start c2
  
<prefix>
+
а для запуска всей композы -- команду:
  
заменять на
+
docker compose start
  
ivanov_ii
 
  
Например
+
Для развёртывания (поднятия -- up) композы выше использовалась команда:
  
  ivanov_ii_container_db
+
  docker compose up -d
  
  
====Выполнение задания====
+
Существует обратная операция, которую условно можно назвать свёртыванием (опускания -- down) композы. Для этого может быть использована команда:
  
Используя справку по docker, docker-compose и набор выполненных практических работ запустить тестовое Java-приложение в композиции из двух контейнеров, аналогичных контейнерам с1 и с2, описанных в практической работе №5, исходя из следующих параметров:
+
docker compose down
  
0. Сеть должна иметь имя
+
Выполнение этой команды приводит к остановке и удалению всех контейнеров композы. При этом образы остаются в системе.
  
net_<prefix>
+
После операции свёртывания композы в системе остаются занятые виртуальные диски, которые резервируются для контейнеров в момент запуска композы. Для очистки этих дисков, а следовательно для увеличения свободного места на диске, можно выполнить команду:
  
1. Контейнер с базой данных должен иметь имя
+
docker volume prune
  
<prefix>_container_db
+
Эта команда удалит все не занятые контейнерами виртуальные диски (volumes) подсистемы docker.
  
и хостовое имя
 
  
<prefix>-container-db
+
Также посредством команды
  
2. Контейнер с Java-приложением должен иметь имя
+
docker compose
  
<prefix>_container_app
+
помимо остановки и запуска контейнеров можно выполнять другие действия над контенерами композы. Например, просмотр журналов (логов) и другие.
  
и хостовое имя
 
  
<prefix>-container-app
+
Изучите справочную систему команды
  
3. База данных должна иметь название
+
docker compose
  
<prefix>_application_db
+
для ознакомления с другим её функционалом.
  
имя пользователя
+
===Самостоятельное задание===
  
<prefix>_application_user
+
====Подготовка====
  
пароль
+
Придумать уникальный префикс для именования названий, завязанный на фамилию и инициалы обучающегося.
  
<prefix>_applicationPassw0rd123
+
Например, для обучающегося
  
На основе этих данных должен быть создан файл
+
Иванов Иван Иванович
  
docker-compose.yaml
+
Префикс (<prefix>) будет состоять из фамилии и инициалов
  
а ход работы по его созданию и процедуре запуска работоспособной композы должен быть отражён в отчёте по практической работе №5
+
ivanov_ii
  
==[Практическая работа №6] Загрузка образа на hub.docker.com==
+
Тогда в приведённых ниже примерах необходимо
  
===Исходные данные===
+
<prefix>
  
У нас есть docker-образ с Java-приложением. Скорее всего он называется
+
заменять на
  
  vpupkin/java_prod
+
  ivanov_ii
  
В практических работах 1-5 изучение работы с docker и docker-compose осуществлялось исходя из идеи о том, что в будущем для выгрузки docker-образов на hub.docker.com имя образа должно обязательно содержать префикс в виде логина на портале hub.docker.com, отделённый от имени самого образа символом
+
Например
  
  /
+
  ivanov_ii_container_db
  
В общем виде имя docker-образа, пригодного для загрузки на портал hub.docker.com выглядит так:
 
  
<username>/<imagename>:<tag>
+
====Выполнение задания====
  
Например, для пользователя с логином
+
Используя справку по docker, docker-compose и набор выполненных практических работ запустить тестовое Java-приложение в композиции из двух контейнеров, аналогичных контейнерам с1 и с2, описанных в практической работе №5, исходя из следующих параметров:
  
vpupkin
+
0. Сеть должна иметь имя
  
и смысловым названием контейнера с Java-приложением:
+
net_<prefix>
  
java_prod
+
1. Контейнер с базой данных должен иметь имя
  
полное имя docker-образа будет следующим:
+
<prefix>_container_db
  
vpupkin/java_prod
+
и хостовое имя
  
Ещё более полное имя docker-образа может быть таким:
+
<prefix>-container-db
  
vpupkin/java_prod:some_tag_name
+
2. Контейнер с Java-приложением должен иметь имя
  
, где
+
<prefix>_container_app
  
some_tag_name
+
и хостовое имя
  
это любое имя тега, которое может быть придумано создателем образа.
+
<prefix>-container-app
  
Обычно, для production-образов значением тега по умолчанию является:
+
3. База данных должна иметь название
  
  latest
+
  <prefix>_application_db
  
Следовательно, если на портале hub.docker.com предполагается публиковать единственный вариант образа контейнера, то в полном имени образа будем использовать рекомендованный вариант тега. Тогда общий вид имени образа приобретёт следующий вид:
+
имя пользователя
  
  vpupkin/java_prod:latest
+
  <prefix>_application_user
  
===Изменение имени docker-образа===
+
пароль
 +
 
 +
<prefix>_applicationPassw0rd123
  
Если в процессе выполнения практических работ 1-5 у docker-образа имя осталось шаблонным (т.е. в качестве пользователя остался собирательный образ пользователя -- vpupkin), то перед публикацией образа на hub.docker.com необходимо его изменить.
+
На основе этих данных должен быть создан файл
  
Если ваш образ называется
+
docker-compose.yaml
  
vpupkin/java_prod
+
а ход работы по его созданию и процедуре запуска работоспособной композы должен быть отражён в отчёте по практической работе №5
  
, а ваш настоящий аккаунт на hub.docker.com имеет логин:
+
==[Практическая работа №6] Загрузка образа на hub.docker.com==
  
ivanov_ii
+
===Исходные данные===
  
, то прежде чем выполнять публикацию образа его необходимо переименовать. Новое имя образа может быть, например, таким:
+
У нас есть docker-образ с Java-приложением. Скорее всего он называется
  
  ivanov_ii/java_prod
+
  vpupkin/java_prod
  
В целом, не имеет значения какое название образ будет иметь справа от символа
+
В практических работах 1-5 изучение работы с docker и docker-compose осуществлялось исходя из идеи о том, что в будущем для выгрузки docker-образов на hub.docker.com имя образа должно обязательно содержать префикс в виде логина на портале hub.docker.com, отделённый от имени самого образа символом
  
 
  /
 
  /
  
Главное, не давать контейнеру названий, совпадающих с уже загруженными в hub.docker.com контейнерами под вашим именем пользователя (в данном случае -- под логином ivanov_ii).
+
В общем виде имя docker-образа, пригодного для загрузки на портал hub.docker.com выглядит так:
Строго говоря, значение тега справа от двоеточия в имени образа предназначено для того, чтобы у пользователя была возможность не придумывать новые названия для разновидностей docker-образа (при необходимости их публикации на портале), а просто тегировать эти названия.
 
  
Учитывая факт того, что в случае отсутствия имени тега (значения справа от двоеточия) у docker-образа при использовании имени образа в команде
+
<username>/<imagename>:<tag>
  
docker run ...
+
Например, для пользователя с логином
  
или при использовании имени образа в файле
+
vpupkin
  
docker-compose.yaml
+
и смысловым названием контейнера с Java-приложением:
  
инфраструктура docker подразумевает использование тега по умолчанию (latest), необходимо задать тег по умолчанию при задании имени образу перед публикацией его на портале hub.docker.com
+
java_prod
  
Изменить имя docker-образа с
+
полное имя docker-образа будет следующим:
  
 
  vpupkin/java_prod
 
  vpupkin/java_prod
  
на
+
Ещё более полное имя docker-образа может быть таким:
 +
 
 +
vpupkin/java_prod:some_tag_name
  
ivanov_ii/java_prod:latest
+
, где
  
можно командой (дополнительно уточнив в новом имени значение тега -- справа от двоеточия):
+
some_tag_name
  
docker tag vpupkin/java_prod ivanov_ii/java_prod:latest
+
это любое имя тега, которое может быть придумано создателем образа.
  
Результат переименования образа можно проверить командой:
+
Обычно, для production-образов значением тега по умолчанию является:
  
  docker images
+
  latest
  
В ответе можно наблюдать несколько образов с одинаковым IMAGE ID
+
Следовательно, если на портале hub.docker.com предполагается публиковать единственный вариант образа контейнера, то в полном имени образа будем использовать рекомендованный вариант тега. Тогда общий вид имени образа приобретёт следующий вид:
  
<pre>
+
vpupkin/java_prod:latest
REPOSITORY            TAG      IMAGE ID      CREATED        SIZE
 
ivanov_ii/java_prod  latest    82acd99eb61f  20 hours ago  1.09GB
 
vpupkin/java_prod     latest   82acd99eb61f  20 hours ago  1.09GB
 
</pre>
 
  
При необходимости, образ с предыдущим тегом (vpupkin/java_prod) можно удалить (при отсутствии контейнеров, запущенных на его базе!) командой:
+
===Изменение имени docker-образа===
  
docker rmi vpupkin/java_prod
+
Если в процессе выполнения практических работ 1-5 у docker-образа имя осталось шаблонным (т.е. в качестве пользователя остался собирательный образ пользователя -- vpupkin), то перед публикацией образа на hub.docker.com необходимо его изменить.
  
===Решаемая задача===
+
Если ваш образ называется
  
Опубликовать подготовленный docker-образ, имеющий имя
+
vpupkin/java_prod
  
ivanov_ii/java_prod:latest
+
, а ваш настоящий аккаунт на hub.docker.com имеет логин:
  
на hub.docker.com
+
ivanov_ii
  
Для этого необходимо иметь логин и пароль от учётной записи на портале hub.docker.com
+
, то прежде чем выполнять публикацию образа его необходимо переименовать. Новое имя образа может быть, например, таким:
  
===Публикация docker-образа===
+
ivanov_ii/java_prod
  
Выполните аутентификацию на портале. Для этого в терминале (где обычно запускаете команды docker... и другие) выполните команду:
+
В целом, не имеет значения какое название образ будет иметь справа от символа
  
  docker login
+
  /
  
В ответ будет выведен текстовый диалог, в котором необходимо ввести логин и пароль. В случае корректного ввода логина и пароля в конце диалога будет выведено сообщение
+
Главное, не давать контейнеру названий, совпадающих с уже загруженными в hub.docker.com контейнерами под вашим именем пользователя (в данном случае -- под логином ivanov_ii).
 +
Строго говоря, значение тега справа от двоеточия в имени образа предназначено для того, чтобы у пользователя была возможность не придумывать новые названия для разновидностей docker-образа (при необходимости их публикации на портале), а просто тегировать эти названия.
  
Login Succeeded
+
Учитывая факт того, что в случае отсутствия имени тега (значения справа от двоеточия) у docker-образа при использовании имени образа в команде
  
Полный текст диалога должен быть похож на этот:
+
docker run ...
  
<pre>
+
или при использовании имени образа в файле
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
 
Username: ivanov_ii
 
Password:
 
WARNING! Your password will be stored unencrypted in /home/student/.docker/config.json.
 
Configure a credential helper to remove this warning. See
 
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
 
  
Login Succeeded
+
docker-compose.yaml
</pre>
 
  
 +
инфраструктура docker подразумевает использование тега по умолчанию (latest), необходимо задать тег по умолчанию при задании имени образу перед публикацией его на портале hub.docker.com
  
После успешного логина для публикации образа выполните команду
+
Изменить имя docker-образа с
  
  docker push ivanov_ii/java_prod:latest
+
  vpupkin/java_prod
  
Процедура публикации будет похожа на эту:
+
на
  
<pre>
+
ivanov_ii/java_prod:latest
The push refers to repository [docker.io/ivanov_ii/java_prod]
+
 
e1640cc719ff: Pushed
+
можно командой (дополнительно уточнив в новом имени значение тега -- справа от двоеточия):
6fb986383f38: Pushed
 
fbf95f9f9b64: Pushed
 
9e9e19c988d7: Pushed
 
fa67c5190d97: Pushed
 
2b1db325894b: Pushed
 
60bdc4ff8a54: Mounted from library/alt
 
9a03b2bc42d8: Mounted from library/alt
 
latest: digest: sha256:e75a567439afb64a9d3b5b119650e91775e7eb1d9345f5171fefba0cfe18aea3 size: 1990
 
</pre>
 
  
После завершения процедуры публикации можно проверить наличие образа на портале https://hub.docker.com в личном кабинете, загрузив страницу в браузере выполнив вход в систему.
+
docker tag vpupkin/java_prod ivanov_ii/java_prod:latest
  
==Оптимизации==
+
Результат переименования образа можно проверить командой:
  
===Оптимизация для контейнера в практической работе №2===
+
docker images
  
Для сборки приложения можно использовать компилятор Java, доступный в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:
+
В ответе можно наблюдать несколько образов с одинаковым IMAGE ID
  
 
<pre>
 
<pre>
FROM alt:p10
+
REPOSITORY            TAG      IMAGE ID      CREATED        SIZE
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
+
ivanov_ii/java_prod  latest    82acd99eb61f  20 hours ago  1.09GB
RUN apt-get update -q -y \
+
vpupkin/java_prod     latest    82acd99eb61f  20 hours ago  1.09GB
     && apt-get dist-upgrade -q -y \
 
    && apt-get install java-11-openjdk-devel nano git java-11-openjdk libGL libgtk+3 libXxf86vm xorg-dri-swrast fonts-ttf-dejavu -q -y
 
 
</pre>
 
</pre>
  
Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством)
+
При необходимости, образ с предыдущим тегом (vpupkin/java_prod) можно удалить (при отсутствии контейнеров, запущенных на его базе!) командой:
  
затем на этапе клонирования проекта командой
+
docker rmi vpupkin/java_prod
  
git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter
+
===Решаемая задача===
  
нужно сменить ветку для использования кода, адаптированного под платформу Java-11 (вместо Java-19 по умолчанию)
+
Опубликовать подготовленный docker-образ, имеющий имя
  
  git checkout jdk11
+
  ivanov_ii/java_prod:latest
  
 +
на hub.docker.com
  
Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере
+
Для этого необходимо иметь логин и пароль от учётной записи на портале hub.docker.com
Недостатки: более низкая версия платформы Java (11)
 
  
Также следует обратить внимание на то, что сборка контейнера производится на другом образе операционной системы (alt:p10) -- официальный образ производителя -- и набор устанавливаемых пакетов отличается от оригинального набора, описанного в практической работе №3.
+
===Публикация docker-образа===
  
В остальном порядок выполнения практической работы не отличается от практической работы №3.
+
Выполните аутентификацию на портале. Для этого в терминале (где обычно запускаете команды docker... и другие) выполните команду:
  
Следует обратить внимание, что в операционной системе Alt для получения компилятора javac нужно установить пакет
+
docker login
  
java-11-openjdk-devel
+
В ответ будет выведен текстовый диалог, в котором необходимо ввести логин и пароль. В случае корректного ввода логина и пароля в конце диалога будет выведено сообщение
  
, что и сделано в соответствюущей RUN-команде в Dockerfile. Также для целей сборки приложения установлены утилиты git и nano.
+
Login Succeeded
 +
 
 +
Полный текст диалога должен быть похож на этот:
 +
 
 +
<pre>
 +
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
 +
Username: ivanov_ii
 +
Password:
 +
WARNING! Your password will be stored unencrypted in /home/student/.docker/config.json.
 +
Configure a credential helper to remove this warning. See
 +
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
  
Пакеты
+
Login Succeeded
 +
</pre>
  
java-11-openjdk-devel nano git
 
  
не нужны в образе для контейнера практической работы №3, следовательно на этапе выполнения практической работы №3 их нужно убрать из команды в Dockerfile
+
После успешного логина для публикации образа выполните команду
  
===Оптимизация для контейнера в практической работе №3===
+
docker push ivanov_ii/java_prod:latest
  
Для сборки образа с готовым приложением можно использовать Runtime-платформу Java (JRE), доступную в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:
+
Процедура публикации будет похожа на эту:
  
 
<pre>
 
<pre>
FROM alt:p10
+
The push refers to repository [docker.io/ivanov_ii/java_prod]
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
+
e1640cc719ff: Pushed
RUN apt-get update -q -y \
+
6fb986383f38: Pushed
    && apt-get dist-upgrade -q -y \
+
fbf95f9f9b64: Pushed
    && apt-get install java-11-openjdk libGL libgtk+3 libXxf86vm xorg-dri-swrast fonts-ttf-dejavu -q -y \
+
9e9e19c988d7: Pushed
    && apt-get autoclean \
+
fa67c5190d97: Pushed
    && apt-get autoremove \
+
2b1db325894b: Pushed
    && /bin/rm /var/cache/apt/archives/*.rpm
+
60bdc4ff8a54: Mounted from library/alt
 +
9a03b2bc42d8: Mounted from library/alt
 +
latest: digest: sha256:e75a567439afb64a9d3b5b119650e91775e7eb1d9345f5171fefba0cfe18aea3 size: 1990
 +
</pre>
  
RUN adduser app
+
После завершения процедуры публикации можно проверить наличие образа на портале https://hub.docker.com в личном кабинете, загрузив страницу в браузере выполнив вход в систему.
  
RUN mkdir /opt/app
+
==Загрузка образов Docker из архивного файла==
COPY app /opt/app
 
COPY startup.sh /
 
RUN chmod +x /startup.sh
 
  
USER app
+
Скачать архивный файл
  
CMD /startup.sh
+
wget https://wiki.nntc.nnov.ru/download/images.tar.xz
</pre>
 
  
Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством. При чём -- только JRE, т.е. без компилятора javac. Компилятор для работы приложения -- не нужен).
+
Распаковать и загрузить образы в docker
  
Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере
+
unxz -c images.tar.xz | docker load
Недостатки: более низкая версия платформы Java (11)
 
  
Также следует обратить внимание на то, что сборка контейнера производится на другом образе операционной системы (alt:p10) -- официальный образ производителя -- и набор устанавливаемых пакетов отличается от оригинального набора, описанного в практической работе №3.
+
==Оптимизации==
 +
 
 +
===Оптимизация для контейнера в практической работе №2===
  
В остальном порядок выполнения практической работы не отличается от практической работы №3.
+
Для сборки приложения можно использовать компилятор Java, доступный в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:
  
===Оптимизация композиции контейнеров в практической работе №5===
+
<pre>
 +
FROM alt:p10
 +
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 +
RUN apt-get update -q -y \
 +
    && apt-get dist-upgrade -q -y \
 +
    && apt-get install java-11-openjdk-devel nano git java-11-openjdk libGL libgtk+3 libXxf86vm xorg-dri-swrast fonts-ttf-dejavu -q -y
 +
</pre>
  
Для добавления к композе контейнера с веб-приложением phpmyadmin необходимо расширить набор сервисов в файле
+
Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством)
  
docker-compose.yaml
+
затем на этапе клонирования проекта командой
  
следующим образом
+
git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter
  
<pre>
+
нужно сменить ветку для использования кода, адаптированного под платформу Java-11 (вместо Java-19 по умолчанию)
version: '3.9'
 
  
services:
+
git checkout jdk11
  c1:
+
 
    container_name: "c1"
+
 
    hostname: "c1"
+
Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере
    image: "mariadb"
+
Недостатки: более низкая версия платформы Java (11)
    restart: "always"
+
 
    environment:
+
Также следует обратить внимание на то, что сборка контейнера производится на другом образе операционной системы (alt:p10) -- официальный образ производителя -- и набор устанавливаемых пакетов отличается от оригинального набора, описанного в практической работе №3.
      MARIADB_ROOT_PASSWORD: "123321"
+
 
      MARIADB_DATABASE: "java_app_db"
+
В остальном порядок выполнения практической работы не отличается от практической работы №3.
      MARIADB_USER: "java_app_user"
 
      MARIADB_PASSWORD: "java_app_password"
 
    networks:
 
      - net_c1_c2
 
  
  c2:
+
Следует обратить внимание, что в операционной системе Alt для получения компилятора javac нужно установить пакет
    container_name: "c2"
+
 
    hostname: "c2"
+
java-11-openjdk-devel
    image: "vpupkin/java_prod"
 
    restart: "no"
 
    environment:
 
      DISPLAY: "$DISPLAY"
 
      DB_HOST: "c1"
 
      DB_PORT: "3306"
 
      DB_NAME: "java_app_db"
 
      DB_USER: "java_app_user"
 
      DB_PASS: "java_app_password"
 
    volumes:
 
      - /tmp/.X11-unix:/tmp/.X11-unix
 
    networks:
 
      - net_c1_c2
 
  
  c3:
+
, что и сделано в соответствюущей RUN-команде в Dockerfile. Также для целей сборки приложения установлены утилиты git и nano.
    container_name: "c3"
 
    hostname: "c3"
 
    image: phpmyadmin
 
    restart: always
 
    ports:
 
      - 8080:80
 
    environment:
 
      - PMA_ARBITRARY=1
 
    networks:
 
      - net_c1_c2
 
  
 +
Пакеты
  
networks:
+
java-11-openjdk-devel nano git
  net_c1_c2:
 
    name: net_c1_c2
 
  
</pre>
+
не нужны в образе для контейнера практической работы №3, следовательно на этапе выполнения практической работы №3 их нужно убрать из команды в Dockerfile
  
 +
===Оптимизация для контейнера в практической работе №3===
  
Относительно конфигурации, представленной в практической работе №5, был добавлен сервис c3:
+
Для сборки образа с готовым приложением можно использовать Runtime-платформу Java (JRE), доступную в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:
  
 +
<pre>
 +
FROM alt:p10
 +
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 +
RUN apt-get update -q -y \
 +
    && apt-get dist-upgrade -q -y \
 +
    && apt-get install java-11-openjdk libGL libgtk+3 libXxf86vm xorg-dri-swrast fonts-ttf-dejavu -q -y \
 +
    && apt-get autoclean \
 +
    && apt-get autoremove \
 +
    && /bin/rm /var/cache/apt/archives/*.rpm
  
<pre>
+
RUN adduser app
  c3:
+
 
    container_name: "c3"
+
RUN mkdir /opt/app
    hostname: "c3"
+
COPY app /opt/app
    image: phpmyadmin
+
COPY startup.sh /
    restart: always
+
RUN chmod +x /startup.sh
    ports:
+
 
      - 8080:80
+
USER app
    environment:
+
 
      - PMA_ARBITRARY=1
+
CMD /startup.sh
    networks:
 
      - net_c1_c2
 
 
</pre>
 
</pre>
  
который был подключен к той же сети, что и остальные контейнеры.
+
Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством. При чём -- только JRE, т.е. без компилятора javac. Компилятор для работы приложения -- не нужен).
 +
 
 +
Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере
 +
Недостатки: более низкая версия платформы Java (11)
 +
 
 +
Также следует обратить внимание на то, что сборка контейнера производится на другом образе операционной системы (alt:p10) -- официальный образ производителя -- и набор устанавливаемых пакетов отличается от оригинального набора, описанного в практической работе №3.
 +
 
 +
В остальном порядок выполнения практической работы не отличается от практической работы №3.
  
У сервиса c3 экспортирован 80-й порт, на котором работает веб-приложение, на порт 8080 хостовой системы.
+
===Оптимизация композиции контейнеров в практической работе №5===
  
Следовательно, веб-приложение phpmyadmin можен быть запущена в браузере хостовой машины по адресу
+
Для добавления к композе контейнера с веб-приложением phpmyadmin необходимо расширить набор сервисов в файле
 +
 
 +
docker-compose.yaml
 +
 
 +
следующим образом
 +
 
 +
<pre>
 +
version: '3.9'
 +
 
 +
services:
 +
  c1:
 +
    container_name: "c1"
 +
    hostname: "c1"
 +
    image: "mariadb"
 +
    restart: "always"
 +
    environment:
 +
      MARIADB_ROOT_PASSWORD: "123321"
 +
      MARIADB_DATABASE: "java_app_db"
 +
      MARIADB_USER: "java_app_user"
 +
      MARIADB_PASSWORD: "java_app_password"
 +
    networks:
 +
      - net_c1_c2
 +
 
 +
  c2:
 +
    container_name: "c2"
 +
    hostname: "c2"
 +
    image: "vpupkin/java_prod"
 +
    restart: "no"
 +
    environment:
 +
      DISPLAY: "$DISPLAY"
 +
      DB_HOST: "c1"
 +
      DB_PORT: "3306"
 +
      DB_NAME: "java_app_db"
 +
      DB_USER: "java_app_user"
 +
      DB_PASS: "java_app_password"
 +
    volumes:
 +
      - /tmp/.X11-unix:/tmp/.X11-unix
 +
    networks:
 +
      - net_c1_c2
 +
 
 +
  c3:
 +
    container_name: "c3"
 +
    hostname: "c3"
 +
    image: phpmyadmin
 +
    restart: always
 +
    ports:
 +
      - 8080:80
 +
    environment:
 +
      - PMA_ARBITRARY=1
 +
    networks:
 +
      - net_c1_c2
 +
 
 +
 
 +
networks:
 +
  net_c1_c2:
 +
    name: net_c1_c2
 +
 
 +
</pre>
 +
 
 +
 
 +
Относительно конфигурации, представленной в практической работе №5, был добавлен сервис c3:
 +
 
 +
 
 +
<pre>
 +
  c3:
 +
    container_name: "c3"
 +
    hostname: "c3"
 +
    image: phpmyadmin
 +
    restart: always
 +
    ports:
 +
      - 8080:80
 +
    environment:
 +
      - PMA_ARBITRARY=1
 +
    networks:
 +
      - net_c1_c2
 +
</pre>
 +
 
 +
который был подключен к той же сети, что и остальные контейнеры.
 +
 
 +
У сервиса c3 экспортирован 80-й порт, на котором работает веб-приложение, на порт 8080 хостовой системы.
 +
 
 +
Следовательно, веб-приложение phpmyadmin можен быть запущена в браузере хостовой машины по адресу
  
 
  http://localhost:8080
 
  http://localhost:8080
  
Для подключения необходимо использовать следующие данные:
+
Для подключения необходимо использовать следующие данные:
 
+
 
  Сервер: c1
+
  Сервер: c1
  Пользователь: root или java_app_user
+
  Пользователь: root или java_app_user
  Пароль: 123321 или java_app_password
+
  Пароль: 123321 или java_app_password
 
+
 
Почему так? Смотрите внимательно в файл
+
Почему так? Смотрите внимательно в файл
 
+
 
  docker-compose.yaml
+
  docker-compose.yaml
 
+
 
===Работа docker через прокси-сервер===
+
===Оптимизация №6 (запуск графического приложения в Docker под Windows)===
 
+
 
отредактировать файл
+
1. Установить VcXsrv Windows X Server: https://sourceforge.net/projects/vcxsrv/
 
+
 
  ~/.docker/config.json
+
2. Запустить приложение в режиме "Multiple windows", Display Number = 0, Start no client, поставить галочку "Disable Access Control"
 
+
 
привести его к следующему виду:
+
3. Приложение будет запущено в трее.
 
+
 
<pre>
+
Команда для запуска приложения (на примере Практической работы №2)
{
+
 
"auths": {
+
docker run --rm -it -e DISPLAY=<здесь ip адрес вашей windows-машины>:0 --mount source=C:\Users\student\pr02\src,target=/root/src,type=bind --name=java_test --hostname=java-test vpupkin/java_dev /bin/bash
"https://index.docker.io/v1/": {
+
 
"auth": "ЗДЕСЬ_БУДЕТ_TOKEN_ОТ_HUB.DOCKER.COM_У_КАЖДОГО_--СВОЙ"
+
==Примеры==
}
+
 
},
+
===Lazarus приложение===
"proxies": {
+
 
"default": {
+
https://hub.docker.com/r/vslugin/lazarus_prod
"httpProxy": "http://10.0.52.52:3128",
+
 
"httpsProxy": "http://10.0.52.52:3128",
+
docker pull vslugin/lazarus_prod:latest
"noProxy": "127.0.0.0/8"
+
  docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --name=lazarus_prod --hostname=lazarus-prod vslugin/lazarus_prod
}
+
 
}
+
Пример запуска контейнера
}
+
 
 +
docker start lazarus_prod
 +
 
 +
===Java приложение с базой данных (два контейнера)===
 +
 
 +
https://hub.docker.com/r/vslugin/java_prod
 +
 
 +
====Развёртывание и запуск вручную====
 +
 
 +
=====Команда для разрешения подключения к X-серверу=====
 +
 
 +
На докер-хосте под пользователем, под которым планируется запускать приложение из контейнера, выполнить команду:
 +
 
 +
xhost +
 +
 
 +
=====Команда для ручного развёртывания=====
 +
 
 +
docker network create net_c1_c2;docker run --name=c1 --hostname=c1 -e MARIADB_ROOT_PASSWORD=123321 -e MARIADB_DATABASE=java_app_db -e MARIADB_USER=java_app_user -e MARIADB_PASSWORD=java_app_password --network net_c1_c2 -d mariadb;sleep 5s;docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --name=c2 --hostname=c2 -e DB_HOST=c1 -e DB_PORT=3306 -e DB_NAME=java_app_db -e DB_USER=java_app_user -e DB_PASS=java_app_password --network net_c1_c2 vslugin/java_prod:latest
 +
 
 +
=====Команда запуска приложения=====
 +
 
 +
`docker start c2`
 +
 
 +
====Развёртывание и запуск в docker-compose====
 +
 
 +
=====Развёртывание=====
 +
 
 +
Просто бросьте это в консоль:
 +
<pre>
 +
cd
 +
mkdir compose_c1_c2
 +
cd compose_c1_c2
 +
cat << EOF > docker-compose.yaml
 +
version: '3.9'
 +
 
 +
services:
 +
  c1:
 +
    container_name: "c1"
 +
    hostname: "c1"
 +
    image: "mariadb"
 +
    restart: "always"
 +
    environment:
 +
      MARIADB_ROOT_PASSWORD: "123321"
 +
      MARIADB_DATABASE: "java_app_db"
 +
      MARIADB_USER: "java_app_user"
 +
      MARIADB_PASSWORD: "java_app_password"
 +
    networks:
 +
      - net_c1_c2
 +
 
 +
  c2:
 +
    container_name: "c2"
 +
    hostname: "c2"
 +
    image: "vslugin/java_prod:latest"
 +
    restart: "no"
 +
    environment:
 +
      DISPLAY: "$DISPLAY"
 +
      DB_HOST: "c1"
 +
      DB_PORT: "3306"
 +
      DB_NAME: "java_app_db"
 +
      DB_USER: "java_app_user"
 +
      DB_PASS: "java_app_password"
 +
    volumes:
 +
      - /tmp/.X11-unix:/tmp/.X11-unix
 +
    networks:
 +
      - net_c1_c2
 +
 
 +
networks:
 +
  net_c1_c2:
 +
    name: net_c1_c2
 +
EOF
 +
 
 +
docker-compose up -d
 
</pre>
 
</pre>
  
===Лайвхаки===
+
==== Команда запуска ====
 
 
Настроить доступ к registry-1.docker.io через статический маршрут
 
 
 
su -
 
 
 
echo '44.205.64.79 registry-1.docker.io' >> /etc/hosts
 
 
 
ip ro add 44.205.64.79 via 192.168.66.66
 
 
 
 
 
Переключить основной шлюз
 
 
 
su -
 
 
 
ip ro del default
 
 
 
ip ro add default via 10.207.151.253
 
  
  echo 'nameserver 8.8.8.8' > /etc/resolv.conf
+
  docker start c2

Текущая версия на 09:25, 28 января 2025

Содержание

DOCKER_IN_ESPD

Прокси сервер

В ЕСПД каждой организации существует адрес прокси-сервера для доступа в централизованно-ограниченный провайдером интернет.

Например, это может быть адрес и порт:

10.0.52.52:3128

Настройка сервиса для работы с прокси-сервером в ОС Альт

Для настройки сервиса docker в ОС Альт на доступ к образам с

hub.docker.com

необходимо:

Импортировать сертификат (подробнее об этом здесь здесь):

Переходим в каталог

cd /etc/pki/ca-trust/source/anchors/

Скачиваем сертификат

wget --no-check-certificate https://espd.rt.ru/docs/ca-root.crt

Приминяем

update-ca-trust

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

HTTP_PROXY

и

HTTPS_PROXY

Для этого необходимо отредактировать файл

/etc/sysconfig/docker

Было:

cat /etc/sysconfig/docker
OPTIONS=""

Стало:

cat /etc/sysconfig/docker
HTTP_PROXY=http://10.0.52.52:3128
HTTPS_PROXY=http://10.0.52.52:3128
OPTIONS=""

Важно! Адрес и порт прокси сервера могут быть другими!

Затем необходимо перезапустить сервис

systemctl restart docker

Теперь можно пробовать получить образ

docker pull alt:p10

В случае успешной настройки в ответ должно быть что-то вроде этого

p10: Pulling from library/alt
8d0b964d5817: Pulling fs layer 
529c2ffbf4d6: Download complete 
8d0b964d5817: Pull complete 
529c2ffbf4d6: Pull complete 
Digest: sha256:1a4f3803dee404126c6947ea9f791eb781e25b541477dc242ef188e4e7734bef
Status: Downloaded newer image for alt:p10
docker.io/library/alt:p10

Лабораторные работы по Docker

Подготовка рабочего места

Для выполнения всех работ достаточно установить в виртуальную машину ОС Альт Рабочая Станция 10.

Ссылка на загрузку установочного образа: https://download.basealt.ru/pub/distributions/ALTLinux/p10/images/workstation/x86_64/alt-workstation-10.0-x86_64.iso

После установки нужно обновить систему

su -
apt-get update
apt-get dist-upgrade
update-kernel -f

открыть терминал и установить Docker командой

apt-get install docker-engine docker-compose-v2

Затем добавить текущего пользователя в группу docker командой

usermod -a -Gdocker student

затем включить сервис и поставить его в автозагрузку

systemctl start docker
systemctl enable docker

перезагрузиться

reboot

[Практическая работа №1] Создание простого контейнера

Вручную

Откройте терминал хостовой машины

На базе официального стандартного Docker-образа

alt:p10

Только получить образ на компьютер можно командой:

docker pull alt:p10

создайте и запустите Docker-контейнер:

docker run -it --name=my_first_container --hostname=my-first-container alt:p10 /bin/bash


В случае успешного создания Docker-контейнера в эмуляторе терминала приглашение должно смениться на такое:

root@my-first-container:/#

Внимание! Сейчас вы внутри Docker-контейнера и можете командовать им! Если скомандовать

exit

, то контейнер завершит свою работу и найти и запустить его можно таким образом:

Найти:

docker ps -a

в ответе среди возможных прочих контейнеров должен быть такой:

f0a3cc6a8b63        altlinux/base:p10                 "/bin/bash"              15 seconds ago      Exited (0) 5 seconds ago                                my_first_container

Имя его в данном случае:

my_first_container

Идентификатор его в данном случае:

f0a3cc6a8b63

Запустить:

docker start my_first_container

или:

docker start f0a3cc6a8b63

Естественно, в конкретном случае идентификатор будет другой.


Подключиться к терминалу Docker-контейнера:

docker attach my_first_container

или

docker attach f0a3cc6a8b63


Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать

exit

, то контейнер завершит свою работу придётся опять читать выше по тексту как его запускать...


Однако есть способ отключиться от терминала и не завершить Docker-контейнер:

Для этого нужно последовательно нажать сочетания клавиш:

Ctrl + P

затем

Ctrl + Q


После этого приглашение командной строки контейнера должно заменить приглашение хостовой системы.


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

Для создания собственного образа вручную необходимо внести изменения внутри нашего контейнера, а затем выполнить операцию по "превращению" нашего контейнера в образ.

Задача

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

Ход работы

Запустите контейнер my_first_container и подключитесь к его терминалу (как это сделать - описано выше)

Установите внутри контейнера текстовый редактор

apt-get update
apt-get install nano

Создайте с помощью установленного редактора nano файл сценария

bootstrap.sh

со следующим содержимым:

#!/bin/bash
echo "Hello, $USER_NAME"

Сделайте файл исполняемым

chmod +x /bootstrap.sh

Проверьте работоспособность командой:

USER_NAME=Ivan /bootstrap.sh

в результате в терминал должна быть выдана строка

Hello, Ivan

Завершите контейнер, выйдя из него:

exit

Создайте новый образ на базе изменённого контейнера командой:

docker commit -a Vasya -m "My first own image" my_first_container my_first_image

Образ будет доступен в списке образов

docker images

Выполните запуск контейнера с автоматическим удалением его после завершения, передавая в команду запуска различные значения переменной окружения

USER_NAME

Примеры команды:

docker run --rm -e USER_NAME=Ivan my_first_image /bootstrap.sh
docker run --rm -e USER_NAME=Maria my_first_image /bootstrap.sh
docker run --rm -e USER_NAME=Petr my_first_image /bootstrap.sh
docker run --rm -e USER_NAME=Ekaterina my_first_image /bootstrap.sh

Автоматически (посредством файла Dockerfile)

Откройте терминал хостовой машины и создайте рабочий каталог

mkdir pr01

Перейдите в рабочий каталог

cd pr01

Создание файлов

В рабочем каталоге создайте файл

Dockerfile

по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):

FROM alt:p10
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
RUN echo '#!/bin/bash' > /bootstrap.sh
RUN echo 'echo "Hello, $USER_NAME"' >> /bootstrap.sh
RUN chmod +x /bootstrap.sh
CMD /bootstrap.sh


В конце этого этапа в рабочем каталоге должен быть один файл:

Dockerfile

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

Для создания Docker-образа (image) выполните команду:

docker build -t 'my_second_image:latest' .

Для проверки существования созданного контейнера выполните команду:

docker images

Среди текста ответа должна появиться строчка с новым контейнером:

my_second_image        latest              add5d00c3dc0        7 seconds ago       72.9MB

Запуск контейнера на базе образа

Запуск контейнеров на базе созданного образа (за исключением имени образа и отсутствием необходимости указывать исполняемый скрипт (он указан непосредственно в Dockerfile)) ни чем не будет отличаться от запуска контейнеров в ходе создания образа вручную:

docker run --rm -e USER_NAME=Ivan my_second_image
docker run --rm -e USER_NAME=Maria my_second_image
docker run --rm -e USER_NAME=Petr my_second_image
docker run --rm -e USER_NAME=Ekaterina my_second_image

[Практическая работа №2] Создание контейнера для разработки приложения на языке Java

Откройте терминал хостовой машины и создайте рабочий каталог

mkdir pr02

Перейдите в рабочий каталог

cd pr02

Создание файлов

Скачайте в рабочий каталог JDK версии 19.0.1. Это можно сделать командой (рекомендуется использовать в локальной сети колледжа)

wget https://wiki.nntc.nnov.ru/download/openjdk-19.0.1_linux-x64_bin.tar.gz

или командой (при работе вне локальной сети колледжа)

wget https://download.java.net/java/GA/jdk19.0.1/afdd2e245b014143b62ccb916125e3ce/10/GPL/openjdk-19.0.1_linux-x64_bin.tar.gz

Распакуйте загруженный файл командой

tar -xzpf openjdk-19.0.1_linux-x64_bin.tar.gz

В результате будет доступен каталог

jdk-19.0.1

На этом этапе архив можно удалить командой

rm openjdk-19.0.1_linux-x64_bin.tar.gz

В рабочем каталоге создайте файл

Dockerfile_dev

по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):

FROM alt:p10
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
RUN apt-get update -q -y && apt-get install nano git libX11 libX11-devel libXxf86vm libXxf86vm-devel libGL xorg-dri-swrast fonts-ttf-dejavu mate-calc -q -y
RUN mkdir /opt/jdk-19.0.1
COPY jdk-19.0.1 /opt/jdk-19.0.1
RUN echo PATH="$PATH:/opt/jdk-19.0.1/bin" >> /root/.bashrc
RUN source /root/.bashrc

В конце этого этапа в рабочем каталоге должны быть файл:

Dockerfile_dev

и каталог

jdk-19.0.1

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

Далее в этом разделе будем исходить из условия, что ваш логин на https://hub.docker.com/ будет

vpupkin

а пароль

ну, вы сами знаете...


! Также стоит помнить, что в эмуляторе терминала находиться нужно в рабочем каталоге !


Для создания Docker-образа (image) выполните команду:

docker build -t 'vpupkin/java_dev:latest' -f Dockerfile_dev .


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

docker images

Среди текста ответа должна появиться строчка с новым образом:

vpupkin/java_dev   latest              fa1a63896356        9 seconds ago       2.42GB


Запуск контейнера на базе образа

mkdir /home/student/pr02/src

На базе полученного образа запустите контейнер, пробросив внутрь контейнера локальный каталог хостовой машины:

docker run -it --mount source=/home/student/pr02/src,target=/root/src,type=bind --name=java_dev --hostname=java-dev vpupkin/java_dev /bin/bash

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

В случае успешного создания контейнера в эмуляторе терминала приглашение должно смениться на такое:

root@java-dev:/#

Проверка версии Java RE и компилятора должны возвращать примерно следующее:

root@java-dev:/# java -version
openjdk version "19.0.1" 2022-10-18
OpenJDK Runtime Environment (build 19.0.1+10-21)
OpenJDK 64-Bit Server VM (build 19.0.1+10-21, mixed mode, sharing)
bash-4.4# 
bash-4.4# javac -version
javac 19.0.1

Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать

exit

, то контейнер завершит свою работу и найти и запустить его можно таким образом:

Найти:

docker ps -a

в ответе среди возможных прочих контейнеров должен быть такой:

8e5f4fd0a99b        vpupkin/java_dev   "/bin/bash"         3 minutes ago       Exited (0) 6 seconds ago                       java_dev

Имя его в данном случае:

java_dev

Идентификатор его в данном случае:

8e5f4fd0a99b

Остальное пока не важно, однако можно догадаться за что отвечают остальные параметры...


Запустить:

docker start java_dev

или:

docker start 8e5f4fd0a99b

Естественно, в конкретном случае идентификатор будет другой.


Подключиться к терминалу:

docker attach java_dev

или

docker attach 8e5f4fd0a99b


Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать

exit

, то контейнер завершит свою работу придётся опять читать выше по тексту как его запускать...


Однако есть способ отключиться от терминала и не завершить контейнер:

Для этого нужно последовательно нажать сочетания клавиш:

Ctrl + P

затем

Ctrl + Q


После этого приглашение командной строки контейнера должно заменить приглашение хостовой системы.


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

Сборка приложения на языке Java в docker-контейнере

Перейдём в каталог

cd /root/src/

Склонируем проект приложения на Java

git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter

Перейдём в проект

cd simple-counter

Исходя из рекомендаци в файле README.md выполним сборку проекта

bash mvnw install
bash mvnw dependency:copy-dependencies

В случае успешной сборки в терминале котейнера долждно быть написано что-то похожее на это:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

На этом этам сборки приложения заврешён.

Теперь наша задача - запустить приложение прямо на хостовой машине (но выполняться оно будет в контейнере).

Запуск собранного приложения в docker-контейнере на базе образа с JDK

Запустим новый контейнер командой:

docker run --rm -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --mount source=/home/student/pr02/src,target=/root/src,type=bind --name=java_test --hostname=java-test vpupkin/java_dev /bin/bash

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

Первая: установлена (внутрь контейнера) переменная окружения

DISPLAY

равная значению аналогичной переменной окружения хостовой системы.

Вторая: проброшено устройство

/tmp/.X11-unix

из хостовой системы в контейнер.

Также добавлено монтирование каталога src для обмена файлами межу контейнером и хостовой системой, а также добавлена опция

--rm

которая уничтожает контейнер после его завершения (за данные мы не переживаем, они же лежат локально в каталоге src, который каждый раз монтируется при старте в новый контейнер).


Эта опция сюда добавлена, поскольку сама команда старта контейнера содержит в себе цель запускать именно оболочку /bin/bash для ручного тестирования запуска собранного приложения.

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


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

Важный момент: В некоторых операционных системах может потребоваться выполнить команду

xhost +

для разрешения подключения контейнера к графической оболочке X-сервера.

Тестовый запуск приложения можно выполнить командами:

cd /root/src/simple-counter/
java --module-path=target/dependency/ --add-modules javafx.controls,javafx.fxml -cp target/demo_up04-1.0-SNAPSHOT.jar com.example.demo_up04.DemoApplication

Отвечаем на главный вопрос?

Вопрос звучит так:

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


Не нужны по нескольким причинам:

  1. Исходный код чаще всего остаётся интеллектуальной собственностью компании-разработчика и не должен оказаться у заказчика;
  2. Наличие на Production-системе компилятора какого-либо языка и/или каких-либо средств разработки является потенциальной уязвимостью системы;
  3. Инструменты сборки и тестирования никогда не понадобятся конечному пользователю на Production-системе, но всегда будут занимать место на файловой системе контейнера.

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

Как это сделать -- см. в следующей практической работе.

[Практическая работа №3] Создание контейнера для запуска Java-приложения

Откройте терминал хостовой машины. Создайте рабочий каталог

mkdir pr03

Перейдите в рабочий каталог

cd pr03

Создание файлов

В рабочем каталоге создайте файл

Dockerfile_prod

по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):

FROM alt:p10
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
RUN apt-get update -q -y \
    && apt-get install nano su libX11 libX11-devel libXxf86vm libXxf86vm-devel libGL xorg-dri-swrast fonts-ttf-dejavu mate-calc -q -y \
    && apt-get autoclean \
    && apt-get autoremove

RUN adduser app

RUN mkdir /opt/jdk-19.0.1
COPY jdk-19.0.1 /opt/jdk-19.0.1

RUN mkdir /opt/app
COPY app /opt/app
COPY startup.sh /
RUN chmod +x /startup.sh

RUN echo "PATH=$PATH:/opt/jdk-19.0.1/bin" > /home/app/.bashrc
RUN echo "export JAVA_HOME=/opt/jdk-19.0.1" >> /home/app/.bashrc

USER app

CMD /startup.sh

Создайте каталог app в рабочем каталоге

mkdir app

Скопируйте исполняемый файл, полученный в предыдущей работе в рабочий каталог

/bin/cp -r ../pr02/src/simple-counter/target app/

Скачайте в рабочий каталог JDK версии 19.0.1. Это можно сделать командой (рекомендуется использовать в локальной сети колледжа)

wget https://wiki.nntc.nnov.ru/download/openjdk-19.0.1_linux-x64_bin.tar.gz

или командой (при работе вне локальной сети колледжа)

wget https://download.java.net/java/GA/jdk19.0.1/afdd2e245b014143b62ccb916125e3ce/10/GPL/openjdk-19.0.1_linux-x64_bin.tar.gz

Распакуйте загруженный файл командой

tar -xzpf openjdk-19.0.1_linux-x64_bin.tar.gz

На этом этапе архив можно удалить командой

rm openjdk-19.0.1_linux-x64_bin.tar.gz

Создайте в рабочем каталоге файл

startup.sh

со следующим содержимым

#!/bin/bash
source /home/app/.bashrc
cd /opt/app
java --module-path=target/dependency/ --add-modules javafx.controls,javafx.fxml -cp target/demo_up04-1.0-SNAPSHOT.jar com.example.demo_up04.DemoApplication

В конце этого этапа в рабочем каталоге должно быть два файла:

Dockerfile_prod
startup.sh

И два каталога:

jdk-19.0.1
app

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

Далее в этом разделе будем исходить из условия, что ваш логин на https://hub.docker.com/ будет

vpupkin

а пароль

ну, вы сами знаете...


! Также стоит помнить, что в эмуляторе терминала находиться нужно в рабочем каталоге !


Для создания Docker-образа (image) выполните команду:

docker build -t 'vpupkin/java_prod:latest' -f Dockerfile_prod .


Для проверки существования созданного контейнера выполните команду:

docker images

Среди текста ответа должна появиться строчка с новым контейнером:

vpupkin/java_prod   latest              20bb2900074d        16 seconds ago      217MB


! Обратите внимание на размер контейнера !
Сравните размер контейнера с размером контейнера java_dev из предыдущей работы

Запуск контейнера на базе образа

Создадим каталог для обмена данными с контейнером

mkdir $HOME/data

На базе полученного образа запустите контейнер, пробросив внутрь контейнера локальный каталог хостовой машины:

docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --mount source="$HOME/data",target=/home/app/data,type=bind --name=java_prod --hostname=java-prod vpupkin/java_prod


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

Dockerfile_prod

строчкой

CMD /bin/su -c "/startup.sh" app

Результатом запуска контейнера должно стать запущенное внутри контейнера графическое приложение с отображением графического интерфейса на хостовой машине.

При закрытии окна графического приложения контейнер будет завершён и будет доступен среди списка контейнеров

docker ps -a

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

docker start java_prod

[Практическая работа №4] Взаимодействие двух контейнеров по сети (ручной запуск)

Задача: Запустить Java-приложение в контейнере с именем c2, который взаимодействует с базой данных Mariadb, запущенной в контейнере с именем c1

Загрузка образа для контейнера с mariadb

docker pull mariadb

Создание сетевого моста

docker network create net_c1_c2

Проверить список сетевых мостов можно командой

docker network list

Запуск контейнера c1 и подготовка базы данных

Создать контейнер с базой данных Mariadb и задать исходные параметры работы СУБД (название базы данных, логин и пароль для базы данных, пароль пользователя root) через переменные окружения

docker run --name=c1 --hostname=c1 -e MARIADB_ROOT_PASSWORD=123321 -e MARIADB_DATABASE=java_app_db -e MARIADB_USER=java_app_user -e MARIADB_PASSWORD=java_app_password --network net_c1_c2 -d mariadb

Проверить корректность подключения к Mariadb с созданным пользователем к созданной базе данных (подключиться к консоли контейнера c1 и воспользоваться клиентом mariadb)

docker exec -it c1 /bin/bash

Внутри контейнера запустить клиент mariadb (ранее это был клиент mysql) с параметрами подключения к бд:

mariadb -u java_app_user -pjava_app_password -h localhost java_app_db

Выход из mariadb и затем из контейнера

exit
exit

Запуск контейнера c2 с Java-приложением

Запуск контейнера с Java-приложением производится аналогично запуску, подробно описанному в практической работе №3 с учётом ряда нюансов:

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

с2

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

с2

3. Необходимо учитывать, что для корректного подключения Java-приложения к базе данных, доступной в контейнере с именем_контейнера=именем_хоста=с1 необходимо при запуске контейнера с2 передать набор переменных окружения для настройки Java-приложения на работу с базой данных в контейнере c1

DB_HOST=c1
DB_PORT=3306
DB_NAME=java_app_db
DB_USER=java_app_user
DB_PASS=java_app_password

Пример команды для запуска контейнера c2 (запуск контейнера осуществляется на базе образа, созданного в практической работе №3)

Не забудем про

xhost +
docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --name=c2 --hostname=c2 -e DB_HOST=c1 -e DB_PORT=3306 -e DB_NAME=java_app_db -e DB_USER=java_app_user -e DB_PASS=java_app_password --network net_c1_c2 vpupkin/java_prod

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

--mount source="$HOME/data",target=/home/app/data,type=bind

В данном примере этот параметр опущен, т.к. тестовое приложение не имеет функций чтения и записи файлов.

Самостоятельное задание

Подготовка

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

Например, для обучающегося

Иванов Иван Иванович

Префикс (<prefix>) будет состоять из фамилии и инициалов

ivanov_ii

Тогда в приведённых ниже примерах необходимо

<prefix>

заменять на

ivanov_ii

Например

ivanov_ii_container_db


Выполнение задания

Используя справку по docker и набор выполненных практических работ запустить тестовое Java-приложение в двух контейнерах, аналогичных контейнерам с1 и с2, исходя из следующих параметров:

0. Сетевой мост должен иметь имя

net_<prefix>

1. Контейнер с базой данных должен иметь имя

<prefix>_container_db

и хостовое имя

<prefix>-container-db

2. Контейнер с Java-приложением должен иметь имя

<prefix>_container_app

и хостовое имя

<prefix>-container-app

3. База данных должна иметь название

<prefix>_application_db

имя пользователя

<prefix>_application_user

пароль

<prefix>_applicationPassw0rd123

Ход работы отразить в отчёте по практической работе №4

[Практическая работа №5] Взаимодействие двух контейнеров по сети (docker compose)

Предисловие

Решаемая в данной практической работе задача аналогична задаче из практической работы №4. Отличия состоят лишь в том, что в практической работе №4 запуск двух контейнеров, взаимодействующих между собой внутри изолированной сети, осуществляется вручную, путём выполнения команд:

docker run ...

Для автоматизации запуска приложений, компоненты которых разделены по контейнерам (их (приложения в контейнерах) ещё называют микросервисами) может быть использован инструмент:

docker compose

Инструмент docker compose (смысл названия можно перевести как "композиция из докер контейнеров") предназначен для того, чтобы автоматически запустить несколько docker-контейнеров в одном контексте (как правило, под контекстом подразумевается общая сеть, изолированная от хостовой системы но доступная для всех контейнеров композиции (как говорят DevOps-инженеры -- "композы")).

В практической работе №2 мы изучали два способа создания docker-образа: ручной и автоматический.

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

Автоматический способ подразумевал решение аналогичной задачи, но без участия пользователя. Т.е. пользователь один раз описывал файл (Dockerfile), который включал в себя все необходимые команды (которые в ручном режиме пользователь выполнял вручную) и директивы, которых минимально необходимо и достаточно для сборки образа в автоматическом режиме. После того, как был подготовлен Dockerfile, на его базе командой:

docker build...

производилась сборка образа


Между ручным запуском двух контейнеров, описанным в практической работе №4, и автоматическим запуском композиции из докер контейнеров (композы), описываемой в этой практической работе, можно провести такую же аналогию, как между созданием образа контейнера вручную и созданием образа контейнера автоматически. Два этих способа (ручной и автоматический) объединяет наличие специального конфигурационного файла. В случае с автоматической сборкой docker-образа это файл:

Dockerfile

, в случае же с автоматическим запуском нескольких контейнеров в композе -- это файл:

docker-compose.yaml

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

1. Сконфигурировать файл

docker-compose.yaml

2. Выполнить запуск композы командой

docker compose up ...

Практика

Создайте рабочий каталог и перейдите в него

mkdir compose_с1_с2
cd compose_с1_с2

Создайте файл

docker-compose.yaml

со следующим содержимым

version: '3.9'

services:
  c1:
    container_name: "c1"
    hostname: "c1"
    image: "mariadb"
    restart: "always"
    environment:
      MARIADB_ROOT_PASSWORD: "123321"
      MARIADB_DATABASE: "java_app_db"
      MARIADB_USER: "java_app_user"
      MARIADB_PASSWORD: "java_app_password"
    networks:
      - net_c1_c2

  c2:
    container_name: "c2"
    hostname: "c2"
    image: "vpupkin/java_prod"
    restart: "no"
    environment:
      DISPLAY: "$DISPLAY"
      DB_HOST: "c1"
      DB_PORT: "3306"
      DB_NAME: "java_app_db"
      DB_USER: "java_app_user"
      DB_PASS: "java_app_password"
    volumes:
      - /tmp/.X11-unix:/tmp/.X11-unix
    networks:
      - net_c1_c2

networks:
  net_c1_c2:
    name: net_c1_c2


В результате в рабочем каталоге должен быть файл:

docker-compose.yaml

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

docker compose up -d

В результате по описанной в файле docker-compose.yaml схеме сервисов будут запущены два контейнера: с1 и с2. В том числе из контейнера с2 будет запущено графическое приложение, которое будет работать с базой данных, запущенной в контейнере с1.

Возможные проблемы и их решения

Проблема №1: не запускается графический интерфейс Java-приложения. Решение: Открыть терминал хостовой системы и выполнить в нём команду для разрешения подключения к графической системы извне (в частности -- из контейнера):

xhost +

Проблема №2: Java-приложение не может подключиться к базе данных. Решение: Повторно запустить контейнер c2. При первом запуске композы в контейнере c1 сервис базы данных не успевает запуститься к моменту, когда в контейнере c2 стартует Java-приложение. Поэтому приложение показывает ошибку. Когда окно приложение закрывается -- контейнер c2 прекращает свою работу, однако контейнер c1 по прежнему работает (и в нём с высокой долей вероятности уже запустилась СУБД). Поэтому повторный запуск контейнера c2 запустит Java-приложение, в котором уже не будет ошибки подключения к базе данных (конечно, при условии, что всё верно настроено).

Работа с контейнерами в контексте docker compose

Если мы находимся в каталоге с файлом (Это важно! Все команды этого раздела актуальны, если соблюдается простое правило -- мы стоим в каталоге с этим файлом):

docker-compose.yaml

то для упрощения работы с контейнерами (сервисами микросервисной архитектуры), входящими в состав композы, можно вместо команды

docker

использовать команду

docker compose

В случае с нашей композой сервисы имеют названия c1 и с2, следовательно, для их остановки можно применять команды:

docker compose stop c1

или

docker compose stop c2

а для остановки всей композы -- команду:

docker compose stop

а для запуска, соответственно

docker compose start c1

или

docker compose start c2

а для запуска всей композы -- команду:

docker compose start


Для развёртывания (поднятия -- up) композы выше использовалась команда:

docker compose up -d


Существует обратная операция, которую условно можно назвать свёртыванием (опускания -- down) композы. Для этого может быть использована команда:

docker compose down

Выполнение этой команды приводит к остановке и удалению всех контейнеров композы. При этом образы остаются в системе.

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

docker volume prune

Эта команда удалит все не занятые контейнерами виртуальные диски (volumes) подсистемы docker.


Также посредством команды

docker compose

помимо остановки и запуска контейнеров можно выполнять другие действия над контенерами композы. Например, просмотр журналов (логов) и другие.


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

docker compose

для ознакомления с другим её функционалом.

Самостоятельное задание

Подготовка

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

Например, для обучающегося

Иванов Иван Иванович

Префикс (<prefix>) будет состоять из фамилии и инициалов

ivanov_ii

Тогда в приведённых ниже примерах необходимо

<prefix>

заменять на

ivanov_ii

Например

ivanov_ii_container_db


Выполнение задания

Используя справку по docker, docker-compose и набор выполненных практических работ запустить тестовое Java-приложение в композиции из двух контейнеров, аналогичных контейнерам с1 и с2, описанных в практической работе №5, исходя из следующих параметров:

0. Сеть должна иметь имя

net_<prefix>

1. Контейнер с базой данных должен иметь имя

<prefix>_container_db

и хостовое имя

<prefix>-container-db

2. Контейнер с Java-приложением должен иметь имя

<prefix>_container_app

и хостовое имя

<prefix>-container-app

3. База данных должна иметь название

<prefix>_application_db

имя пользователя

<prefix>_application_user

пароль

<prefix>_applicationPassw0rd123

На основе этих данных должен быть создан файл

docker-compose.yaml

а ход работы по его созданию и процедуре запуска работоспособной композы должен быть отражён в отчёте по практической работе №5

[Практическая работа №6] Загрузка образа на hub.docker.com

Исходные данные

У нас есть docker-образ с Java-приложением. Скорее всего он называется

vpupkin/java_prod

В практических работах 1-5 изучение работы с docker и docker-compose осуществлялось исходя из идеи о том, что в будущем для выгрузки docker-образов на hub.docker.com имя образа должно обязательно содержать префикс в виде логина на портале hub.docker.com, отделённый от имени самого образа символом

/

В общем виде имя docker-образа, пригодного для загрузки на портал hub.docker.com выглядит так:

<username>/<imagename>:<tag>

Например, для пользователя с логином

vpupkin

и смысловым названием контейнера с Java-приложением:

java_prod

полное имя docker-образа будет следующим:

vpupkin/java_prod

Ещё более полное имя docker-образа может быть таким:

vpupkin/java_prod:some_tag_name

, где

some_tag_name

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

Обычно, для production-образов значением тега по умолчанию является:

latest

Следовательно, если на портале hub.docker.com предполагается публиковать единственный вариант образа контейнера, то в полном имени образа будем использовать рекомендованный вариант тега. Тогда общий вид имени образа приобретёт следующий вид:

vpupkin/java_prod:latest

Изменение имени docker-образа

Если в процессе выполнения практических работ 1-5 у docker-образа имя осталось шаблонным (т.е. в качестве пользователя остался собирательный образ пользователя -- vpupkin), то перед публикацией образа на hub.docker.com необходимо его изменить.

Если ваш образ называется

vpupkin/java_prod

, а ваш настоящий аккаунт на hub.docker.com имеет логин:

ivanov_ii

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

ivanov_ii/java_prod

В целом, не имеет значения какое название образ будет иметь справа от символа

/

Главное, не давать контейнеру названий, совпадающих с уже загруженными в hub.docker.com контейнерами под вашим именем пользователя (в данном случае -- под логином ivanov_ii). Строго говоря, значение тега справа от двоеточия в имени образа предназначено для того, чтобы у пользователя была возможность не придумывать новые названия для разновидностей docker-образа (при необходимости их публикации на портале), а просто тегировать эти названия.

Учитывая факт того, что в случае отсутствия имени тега (значения справа от двоеточия) у docker-образа при использовании имени образа в команде

docker run ...

или при использовании имени образа в файле

docker-compose.yaml

инфраструктура docker подразумевает использование тега по умолчанию (latest), необходимо задать тег по умолчанию при задании имени образу перед публикацией его на портале hub.docker.com

Изменить имя docker-образа с

vpupkin/java_prod

на

ivanov_ii/java_prod:latest

можно командой (дополнительно уточнив в новом имени значение тега -- справа от двоеточия):

docker tag vpupkin/java_prod ivanov_ii/java_prod:latest

Результат переименования образа можно проверить командой:

docker images

В ответе можно наблюдать несколько образов с одинаковым IMAGE ID

REPOSITORY            TAG       IMAGE ID       CREATED        SIZE
ivanov_ii/java_prod   latest    82acd99eb61f   20 hours ago   1.09GB
vpupkin/java_prod     latest    82acd99eb61f   20 hours ago   1.09GB

При необходимости, образ с предыдущим тегом (vpupkin/java_prod) можно удалить (при отсутствии контейнеров, запущенных на его базе!) командой:

docker rmi vpupkin/java_prod

Решаемая задача

Опубликовать подготовленный docker-образ, имеющий имя

ivanov_ii/java_prod:latest

на hub.docker.com

Для этого необходимо иметь логин и пароль от учётной записи на портале hub.docker.com

Публикация docker-образа

Выполните аутентификацию на портале. Для этого в терминале (где обычно запускаете команды docker... и другие) выполните команду:

docker login

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

Login Succeeded

Полный текст диалога должен быть похож на этот:

Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: ivanov_ii
Password: 
WARNING! Your password will be stored unencrypted in /home/student/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded


После успешного логина для публикации образа выполните команду

docker push ivanov_ii/java_prod:latest

Процедура публикации будет похожа на эту:

The push refers to repository [docker.io/ivanov_ii/java_prod]
e1640cc719ff: Pushed 
6fb986383f38: Pushed 
fbf95f9f9b64: Pushed 
9e9e19c988d7: Pushed 
fa67c5190d97: Pushed 
2b1db325894b: Pushed 
60bdc4ff8a54: Mounted from library/alt 
9a03b2bc42d8: Mounted from library/alt 
latest: digest: sha256:e75a567439afb64a9d3b5b119650e91775e7eb1d9345f5171fefba0cfe18aea3 size: 1990

После завершения процедуры публикации можно проверить наличие образа на портале https://hub.docker.com в личном кабинете, загрузив страницу в браузере выполнив вход в систему.

Загрузка образов Docker из архивного файла

Скачать архивный файл

wget https://wiki.nntc.nnov.ru/download/images.tar.xz 

Распаковать и загрузить образы в docker

unxz -c images.tar.xz | docker load

Оптимизации

Оптимизация для контейнера в практической работе №2

Для сборки приложения можно использовать компилятор Java, доступный в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:

FROM alt:p10
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
RUN apt-get update -q -y \
    && apt-get dist-upgrade -q -y \
    && apt-get install java-11-openjdk-devel nano git java-11-openjdk libGL libgtk+3 libXxf86vm xorg-dri-swrast fonts-ttf-dejavu -q -y

Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством)

затем на этапе клонирования проекта командой

git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter

нужно сменить ветку для использования кода, адаптированного под платформу Java-11 (вместо Java-19 по умолчанию)

git checkout jdk11


Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере Недостатки: более низкая версия платформы Java (11)

Также следует обратить внимание на то, что сборка контейнера производится на другом образе операционной системы (alt:p10) -- официальный образ производителя -- и набор устанавливаемых пакетов отличается от оригинального набора, описанного в практической работе №3.

В остальном порядок выполнения практической работы не отличается от практической работы №3.

Следует обратить внимание, что в операционной системе Alt для получения компилятора javac нужно установить пакет

java-11-openjdk-devel

, что и сделано в соответствюущей RUN-команде в Dockerfile. Также для целей сборки приложения установлены утилиты git и nano.

Пакеты

java-11-openjdk-devel nano git

не нужны в образе для контейнера практической работы №3, следовательно на этапе выполнения практической работы №3 их нужно убрать из команды в Dockerfile

Оптимизация для контейнера в практической работе №3

Для сборки образа с готовым приложением можно использовать Runtime-платформу Java (JRE), доступную в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:

FROM alt:p10
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
RUN apt-get update -q -y \
    && apt-get dist-upgrade -q -y \
    && apt-get install java-11-openjdk libGL libgtk+3 libXxf86vm xorg-dri-swrast fonts-ttf-dejavu -q -y \
    && apt-get autoclean \
    && apt-get autoremove \
    && /bin/rm /var/cache/apt/archives/*.rpm

RUN adduser app

RUN mkdir /opt/app
COPY app /opt/app
COPY startup.sh /
RUN chmod +x /startup.sh

USER app

CMD /startup.sh

Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством. При чём -- только JRE, т.е. без компилятора javac. Компилятор для работы приложения -- не нужен).

Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере Недостатки: более низкая версия платформы Java (11)

Также следует обратить внимание на то, что сборка контейнера производится на другом образе операционной системы (alt:p10) -- официальный образ производителя -- и набор устанавливаемых пакетов отличается от оригинального набора, описанного в практической работе №3.

В остальном порядок выполнения практической работы не отличается от практической работы №3.

Оптимизация композиции контейнеров в практической работе №5

Для добавления к композе контейнера с веб-приложением phpmyadmin необходимо расширить набор сервисов в файле

docker-compose.yaml

следующим образом

version: '3.9'

services:
  c1:
    container_name: "c1"
    hostname: "c1"
    image: "mariadb"
    restart: "always"
    environment:
      MARIADB_ROOT_PASSWORD: "123321"
      MARIADB_DATABASE: "java_app_db"
      MARIADB_USER: "java_app_user"
      MARIADB_PASSWORD: "java_app_password"
    networks:
      - net_c1_c2

  c2:
    container_name: "c2"
    hostname: "c2"
    image: "vpupkin/java_prod"
    restart: "no"
    environment:
      DISPLAY: "$DISPLAY"
      DB_HOST: "c1"
      DB_PORT: "3306"
      DB_NAME: "java_app_db"
      DB_USER: "java_app_user"
      DB_PASS: "java_app_password"
    volumes:
      - /tmp/.X11-unix:/tmp/.X11-unix
    networks:
      - net_c1_c2

  c3:
    container_name: "c3"
    hostname: "c3"
    image: phpmyadmin
    restart: always
    ports:
      - 8080:80
    environment:
      - PMA_ARBITRARY=1
    networks:
      - net_c1_c2


networks:
  net_c1_c2:
    name: net_c1_c2


Относительно конфигурации, представленной в практической работе №5, был добавлен сервис c3:


  c3:
    container_name: "c3"
    hostname: "c3"
    image: phpmyadmin
    restart: always
    ports:
      - 8080:80
    environment:
      - PMA_ARBITRARY=1
    networks:
      - net_c1_c2

который был подключен к той же сети, что и остальные контейнеры.

У сервиса c3 экспортирован 80-й порт, на котором работает веб-приложение, на порт 8080 хостовой системы.

Следовательно, веб-приложение phpmyadmin можен быть запущена в браузере хостовой машины по адресу

http://localhost:8080

Для подключения необходимо использовать следующие данные:

Сервер: c1
Пользователь: root или java_app_user
Пароль: 123321 или java_app_password

Почему так? Смотрите внимательно в файл

docker-compose.yaml

Оптимизация №6 (запуск графического приложения в Docker под Windows)

1. Установить VcXsrv Windows X Server: https://sourceforge.net/projects/vcxsrv/

2. Запустить приложение в режиме "Multiple windows", Display Number = 0, Start no client, поставить галочку "Disable Access Control"

3. Приложение будет запущено в трее.

Команда для запуска приложения (на примере Практической работы №2)

docker run --rm -it -e DISPLAY=<здесь ip адрес вашей windows-машины>:0 --mount source=C:\Users\student\pr02\src,target=/root/src,type=bind --name=java_test --hostname=java-test vpupkin/java_dev /bin/bash

Примеры

Lazarus приложение

https://hub.docker.com/r/vslugin/lazarus_prod

docker pull vslugin/lazarus_prod:latest
docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --name=lazarus_prod --hostname=lazarus-prod vslugin/lazarus_prod

Пример запуска контейнера

docker start lazarus_prod

Java приложение с базой данных (два контейнера)

https://hub.docker.com/r/vslugin/java_prod

Развёртывание и запуск вручную

Команда для разрешения подключения к X-серверу

На докер-хосте под пользователем, под которым планируется запускать приложение из контейнера, выполнить команду:

xhost +
Команда для ручного развёртывания
docker network create net_c1_c2;docker run --name=c1 --hostname=c1 -e MARIADB_ROOT_PASSWORD=123321 -e MARIADB_DATABASE=java_app_db -e MARIADB_USER=java_app_user -e MARIADB_PASSWORD=java_app_password --network net_c1_c2 -d mariadb;sleep 5s;docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --name=c2 --hostname=c2 -e DB_HOST=c1 -e DB_PORT=3306 -e DB_NAME=java_app_db -e DB_USER=java_app_user -e DB_PASS=java_app_password --network net_c1_c2 vslugin/java_prod:latest
Команда запуска приложения

`docker start c2`

Развёртывание и запуск в docker-compose

Развёртывание

Просто бросьте это в консоль:

cd
mkdir compose_c1_c2
cd compose_c1_c2
cat << EOF > docker-compose.yaml
version: '3.9'

services:
  c1:
    container_name: "c1"
    hostname: "c1"
    image: "mariadb"
    restart: "always"
    environment:
      MARIADB_ROOT_PASSWORD: "123321"
      MARIADB_DATABASE: "java_app_db"
      MARIADB_USER: "java_app_user"
      MARIADB_PASSWORD: "java_app_password"
    networks:
      - net_c1_c2

  c2:
    container_name: "c2"
    hostname: "c2"
    image: "vslugin/java_prod:latest"
    restart: "no"
    environment:
      DISPLAY: "$DISPLAY"
      DB_HOST: "c1"
      DB_PORT: "3306"
      DB_NAME: "java_app_db"
      DB_USER: "java_app_user"
      DB_PASS: "java_app_password"
    volumes:
      - /tmp/.X11-unix:/tmp/.X11-unix
    networks:
      - net_c1_c2

networks:
  net_c1_c2:
    name: net_c1_c2
EOF

docker-compose up -d

Команда запуска

docker start c2