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

Материал из wiki.nntc.nnov.ru
Перейти к навигации Перейти к поиску
(Создание файлов)
(Загрузка образов Docker из архивного файла)
 
(не показаны 32 промежуточные версии этого же участника)
Строка 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 alt:p10
+
Важно! Адрес и порт прокси сервера могут быть другими!
  
создайте и запустите Docker-контейнер:
+
Затем необходимо перезапустить сервис
  
  docker run -it --name=my_first_container --hostname=my-first-container alt: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 файл сценария
+
Запустить:
  
  bootstrap.sh
+
  docker start my_first_container
  
со следующим содержимым:
+
или:
  
  #!/bin/bash
+
  docker start f0a3cc6a8b63
echo "Hello, $USER_NAME"
 
  
Сделайте файл исполняемым
+
Естественно, в конкретном случае идентификатор будет другой.
  
chmod +x /bootstrap.sh
 
  
Проверьте работоспособность командой:
+
Подключиться к терминалу Docker-контейнера:
  
  USER_NAME=Ivan /bootstrap.sh
+
  docker attach my_first_container
  
в результате в терминал должна быть выдана строка
+
или
 +
 
 +
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 my_first_image /bootstrap.sh
+
  Ctrl + Q
  
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
+
====Ход работы====
  
====Создание файлов====
+
Запустите контейнер my_first_container и подключитесь к его терминалу (как это сделать - описано выше)
  
В рабочем каталоге создайте файл
+
Установите внутри контейнера текстовый редактор
  
  Dockerfile
+
  apt-get update
 +
apt-get install nano
  
по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):
+
Создайте с помощью установленного редактора nano файл сценария
  
<pre>
+
bootstrap.sh
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
 
</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
 +
 
 +
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 pr02
+
  mkdir pr01
  
 
Перейдите в рабочий каталог
 
Перейдите в рабочий каталог
  
  cd pr02
+
  cd pr01
  
===Создание файлов===
+
====Создание файлов====
  
Скачайте в рабочий каталог JDK версии 19.0.1. Это можно сделать командой (рекомендуется использовать в локальной сети колледжа)
+
В рабочем каталоге создайте файл
  
  wget https://wiki.nntc.nnov.ru/download/openjdk-19.0.1_linux-x64_bin.tar.gz
+
  Dockerfile
  
или командой (при работе вне локальной сети колледжа)
+
по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):
  
wget https://download.java.net/java/GA/jdk19.0.1/afdd2e245b014143b62ccb916125e3ce/10/GPL/openjdk-19.0.1_linux-x64_bin.tar.gz
+
<pre>
 +
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
 +
</pre>
  
Распакуйте загруженный файл командой
 
  
tar -xzpf openjdk-19.0.1_linux-x64_bin.tar.gz
+
В конце этого этапа в рабочем каталоге должен быть один файл:
  
В результате будет доступен каталог
+
Dockerfile
  
jdk-19.0.1
+
====Создание образа контейнера====
  
На этом этапе архив можно удалить командой
+
Для создания Docker-образа (image) выполните команду:
  
  rm openjdk-19.0.1_linux-x64_bin.tar.gz
+
  docker build -t 'my_second_image:latest' .
  
В рабочем каталоге создайте файл
+
Для проверки существования созданного контейнера выполните команду:
  
  Dockerfile_dev
+
  docker images
  
по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):
+
Среди текста ответа должна появиться строчка с новым контейнером:
  
<pre>
+
my_second_image        latest              add5d00c3dc0        7 seconds ago      72.9MB
FROM altlinux/base: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>
 
  
В конце этого этапа в рабочем каталоге должны быть файл:
+
====Запуск контейнера на базе образа====
  
Dockerfile_dev
+
Запуск контейнеров на базе созданного образа (за исключением имени образа и отсутствием необходимости указывать исполняемый скрипт (он указан непосредственно в Dockerfile)) ни чем не будет отличаться от запуска контейнеров в ходе создания образа вручную:
 
и каталог
 
  
  jdk-19.0.1
+
  docker run --rm -e USER_NAME=Ivan my_second_image
  
===Создание образа контейнера===
+
docker run --rm -e USER_NAME=Maria my_second_image
  
Далее в этом разделе будем исходить из условия, что ваш логин на https://hub.docker.com/ будет
+
docker run --rm -e USER_NAME=Petr my_second_image
  
  vpupkin
+
  docker run --rm -e USER_NAME=Ekaterina my_second_image
  
а пароль
+
==[Практическая работа №2] Создание контейнера для разработки приложения на языке Java==
  
ну, вы сами знаете...
+
Откройте терминал хостовой машины и создайте рабочий каталог
  
 +
mkdir pr02
  
 +
Перейдите в рабочий каталог
  
  ! Также стоит помнить, что в эмуляторе терминала находиться нужно в рабочем каталоге !
+
  cd pr02
  
 +
===Создание файлов===
  
Для создания Docker-образа (image) выполните команду:
+
Скачайте в рабочий каталог JDK версии 19.0.1. Это можно сделать командой (рекомендуется использовать в локальной сети колледжа)
  
  docker build -t 'vpupkin/java_dev:latest' -f Dockerfile_dev .
+
  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
  
docker images
+
Распакуйте загруженный файл командой
  
Среди текста ответа должна появиться строчка с новым образом:
+
tar -xzpf openjdk-19.0.1_linux-x64_bin.tar.gz
  
vpupkin/java_dev  latest              fa1a63896356        9 seconds ago      2.42GB
+
В результате будет доступен каталог
  
 +
jdk-19.0.1
  
===Запуск контейнера на базе образа===
+
На этом этапе архив можно удалить командой
  
  mkdir /home/student/pr02/src
+
  rm openjdk-19.0.1_linux-x64_bin.tar.gz
  
На базе полученного образа запустите контейнер, пробросив внутрь контейнера локальный каталог хостовой машины:
+
В рабочем каталоге создайте файл
  
  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
+
  Dockerfile_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>
  
root@java-dev:/#
+
В конце этого этапа в рабочем каталоге должны быть файл:
  
Проверка версии Java RE и компилятора должны возвращать примерно следующее:
+
Dockerfile_dev
 +
 +
и каталог
  
<pre>
+
jdk-19.0.1
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>
 
  
Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать
+
===Создание образа контейнера===
  
exit
+
Далее в этом разделе будем исходить из условия, что ваш логин на https://hub.docker.com/ будет
  
, то контейнер завершит свою работу и найти и запустить его можно таким образом:
+
vpupkin
  
Найти:
+
а пароль
  
  docker ps -a
+
  ну, вы сами знаете...
  
в ответе среди возможных прочих контейнеров должен быть такой:
 
  
8e5f4fd0a99b        vpupkin/java_dev  "/bin/bash"        3 minutes ago      Exited (0) 6 seconds ago                      java_dev
 
  
Имя его в данном случае:
+
! Также стоит помнить, что в эмуляторе терминала находиться нужно в рабочем каталоге !
  
java_dev
 
  
Идентификатор его в данном случае:
+
Для создания Docker-образа (image) выполните команду:
  
  8e5f4fd0a99b
+
  docker build -t 'vpupkin/java_dev:latest' -f Dockerfile_dev .
  
Остальное пока не важно, однако можно догадаться за что отвечают остальные параметры...
 
  
 +
Для проверки существования созданного образа выполните команду:
  
Запустить:
+
docker images
  
docker start java_dev
+
Среди текста ответа должна появиться строчка с новым образом:
  
или:
+
vpupkin/java_dev  latest              fa1a63896356        9 seconds ago      2.42GB
  
docker start 8e5f4fd0a99b
 
  
Естественно, в конкретном случае идентификатор будет другой.
+
===Запуск контейнера на базе образа===
 +
 
 +
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
  
Подключиться к терминалу:
+
Также в этой команде запуска задаются: имя контейнера, имя хоста, команда, которую выполнит контейнер при запуске и указаны ключи, которые автоматически подключают терминал к контейнеру.
  
docker attach java_dev
+
В случае успешного создания контейнера в эмуляторе терминала приглашение должно смениться на такое:
  
или
+
root@java-dev:/#
  
  docker attach 8e5f4fd0a99b
+
Проверка версии 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>
  
 
Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать
 
Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать
Строка 403: Строка 439:
 
  exit
 
  exit
  
, то контейнер завершит свою работу придётся опять читать выше по тексту как его запускать...
+
, то контейнер завершит свою работу и найти и запустить его можно таким образом:
  
 +
Найти:
  
Однако есть способ отключиться от терминала и не завершить контейнер:
+
docker ps -a
  
Для этого нужно последовательно нажать сочетания клавиш:
+
в ответе среди возможных прочих контейнеров должен быть такой:
  
  Ctrl + P
+
  8e5f4fd0a99b        vpupkin/java_dev  "/bin/bash"        3 minutes ago      Exited (0) 6 seconds ago                      java_dev
  
затем
+
Имя его в данном случае:
  
  Ctrl + Q
+
  java_dev
  
 +
Идентификатор его в данном случае:
  
После этого приглашение командной строки контейнера должно заменить приглашение хостовой системы.
+
8e5f4fd0a99b
  
 +
Остальное пока не важно, однако можно догадаться за что отвечают остальные параметры...
  
На этом этапе мы научились создавать образ контейнера и запускать контейнер на его базе.
 
  
===Сборка приложения на языке Java в docker-контейнере===
+
Запустить:
  
Перейдём в каталог
+
docker start java_dev
  
cd /root/src/
+
или:
  
Склонируем проект приложения на Java
+
docker start 8e5f4fd0a99b
  
git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter
+
Естественно, в конкретном случае идентификатор будет другой.
  
Перейдём в проект
 
  
cd simple-counter
+
Подключиться к терминалу:
  
Исходя из рекомендаци в файле README.md выполним сборку проекта
+
docker attach java_dev
  
bash mvnw install
+
или
bash mvnw dependency:copy-dependencies
 
  
В случае успешной сборки в терминале котейнера долждно быть написано что-то похожее на это:
+
docker attach 8e5f4fd0a99b
  
<pre>
 
[INFO] ------------------------------------------------------------------------
 
[INFO] BUILD SUCCESS
 
[INFO] ------------------------------------------------------------------------
 
</pre>
 
  
На этом этам сборки приложения заврешён.
+
Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать
  
Теперь наша задача - запустить приложение прямо на хостовой машине (но выполняться оно будет в контейнере).
+
exit
  
===Запуск собранного приложения в 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
+
Однако есть способ отключиться от терминала и не завершить контейнер:
  
Для успешного запуска графического приложения, работающего в контейнере, с возможностью отображения графического интерфейса, в этой команде сделано две вещи:
+
Для этого нужно последовательно нажать сочетания клавиш:
  
Первая: установлена (внутрь контейнера) переменная окружения
+
Ctrl + P
  
DISPLAY
+
затем
  
равная значению аналогичной переменной окружения хостовой системы.
+
Ctrl + Q
  
Вторая: проброшено устройство
 
  
/tmp/.X11-unix
+
После этого приглашение командной строки контейнера должно заменить приглашение хостовой системы.
  
из хостовой системы в контейнер.
 
  
Также добавлено монтирование каталога src для обмена файлами межу контейнером и хостовой системой, а также добавлена опция
+
На этом этапе мы научились создавать образ контейнера и запускать контейнер на его базе.
  
--rm
+
===Сборка приложения на языке Java в docker-контейнере===
  
которая уничтожает контейнер после его завершения (за данные мы не переживаем, они же лежат локально в каталоге src, который каждый раз монтируется при старте в новый контейнер).
+
Перейдём в каталог
  
 +
cd /root/src/
  
Эта опция сюда добавлена, поскольку сама команда старта контейнера содержит в себе цель запускать именно оболочку /bin/bash для ручного тестирования запуска собранного приложения.
+
Склонируем проект приложения на Java
  
Предполагается, что после такого тестирования контейнер не нужен и при выходе из него его логичнее всего автоматически удалять.
+
git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter
  
 +
Перейдём в проект
  
Когда работа собранного приложения протестирована и есть понимание, что всё работает корректно, можно приступать к сборке образа для production-контейнера, в котором необходимо оставить необходимое и достаточное количество библиотек, необходимых только для запуска уже собранного приложения, а пакеты и утилиты, необходимые для сборки, не включать в результирующий образ.
+
cd simple-counter
  
Важный момент: В некоторых операционных системах может потребоваться выполнить команду
+
Исходя из рекомендаци в файле README.md выполним сборку проекта
  
  xhost +
+
  bash mvnw install
 +
bash mvnw dependency:copy-dependencies
  
для разрешения подключения контейнера к графической оболочке X-сервера.
+
В случае успешной сборки в терминале котейнера долждно быть написано что-то похожее на это:
  
Тестовый запуск приложения можно выполнить командами:
+
<pre>
 +
[INFO] ------------------------------------------------------------------------
 +
[INFO] BUILD SUCCESS
 +
[INFO] ------------------------------------------------------------------------
 +
</pre>
  
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
 
  
===Отвечаем на главный вопрос?===
+
Теперь наша задача - запустить приложение прямо на хостовой машине (но выполняться оно будет в контейнере).
  
Вопрос звучит так:
+
===Запуск собранного приложения в 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
  
Не нужны по нескольким причинам:
+
Для успешного запуска графического приложения, работающего в контейнере, с возможностью отображения графического интерфейса, в этой команде сделано две вещи:
  
# Исходный чаще всего остаётся интеллектуальной собственностью компании-разработчика и не должен оказаться у заказчика
+
Первая: установлена (внутрь контейнера) переменная окружения
# Наличие на Production-системе компилятора какого-либо языка и/или каких-либо средств разработки является потенциальной уязвимостью системы
 
# Инструменты сборки и тестирования никогда не понадобятся конечному пользователю на  Production-системе, но всегда будут занимать место на файловой системе контейнера
 
  
Поэтому для конечного пользователя целесообразно создать новый образ, исключив оттуда всё лишнее и оставив лишь непосредственно готовое приложение.
+
DISPLAY
  
Как это сделать -- см. в следующей практической работе.
+
равная значению аналогичной переменной окружения хостовой системы.
  
==[Практическая работа №3] Создание контейнера для запуска Java-приложения==
+
Вторая: проброшено устройство
Откройте терминал хостовой машины. Создайте рабочий каталог
 
  
  mkdir pr03
+
  /tmp/.X11-unix
  
Перейдите в рабочий каталог
+
из хостовой системы в контейнер.
  
cd pr03
+
Также добавлено монтирование каталога src для обмена файлами межу контейнером и хостовой системой, а также добавлена опция
  
===Создание файлов===
+
--rm
  
В рабочем каталоге создайте файл
+
которая уничтожает контейнер после его завершения (за данные мы не переживаем, они же лежат локально в каталоге src, который каждый раз монтируется при старте в новый контейнер).
  
Dockerfile_prod
 
  
по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):
+
Эта опция сюда добавлена, поскольку сама команда старта контейнера содержит в себе цель запускать именно оболочку /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
+
Когда работа собранного приложения протестирована и есть понимание, что всё работает корректно, можно приступать к сборке образа для production-контейнера, в котором необходимо оставить необходимое и достаточное количество библиотек, необходимых только для запуска уже собранного приложения, а пакеты и утилиты, необходимые для сборки, не включать в результирующий образ.
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
+
xhost +
RUN echo "export JAVA_HOME=/opt/jdk-19.0.1" >> /home/app/.bashrc
 
  
USER app
+
для разрешения подключения контейнера к графической оболочке X-сервера.
  
CMD /startup.sh
+
Тестовый запуск приложения можно выполнить командами:
</pre>
 
  
Создайте каталог app в рабочем каталоге
+
  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
  mkdir app
 
  
Скопируйте исполняемый файл, полученный в предыдущей работе в рабочий каталог
+
===Отвечаем на главный вопрос?===
  
/bin/cp -rf ../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
+
# Исходный код чаще всего остаётся интеллектуальной собственностью компании-разработчика и не должен оказаться у заказчика;
 +
# Наличие на Production-системе компилятора какого-либо языка и/или каких-либо средств разработки является потенциальной уязвимостью системы;
 +
# Инструменты сборки и тестирования никогда не понадобятся конечному пользователю на Production-системе, но всегда будут занимать место на файловой системе контейнера.
  
Распакуйте загруженный файл командой
+
Поэтому для конечного пользователя целесообразно создать новый образ, исключив оттуда всё лишнее и оставив лишь непосредственно готовое приложение.
  
tar -xzpf openjdk-19.0.1_linux-x64_bin.tar.gz
+
Как это сделать -- см. в следующей практической работе.
  
На этом этапе архив можно удалить командой
+
==[Практическая работа №3] Создание контейнера для запуска Java-приложения==
 +
Откройте терминал хостовой машины. Создайте рабочий каталог
  
  rm openjdk-19.0.1_linux-x64_bin.tar.gz
+
  mkdir pr03
  
Создайте в рабочем каталоге файл
+
Перейдите в рабочий каталог
  
  startup.sh
+
  cd pr03
  
со следующим содержимым
+
===Создание файлов===
  
<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
  
Dockerfile_prod
+
по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):
startup.sh
 
  
И два каталога:
+
<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
  
jdk-19.0.1
+
RUN adduser app
app
 
  
===Создание образа контейнера===
+
RUN mkdir /opt/jdk-19.0.1
 +
COPY jdk-19.0.1 /opt/jdk-19.0.1
  
Далее в этом разделе будем исходить из условия, что ваш логин на https://hub.docker.com/ будет
+
RUN mkdir /opt/app
 +
COPY app /opt/app
 +
COPY startup.sh /
 +
RUN chmod +x /startup.sh
  
vpupkin
+
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
 +
</pre>
  
 +
Создайте каталог app в рабочем каталоге
 +
 +
mkdir app
  
 +
Скопируйте исполняемый файл, полученный в предыдущей работе в рабочий каталог
  
  ! Также стоит помнить, что в эмуляторе терминала находиться нужно в рабочем каталоге !
+
  /bin/cp -r ../pr02/src/simple-counter/target app/
  
 +
Скачайте в рабочий каталог JDK версии 19.0.1. Это можно сделать командой (рекомендуется использовать в локальной сети колледжа)
  
Для создания Docker-образа (image) выполните команду:
+
wget https://wiki.nntc.nnov.ru/download/openjdk-19.0.1_linux-x64_bin.tar.gz
  
docker build -t 'vpupkin/java_prod:latest' -f Dockerfile_prod .
+
или командой (при работе вне локальной сети колледжа)
  
 +
wget https://download.java.net/java/GA/jdk19.0.1/afdd2e245b014143b62ccb916125e3ce/10/GPL/openjdk-19.0.1_linux-x64_bin.tar.gz
  
Для проверки существования созданного контейнера выполните команду:
+
Распакуйте загруженный файл командой
  
  docker images
+
  tar -xzpf openjdk-19.0.1_linux-x64_bin.tar.gz
  
Среди текста ответа должна появиться строчка с новым контейнером:
+
На этом этапе архив можно удалить командой
  
  vpupkin/java_prod  latest              20bb2900074d        16 seconds ago      217MB
+
  rm openjdk-19.0.1_linux-x64_bin.tar.gz
  
 +
Создайте в рабочем каталоге файл
  
  ! Обратите внимание на размер контейнера !
+
  startup.sh
Сравните размер контейнера с размером контейнера java_dev из предыдущей работы
 
  
===Запуск контейнера на базе образа===
+
со следующим содержимым
  
Создадим каталог для обмена данными с контейнером
+
<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>
  
mkdir $HOME/data
+
В конце этого этапа в рабочем каталоге должно быть два файла:
  
На базе полученного образа запустите контейнер, пробросив внутрь контейнера локальный каталог хостовой машины:
+
Dockerfile_prod
 +
startup.sh
  
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
+
И два каталога:
  
 +
jdk-19.0.1
 +
app
  
При запуске контейнера таким образом не указывается команда, т.к. она задаётся в файле
+
===Создание образа контейнера===
  
Dockerfile_prod
+
Далее в этом разделе будем исходить из условия, что ваш логин на https://hub.docker.com/ будет
  
строчкой
+
vpupkin
  
CMD /bin/su -c "/startup.sh" app
+
а пароль
  
Результатом запуска контейнера должно стать запущенное внутри контейнера графическое приложение с отображением графического интерфейса на хостовой машине.
+
ну, вы сами знаете...
  
При закрытии окна графического приложения контейнер будет завершён и будет доступен среди списка контейнеров
 
  
docker ps -a
 
  
Повторный запуск уже существующего контейнера можно осуществить по имени контейнера командой:
+
! Также стоит помнить, что в эмуляторе терминала находиться нужно в рабочем каталоге !
  
docker start java_prod
 
  
==[Практическая работа №4] Взаимодействие двух контейнеров по сети (ручной запуск)==
+
Для создания Docker-образа (image) выполните команду:
  
Задача: Запустить Java-приложение в контейнере с именем c2, который взаимодействует с базой данных Mariadb, запущенной в контейнере с именем c1
+
docker build -t 'vpupkin/java_prod:latest' -f Dockerfile_prod .
  
===Загрузка образа для контейнера с mariadb===
 
  
docker pull mariadb
+
Для проверки существования созданного контейнера выполните команду:
  
===Создание сетевого моста===
+
docker images
  
docker network create net_c1_c2
+
Среди текста ответа должна появиться строчка с новым контейнером:
  
Проверить список сетевых мостов можно командой
+
vpupkin/java_prod  latest              20bb2900074d        16 seconds ago      217MB
  
docker network list
 
  
===Запуск контейнера c1 и подготовка базы данных===
+
! Обратите внимание на размер контейнера !
 +
Сравните размер контейнера с размером контейнера java_dev из предыдущей работы
  
Создать контейнер с базой данных 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)
+
mkdir $HOME/data
  
docker exec -it c1 /bin/bash
+
На базе полученного образа запустите контейнер, пробросив внутрь контейнера локальный каталог хостовой машины:
  
Внутри контейнера запустить клиент mysql с параметрами подключения к бд:
+
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
  
mysql -u java_app_user -pjava_app_password -h localhost java_app_db
 
 
Выход из mysql и из контейнера
 
  
exit
+
При запуске контейнера таким образом не указывается команда, т.к. она задаётся в файле
exit
 
  
===Запуск контейнера c2 с Java-приложением===
+
Dockerfile_prod
  
Запуск контейнера с Java-приложением производится аналогично запуску, подробно описанному в практической работе №3 с учётом ряда нюансов:
+
строчкой
  
1. Необходимо учитывать, что имя запускаемого контейнера должно быть
+
CMD /bin/su -c "/startup.sh" app
  
с2
+
Результатом запуска контейнера должно стать запущенное внутри контейнера графическое приложение с отображением графического интерфейса на хостовой машине.
  
2. Необходимо учитывать, что имя хоста запускаемого контейнера должно быть
+
При закрытии окна графического приложения контейнер будет завершён и будет доступен среди списка контейнеров
  
  с2
+
  docker ps -a
  
3. Необходимо учитывать, что для корректного подключения Java-приложения к базе данных, доступной в контейнере с именем_контейнера=именем_хоста=с1 необходимо при запуске контейнера с2 передать набор переменных окружения для настройки Java-приложения на работу с базой данных в контейнере c1
+
Повторный запуск уже существующего контейнера можно осуществить по имени контейнера командой:
  
  DB_HOST=c1
+
  docker start java_prod
DB_PORT=3306
 
DB_NAME=java_app_db
 
DB_USER=java_app_user
 
DB_PASS=java_app_password
 
  
Пример команды для запуска контейнера c2 (запуск контейнера осуществляется на базе образа, созданного в практической работе №3)
+
==[Практическая работа №4] Взаимодействие двух контейнеров по сети (ручной запуск)==
  
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
+
Задача: Запустить Java-приложение в контейнере с именем c2, который взаимодействует с базой данных Mariadb, запущенной в контейнере с именем c1
  
При необходимости монтирования директорий хостовой машины в контейнер также могут быть использованы дополнительные параметры, как было показано в примере запуска контейнера в практической работе №3 с параметром
+
===Загрузка образа для контейнера с mariadb===
  
  --mount source="$HOME/data",target=/home/app/data,type=bind
+
  docker pull mariadb
  
В данном примере этот параметр опущен, т.к. тестовое приложение не имеет функций чтения и записи файлов.
+
===Создание сетевого моста===
  
===Самостоятельное задание===
+
docker network create net_c1_c2
  
====Подготовка====
+
Проверить список сетевых мостов можно командой
  
Придумать уникальный префикс для именования названий, завязанный на фамилию и инициалы обучающегося.
+
docker network list
  
Например, для обучающегося
+
===Запуск контейнера c1 и подготовка базы данных===
  
Иванов Иван Иванович
+
Создать контейнер с базой данных Mariadb и задать исходные параметры работы СУБД (название базы данных, логин и пароль для базы данных, пароль пользователя root) через переменные окружения
  
Префикс (<prefix>) будет состоять из фамилии и инициалов
+
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
  
ivanov_ii
+
Проверить корректность подключения к Mariadb с созданным пользователем к созданной базе данных (подключиться к консоли контейнера c1 и воспользоваться клиентом mariadb)
  
Тогда в приведённых ниже примерах необходимо
+
docker exec -it c1 /bin/bash
  
<prefix>
+
Внутри контейнера запустить клиент mariadb (ранее это был клиент mysql) с параметрами подключения к бд:
  
заменять на
+
mariadb -u java_app_user -pjava_app_password -h localhost java_app_db
 +
 +
Выход из mariadb и затем из контейнера
  
  ivanov_ii
+
  exit
 +
exit
  
Например
+
===Запуск контейнера c2 с Java-приложением===
  
ivanov_ii_container_db
+
Запуск контейнера с Java-приложением производится аналогично запуску, подробно описанному в практической работе №3 с учётом ряда нюансов:
  
 +
1. Необходимо учитывать, что имя запускаемого контейнера должно быть
  
====Выполнение задания====
+
с2
  
Используя справку по docker и набор выполненных практических работ запустить тестовое Java-приложение в двух контейнерах, аналогичных контейнерам с1 и с2, исходя из следующих параметров:
+
2. Необходимо учитывать, что имя хоста запускаемого контейнера должно быть
  
0. Сетевой мост должен иметь имя
+
с2
  
net_<prefix>
+
3. Необходимо учитывать, что для корректного подключения Java-приложения к базе данных, доступной в контейнере с именем_контейнера=именем_хоста=с1 необходимо при запуске контейнера с2 передать набор переменных окружения для настройки Java-приложения на работу с базой данных в контейнере c1
  
1. Контейнер с базой данных должен иметь имя
+
DB_HOST=c1
 
+
DB_PORT=3306
  <prefix>_container_db
+
DB_NAME=java_app_db
 +
DB_USER=java_app_user
 +
  DB_PASS=java_app_password
  
и хостовое имя
+
Пример команды для запуска контейнера c2 (запуск контейнера осуществляется на базе образа, созданного в практической работе №3)
  
<prefix>-container-db
+
Не забудем про
  
2. Контейнер с Java-приложением должен иметь имя
+
xhost +
  
  <prefix>_container_app
+
  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 с параметром
  
  <prefix>-container-app
+
  --mount source="$HOME/data",target=/home/app/data,type=bind
  
3. База данных должна иметь название
+
В данном примере этот параметр опущен, т.к. тестовое приложение не имеет функций чтения и записи файлов.
  
<prefix>_application_db
+
===Самостоятельное задание===
  
имя пользователя
+
====Подготовка====
  
<prefix>_application_user
+
Придумать уникальный префикс для именования названий, завязанный на фамилию и инициалы обучающегося.
  
пароль
+
Например, для обучающегося
  
  <prefix>_applicationPassw0rd123
+
  Иванов Иван Иванович
  
Ход работы отразить в отчёте по практической работе №4
+
Префикс (<prefix>) будет состоять из фамилии и инициалов
  
==[Практическая работа №5] Взаимодействие двух контейнеров по сети (docker-compose)==
+
ivanov_ii
  
===Предисловие===
+
Тогда в приведённых ниже примерах необходимо
  
Решаемая в данной практической работе задача аналогична задаче из практической работы №4. Отличия состоят лишь в том, что в практической работе №4 запуск двух контейнеров, взаимодействующих между собой внутри изолированной сети, осуществляется вручную, путём выполнения команд:
+
<prefix>
  
docker run ...
+
заменять на
  
Для автоматизации запуска приложений, компоненты которых разделены по контейнерам (их (приложения в контейнерах) ещё называют микросервисами) может быть использован инструмент:
+
ivanov_ii
  
docker-compose
+
Например
  
Инструмент docker-compose (смысл названия можно перевести как "композиция из докер контейнеров") предназначен для того, чтобы автоматически запустить несколько docker-контейнеров в одном контексте (как правило, под контекстом подразумевается общая сеть, изолированная от хостовой системы но доступная для всех контейнеров композиции (как говорят DevOps-инженеры -- "композы")).
+
ivanov_ii_container_db
  
В практической работе №2 мы изучали два способа создания docker-образа: ручной и автоматический.
 
  
Ручной способ подразумевал создание контейнера на базе стандартного образа, выполнение ряда действий внутри этого контейнера вручную, с последующим созданием образа на базе изменённого вручную контейнера. В результате получался новый образ, на базе которого можно запускать новые контейнеры.
+
====Выполнение задания====
  
Автоматический способ подразумевал решение аналогичной задачи, но без участия пользователя. Т.е. пользователь один раз описывал файл (Dockerfile), который включал в себя все необходимые команды (которые в ручном режиме пользователь выполнял вручную) и директивы, которых минимально необходимо и достаточно для сборки образа в автоматическом режиме. После того, как был подготовлен Dockerfile, на его базе командой:
+
Используя справку по docker и набор выполненных практических работ запустить тестовое Java-приложение в двух контейнерах, аналогичных контейнерам с1 и с2, исходя из следующих параметров:
  
docker build...
+
0. Сетевой мост должен иметь имя
  
производилась сборка образа
+
net_<prefix>
  
 +
1. Контейнер с базой данных должен иметь имя
  
Между ручным запуском двух контейнеров, описанным в практической работе №4, и автоматическим запуском композиции из докер контейнеров (композы), описываемой в этой практической работе, можно провести такую же аналогию, как между созданием образа контейнера вручную и созданием образа контейнера автоматически. Два этих способа (ручной и автоматический) объединяет наличие специального конфигурационного файла. В случае с автоматической сборкой docker-образа это файл:
+
<prefix>_container_db
  
Dockerfile
+
и хостовое имя
  
, в случае же с автоматическим запуском нескольких контейнеров в композе -- это файл:
+
<prefix>-container-db
  
docker-compose.yaml
+
2. Контейнер с Java-приложением должен иметь имя
  
Для того, чтобы запустить любую композицию контейнеров, необходимо:
+
<prefix>_container_app
  
1. Сконфигурировать файл
+
и хостовое имя
  
  docker-compose.yaml
+
  <prefix>-container-app
  
2. Выполнить запуск композы командой
+
3. База данных должна иметь название
  
  docker-compose up ...
+
  <prefix>_application_db
  
===Установка docker-compose===
+
имя пользователя
  
В хостовой системе откройте терминал и выполните команду для получения доступа под суперпользователем root
+
<prefix>_application_user
  
su -
+
пароль
  
Введите пароль от суперпользователя. Приглашение должно смениться на суперпользовательское и заканчиваться символом решётки. В этом режиме выполните команду установки пакета из репозитория:
+
<prefix>_applicationPassw0rd123
  
apt-get install docker-compose -y
+
Ход работы отразить в отчёте по практической работе №4
  
При необходимости, перед выполнением этой команды можно выполнить команду обновления базы данных пакетов в репозитории:
+
==[Практическая работа №5] Взаимодействие двух контейнеров по сети (docker compose)==
  
apt-get update
+
===Предисловие===
  
===Практика===
+
Решаемая в данной практической работе задача аналогична задаче из практической работы №4. Отличия состоят лишь в том, что в практической работе №4 запуск двух контейнеров, взаимодействующих между собой внутри изолированной сети, осуществляется вручную, путём выполнения команд:
  
Создайте рабочий каталог и перейдите в него
+
docker run ...
  
mkdir compose_с1_с2
+
Для автоматизации запуска приложений, компоненты которых разделены по контейнерам (их (приложения в контейнерах) ещё называют микросервисами) может быть использован инструмент:
cd compose_с1_с2
 
  
Создайте файл
+
docker compose
  
docker-compose.yaml
+
Инструмент docker compose (смысл названия можно перевести как "композиция из докер контейнеров") предназначен для того, чтобы автоматически запустить несколько docker-контейнеров в одном контексте (как правило, под контекстом подразумевается общая сеть, изолированная от хостовой системы но доступная для всех контейнеров композиции (как говорят DevOps-инженеры -- "композы")).
  
со следующим содержимым
+
В практической работе №2 мы изучали два способа создания docker-образа: ручной и автоматический.
  
<pre>
+
Ручной способ подразумевал создание контейнера на базе стандартного образа, выполнение ряда действий внутри этого контейнера вручную, с последующим созданием образа на базе изменённого вручную контейнера. В результате получался новый образ, на базе которого можно запускать новые контейнеры.
version: '3.9'
 
  
services:
+
Автоматический способ подразумевал решение аналогичной задачи, но без участия пользователя. Т.е. пользователь один раз описывал файл (Dockerfile), который включал в себя все необходимые команды (которые в ручном режиме пользователь выполнял вручную) и директивы, которых минимально необходимо и достаточно для сборки образа в автоматическом режиме. После того, как был подготовлен Dockerfile, на его базе командой:
  c1:
+
 
    container_name: "c1"
+
docker build...
    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:
+
Между ручным запуском двух контейнеров, описанным в практической работе №4, и автоматическим запуском композиции из докер контейнеров (композы), описываемой в этой практической работе, можно провести такую же аналогию, как между созданием образа контейнера вручную и созданием образа контейнера автоматически. Два этих способа (ручной и автоматический) объединяет наличие специального конфигурационного файла. В случае с автоматической сборкой docker-образа это файл:
  net_c1_c2:
 
    name: net_c1_c2
 
</pre>
 
  
 +
Dockerfile
  
В результате в рабочем каталоге должен быть файл:
+
, в случае же с автоматическим запуском нескольких контейнеров в композе -- это файл:
  
 
  docker-compose.yaml
 
  docker-compose.yaml
  
Для запуска композиции выполните в рабочем каталоге команду
+
Для того, чтобы запустить любую композицию контейнеров, необходимо:
  
docker-compose up -d
+
1. Сконфигурировать файл
  
В результате по описанной в файле docker-compose.yaml схеме сервисов будут запущены два контейнера: с1 и с2. В том числе из контейнера с2 будет запущено графическое приложение, которое будет работать с базой данных, запущенной в контейнере с1.
+
docker-compose.yaml
  
====Возможные проблемы и их решения====
+
2. Выполнить запуск композы командой
  
Проблема №1: не запускается графический интерфейс Java-приложения.
+
docker compose up ...
Решение: Открыть терминал хостовой системы и выполнить в нём команду для разрешения подключения к графической системы извне (в частности -- из контейнера):
 
  
xhost +
+
===Практика===
  
Проблема №2: Java-приложение не может подключиться к базе данных.
+
Создайте рабочий каталог и перейдите в него
Решение: Повторно запустить контейнер c2. При первом запуске композы в контейнере c1 сервис базы данных не успевает запуститься к моменту, когда в контейнере c2 стартует Java-приложение. Поэтому приложение показывает ошибку. Когда окно приложение закрывается -- контейнер c2 прекращает свою работу, однако контейнер c1 по прежнему работает (и в нём с высокой долей вероятности уже запустилась СУБД). Поэтому повторный запуск контейнера c2 запустит Java-приложение, в котором уже не будет ошибки подключения к базе данных (конечно, при условии, что всё верно настроено).
 
  
====Работа с контейнерами в контексте docker-compose====
+
mkdir compose_с1_с2
 +
cd compose_с1_с2
  
Если мы находимся в каталоге с файлом (Это важно! Все команды этого раздела актуальны, если соблюдается простое правило -- мы стоим в каталоге с этим файлом):
+
Создайте файл
  
 
  docker-compose.yaml
 
  docker-compose.yaml
  
то для упрощения работы с контейнерами (сервисами микросервисной архитектуры), входящими в состав композы, можно вместо команды
+
со следующим содержимым
  
docker
+
<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
  
docker-compose
+
  c2:
 
+
    container_name: "c2"
В случае с нашей композой сервисы имеют названия c1 и с2, следовательно, для их остановки можно применять команды:
+
    hostname: "c2"
 
+
    image: "vpupkin/java_prod"
docker-compose stop c1
+
    restart: "no"
 
+
    environment:
или
+
      DISPLAY: "$DISPLAY"
 
+
      DB_HOST: "c1"
docker-compose stop c2
+
      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
  
docker-compose stop
+
networks:
 +
  net_c1_c2:
 +
    name: net_c1_c2
 +
</pre>
  
а для запуска, соответственно
 
  
docker-compose start c1
+
В результате в рабочем каталоге должен быть файл:
  
или
+
docker-compose.yaml
  
docker-compose start c2
+
Для запуска композиции выполните в рабочем каталоге команду
  
а для запуска всей композы -- команду:
+
docker compose up -d
  
docker-compose start
+
В результате по описанной в файле docker-compose.yaml схеме сервисов будут запущены два контейнера: с1 и с2. В том числе из контейнера с2 будет запущено графическое приложение, которое будет работать с базой данных, запущенной в контейнере с1.
  
 +
====Возможные проблемы и их решения====
  
Для развёртывания (поднятия -- up) композы выше использовалась команда:
+
Проблема №1: не запускается графический интерфейс Java-приложения.
 +
Решение: Открыть терминал хостовой системы и выполнить в нём команду для разрешения подключения к графической системы извне (в частности -- из контейнера):
  
  docker-compose up -d
+
  xhost +
  
 +
Проблема №2: Java-приложение не может подключиться к базе данных.
 +
Решение: Повторно запустить контейнер c2. При первом запуске композы в контейнере c1 сервис базы данных не успевает запуститься к моменту, когда в контейнере c2 стартует Java-приложение. Поэтому приложение показывает ошибку. Когда окно приложение закрывается -- контейнер c2 прекращает свою работу, однако контейнер c1 по прежнему работает (и в нём с высокой долей вероятности уже запустилась СУБД). Поэтому повторный запуск контейнера c2 запустит Java-приложение, в котором уже не будет ошибки подключения к базе данных (конечно, при условии, что всё верно настроено).
  
Существует обратная операция, которую условно можно назвать свёртыванием (опускания -- down) композы. Для этого может быть использована команда:
+
====Работа с контейнерами в контексте docker compose====
  
docker-compose down
+
Если мы находимся в каталоге с файлом (Это важно! Все команды этого раздела актуальны, если соблюдается простое правило -- мы стоим в каталоге с этим файлом):
  
Выполнение этой команды приводит к остановке и удалению всех контейнеров композы. При этом образы остаются в системе.
+
docker-compose.yaml
  
После операции свёртывания композы в системе остаются занятые виртуальные диски, которые резервируются для контейнеров в момент запуска композы. Для очистки этих дисков, а следовательно для увеличения свободного места на диске, можно выполнить команду:
+
то для упрощения работы с контейнерами (сервисами микросервисной архитектуры), входящими в состав композы, можно вместо команды
  
  docker volume prune
+
  docker
  
Эта команда удалит все не занятые контейнерами виртуальные диски (volumes) подсистемы docker.
+
использовать команду
  
 +
docker compose
  
Также посредством команды
+
В случае с нашей композой сервисы имеют названия c1 и с2, следовательно, для их остановки можно применять команды:
  
  docker-compose
+
  docker compose stop c1
  
помимо остановки и запуска контейнеров можно выполнять другие действия над контенерами композы. Например, просмотр журналов (логов) и другие.
+
или
  
 +
docker compose stop c2
  
Изучите справочную систему команды
+
а для остановки всей композы -- команду:
  
  docker-compose
+
  docker compose stop
  
для ознакомления с другим её функционалом.
+
а для запуска, соответственно
  
===Самостоятельное задание===
+
docker compose start c1
  
====Подготовка====
+
или
  
Придумать уникальный префикс для именования названий, завязанный на фамилию и инициалы обучающегося.
+
docker compose start c2
  
Например, для обучающегося
+
а для запуска всей композы -- команду:
  
  Иванов Иван Иванович
+
  docker compose start
  
Префикс (<prefix>) будет состоять из фамилии и инициалов
 
  
ivanov_ii
+
Для развёртывания (поднятия -- up) композы выше использовалась команда:
  
Тогда в приведённых ниже примерах необходимо
+
docker compose up -d
  
<prefix>
 
  
заменять на
+
Существует обратная операция, которую условно можно назвать свёртыванием (опускания -- down) композы. Для этого может быть использована команда:
  
  ivanov_ii
+
  docker compose down
  
Например
+
Выполнение этой команды приводит к остановке и удалению всех контейнеров композы. При этом образы остаются в системе.
  
ivanov_ii_container_db
+
После операции свёртывания композы в системе остаются занятые виртуальные диски, которые резервируются для контейнеров в момент запуска композы. Для очистки этих дисков, а следовательно для увеличения свободного места на диске, можно выполнить команду:
  
 +
docker volume prune
  
====Выполнение задания====
+
Эта команда удалит все не занятые контейнерами виртуальные диски (volumes) подсистемы docker.
  
Используя справку по docker, docker-compose и набор выполненных практических работ запустить тестовое Java-приложение в композиции из двух контейнеров, аналогичных контейнерам с1 и с2, описанных в практической работе №5, исходя из следующих параметров:
 
  
0. Сеть должна иметь имя
+
Также посредством команды
  
  net_<prefix>
+
  docker compose
  
1. Контейнер с базой данных должен иметь имя
+
помимо остановки и запуска контейнеров можно выполнять другие действия над контенерами композы. Например, просмотр журналов (логов) и другие.
  
<prefix>_container_db
 
  
и хостовое имя
+
Изучите справочную систему команды
  
  <prefix>-container-db
+
  docker compose
  
2. Контейнер с Java-приложением должен иметь имя
+
для ознакомления с другим её функционалом.
  
<prefix>_container_app
+
===Самостоятельное задание===
  
и хостовое имя
+
====Подготовка====
  
<prefix>-container-app
+
Придумать уникальный префикс для именования названий, завязанный на фамилию и инициалы обучающегося.
  
3. База данных должна иметь название
+
Например, для обучающегося
  
  <prefix>_application_db
+
  Иванов Иван Иванович
  
имя пользователя
+
Префикс (<prefix>) будет состоять из фамилии и инициалов
  
  <prefix>_application_user
+
  ivanov_ii
  
пароль
+
Тогда в приведённых ниже примерах необходимо
  
  <prefix>_applicationPassw0rd123
+
  <prefix>
  
На основе этих данных должен быть создан файл
+
заменять на
  
  docker-compose.yaml
+
  ivanov_ii
  
а ход работы по его созданию и процедуре запуска работоспособной композы должен быть отражён в отчёте по практической работе №5
+
Например
  
==[Практическая работа №6] Загрузка образа на hub.docker.com==
+
ivanov_ii_container_db
  
===Исходные данные===
 
  
У нас есть docker-образ с Java-приложением. Скорее всего он называется
+
====Выполнение задания====
  
vpupkin/java_prod
+
Используя справку по docker, docker-compose и набор выполненных практических работ запустить тестовое Java-приложение в композиции из двух контейнеров, аналогичных контейнерам с1 и с2, описанных в практической работе №5, исходя из следующих параметров:
  
В практических работах 1-5 изучение работы с docker и docker-compose осуществлялось исходя из идеи о том, что в будущем для выгрузки docker-образов на hub.docker.com имя образа должно обязательно содержать префикс в виде логина на портале hub.docker.com, отделённый от имени самого образа символом
+
0. Сеть должна иметь имя
  
  /
+
  net_<prefix>
  
В общем виде имя docker-образа, пригодного для загрузки на портал hub.docker.com выглядит так:
+
1. Контейнер с базой данных должен иметь имя
  
  <username>/<imagename>:<tag>
+
  <prefix>_container_db
  
Например, для пользователя с логином
+
и хостовое имя
  
  vpupkin
+
  <prefix>-container-db
  
и смысловым названием контейнера с Java-приложением:
+
2. Контейнер с Java-приложением должен иметь имя
  
  java_prod
+
  <prefix>_container_app
  
полное имя docker-образа будет следующим:
+
и хостовое имя
  
  vpupkin/java_prod
+
  <prefix>-container-app
  
Ещё более полное имя docker-образа может быть таким:
+
3. База данных должна иметь название
  
  vpupkin/java_prod:some_tag_name
+
  <prefix>_application_db
  
, где
+
имя пользователя
  
  some_tag_name
+
  <prefix>_application_user
  
это любое имя тега, которое может быть придумано создателем образа.
+
пароль
  
Обычно, для production-образов значением тега по умолчанию является:
+
<prefix>_applicationPassw0rd123
  
latest
+
На основе этих данных должен быть создан файл
  
Следовательно, если на портале hub.docker.com предполагается публиковать единственный вариант образа контейнера, то в полном имени образа будем использовать рекомендованный вариант тега. Тогда общий вид имени образа приобретёт следующий вид:
+
docker-compose.yaml
  
vpupkin/java_prod:latest
+
а ход работы по его созданию и процедуре запуска работоспособной композы должен быть отражён в отчёте по практической работе №5
  
===Изменение имени docker-образа===
+
==[Практическая работа №6] Загрузка образа на hub.docker.com==
  
Если в процессе выполнения практических работ 1-5 у docker-образа имя осталось шаблонным (т.е. в качестве пользователя остался собирательный образ пользователя -- vpupkin), то перед публикацией образа на hub.docker.com необходимо его изменить.
+
===Исходные данные===
  
Если ваш образ называется
+
У нас есть docker-образ с Java-приложением. Скорее всего он называется
  
 
  vpupkin/java_prod
 
  vpupkin/java_prod
  
, а ваш настоящий аккаунт на hub.docker.com имеет логин:
+
В практических работах 1-5 изучение работы с docker и docker-compose осуществлялось исходя из идеи о том, что в будущем для выгрузки docker-образов на hub.docker.com имя образа должно обязательно содержать префикс в виде логина на портале hub.docker.com, отделённый от имени самого образа символом
  
  ivanov_ii
+
  /
  
, то прежде чем выполнять публикацию образа его необходимо переименовать. Новое имя образа может быть, например, таким:
+
В общем виде имя docker-образа, пригодного для загрузки на портал hub.docker.com выглядит так:
  
  ivanov_ii/java_prod
+
  <username>/<imagename>:<tag>
  
В целом, не имеет значения какое название образ будет иметь справа от символа
+
Например, для пользователя с логином
  
  /
+
  vpupkin
  
Главное, не давать контейнеру названий, совпадающих с уже загруженными в hub.docker.com контейнерами под вашим именем пользователя (в данном случае -- под логином ivanov_ii).
+
и смысловым названием контейнера с Java-приложением:
Строго говоря, значение тега справа от двоеточия в имени образа предназначено для того, чтобы у пользователя была возможность не придумывать новые названия для разновидностей docker-образа (при необходимости их публикации на портале), а просто тегировать эти названия.
 
  
Учитывая факт того, что в случае отсутствия имени тега (значения справа от двоеточия) у docker-образа при использовании имени образа в команде
+
java_prod
  
docker run ...
+
полное имя docker-образа будет следующим:
  
или при использовании имени образа в файле
+
vpupkin/java_prod
  
docker-compose.yaml
+
Ещё более полное имя docker-образа может быть таким:
  
инфраструктура docker подразумевает использование тега по умолчанию (latest), необходимо задать тег по умолчанию при задании имени образу перед публикацией его на портале hub.docker.com
+
vpupkin/java_prod:some_tag_name
  
Изменить имя docker-образа с
+
, где
  
  vpupkin/java_prod
+
  some_tag_name
  
на
+
это любое имя тега, которое может быть придумано создателем образа.
  
ivanov_ii/java_prod:latest
+
Обычно, для production-образов значением тега по умолчанию является:
  
можно командой (дополнительно уточнив в новом имени значение тега -- справа от двоеточия):
+
latest
  
docker tag vpupkin/java_prod ivanov_ii/java_prod:latest
+
Следовательно, если на портале hub.docker.com предполагается публиковать единственный вариант образа контейнера, то в полном имени образа будем использовать рекомендованный вариант тега. Тогда общий вид имени образа приобретёт следующий вид:
  
Результат переименования образа можно проверить командой:
+
vpupkin/java_prod:latest
  
docker images
+
===Изменение имени docker-образа===
  
В ответе можно наблюдать несколько образов с одинаковым IMAGE ID
+
Если в процессе выполнения практических работ 1-5 у docker-образа имя осталось шаблонным (т.е. в качестве пользователя остался собирательный образ пользователя -- vpupkin), то перед публикацией образа на hub.docker.com необходимо его изменить.
  
<pre>
+
Если ваш образ называется
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) можно удалить (при отсутствии контейнеров, запущенных на его базе!) командой:
+
vpupkin/java_prod
  
docker rmi vpupkin/java_prod
+
, а ваш настоящий аккаунт на hub.docker.com имеет логин:
  
===Решаемая задача===
+
ivanov_ii
 +
 
 +
, то прежде чем выполнять публикацию образа его необходимо переименовать. Новое имя образа может быть, например, таким:
  
Опубликовать подготовленный docker-образ, имеющий имя
+
ivanov_ii/java_prod
  
ivanov_ii/java_prod:latest
+
В целом, не имеет значения какое название образ будет иметь справа от символа
  
на hub.docker.com
+
/
  
Для этого необходимо иметь логин и пароль от учётной записи на портале hub.docker.com
+
Главное, не давать контейнеру названий, совпадающих с уже загруженными в hub.docker.com контейнерами под вашим именем пользователя (в данном случае -- под логином ivanov_ii).
 +
Строго говоря, значение тега справа от двоеточия в имени образа предназначено для того, чтобы у пользователя была возможность не придумывать новые названия для разновидностей docker-образа (при необходимости их публикации на портале), а просто тегировать эти названия.
  
===Публикация docker-образа===
+
Учитывая факт того, что в случае отсутствия имени тега (значения справа от двоеточия) у docker-образа при использовании имени образа в команде
  
Выполните аутентификацию на портале. Для этого в терминале (где обычно запускаете команды docker... и другие) выполните команду:
+
docker run ...
  
docker login
+
или при использовании имени образа в файле
  
В ответ будет выведен текстовый диалог, в котором необходимо ввести логин и пароль. В случае корректного ввода логина и пароля в конце диалога будет выведено сообщение
+
docker-compose.yaml
  
Login Succeeded
+
инфраструктура docker подразумевает использование тега по умолчанию (latest), необходимо задать тег по умолчанию при задании имени образу перед публикацией его на портале hub.docker.com
  
Полный текст диалога должен быть похож на этот:
+
Изменить имя docker-образа с
  
<pre>
+
vpupkin/java_prod
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.
+
ivanov_ii/java_prod:latest
Configure a credential helper to remove this warning. See
 
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
 
  
Login Succeeded
+
можно командой (дополнительно уточнив в новом имени значение тега -- справа от двоеточия):
</pre>
 
  
 +
docker tag vpupkin/java_prod ivanov_ii/java_prod:latest
  
После успешного логина для публикации образа выполните команду
+
Результат переименования образа можно проверить командой:
  
  docker push ivanov_ii/java_prod:latest
+
  docker images
  
Процедура публикации будет похожа на эту:
+
В ответе можно наблюдать несколько образов с одинаковым IMAGE ID
  
 
<pre>
 
<pre>
The push refers to repository [docker.io/ivanov_ii/java_prod]
+
REPOSITORY            TAG      IMAGE ID      CREATED        SIZE
e1640cc719ff: Pushed
+
ivanov_ii/java_prod   latest    82acd99eb61f  20 hours ago  1.09GB
6fb986383f38: Pushed
+
vpupkin/java_prod    latest   82acd99eb61f  20 hours ago  1.09GB
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>
 
</pre>
  
После завершения процедуры публикации можно проверить наличие образа на портале https://hub.docker.com в личном кабинете, загрузив страницу в браузере выполнив вход в систему.
+
При необходимости, образ с предыдущим тегом (vpupkin/java_prod) можно удалить (при отсутствии контейнеров, запущенных на его базе!) командой:
  
==Оптимизации==
+
docker rmi vpupkin/java_prod
  
===Оптимизация для контейнера в практической работе №2===
+
===Решаемая задача===
  
Для сборки приложения можно использовать компилятор Java, доступный в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:
+
Опубликовать подготовленный docker-образ, имеющий имя
  
<pre>
+
ivanov_ii/java_prod:latest
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>
 
  
Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством)
+
на hub.docker.com
  
затем на этапе клонирования проекта командой
+
Для этого необходимо иметь логин и пароль от учётной записи на портале hub.docker.com
  
git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter
+
===Публикация docker-образа===
  
нужно сменить ветку для использования кода, адаптированного под платформу Java-11 (вместо Java-19 по умолчанию)
+
Выполните аутентификацию на портале. Для этого в терминале (где обычно запускаете команды docker... и другие) выполните команду:
  
  git checkout jdk11
+
  docker login
  
 +
В ответ будет выведен текстовый диалог, в котором необходимо ввести логин и пароль. В случае корректного ввода логина и пароля в конце диалога будет выведено сообщение
  
Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере
+
Login Succeeded
Недостатки: более низкая версия платформы Java (11)
 
  
Также следует обратить внимание на то, что сборка контейнера производится на другом образе операционной системы (alt:p10) -- официальный образ производителя -- и набор устанавливаемых пакетов отличается от оригинального набора, описанного в практической работе №3.
+
Полный текст диалога должен быть похож на этот:
  
В остальном порядок выполнения практической работы не отличается от практической работы №3.
+
<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
  
Следует обратить внимание, что в операционной системе Alt для получения компилятора javac нужно установить пакет
+
Login Succeeded
 +
</pre>
  
java-11-openjdk-devel
 
  
, что и сделано в соответствюущей RUN-команде в Dockerfile. Также для целей сборки приложения установлены утилиты git и nano.
+
После успешного логина для публикации образа выполните команду
 +
 
 +
docker push ivanov_ii/java_prod:latest
 +
 
 +
Процедура публикации будет похожа на эту:
 +
 
 +
<pre>
 +
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 в личном кабинете, загрузив страницу в браузере выполнив вход в систему.
  
java-11-openjdk-devel nano git
+
==Загрузка образов Docker из архивного файла==
  
не нужны в образе для контейнера практической работы №3, следовательно на этапе выполнения практической работы №3 их нужно убрать из команды в Dockerfile
+
Скачать архивный файл
  
===Оптимизация для контейнера в практической работе №3===
+
wget https://wiki.nntc.nnov.ru/download/images.tar.xz
  
Для сборки образа с готовым приложением можно использовать Runtime-платформу Java (JRE), доступную в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:
+
Распаковать и загрузить образы в docker
  
<pre>
+
unxz -c images.tar.xz | docker load
FROM alt:p10
+
 
 +
==Оптимизации==
 +
 
 +
===Оптимизация для контейнера в практической работе №2===
 +
 
 +
Для сборки приложения можно использовать компилятор Java, доступный в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:
 +
 
 +
<pre>
 +
FROM alt:p10
 
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 
RUN apt-get update -q -y \
 
RUN apt-get update -q -y \
 
     && apt-get dist-upgrade -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 install java-11-openjdk-devel nano git java-11-openjdk libGL libgtk+3 libXxf86vm xorg-dri-swrast fonts-ttf-dejavu -q -y
    && apt-get autoclean \
+
</pre>
    && apt-get autoremove \
 
    && /bin/rm /var/cache/apt/archives/*.rpm
 
  
RUN adduser app
+
Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством)
  
RUN mkdir /opt/app
+
затем на этапе клонирования проекта командой
COPY app /opt/app
 
COPY startup.sh /
 
RUN chmod +x /startup.sh
 
  
USER app
+
git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter
  
CMD /startup.sh
+
нужно сменить ветку для использования кода, адаптированного под платформу Java-11 (вместо Java-19 по умолчанию)
</pre>
+
 
 +
git checkout jdk11
  
Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством. При чём -- только JRE, т.е. без компилятора javac. Компилятор для работы приложения -- не нужен).
 
  
 
Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере
 
Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере
Строка 1306: Строка 1340:
 
В остальном порядок выполнения практической работы не отличается от практической работы №3.
 
В остальном порядок выполнения практической работы не отличается от практической работы №3.
  
===Оптимизация композиции контейнеров в практической работе №5===
+
Следует обратить внимание, что в операционной системе Alt для получения компилятора javac нужно установить пакет
 +
 
 +
java-11-openjdk-devel
 +
 
 +
, что и сделано в соответствюущей RUN-команде в Dockerfile. Также для целей сборки приложения установлены утилиты git и nano.
 +
 
 +
Пакеты
 +
 
 +
java-11-openjdk-devel nano git
  
Для добавления к композе контейнера с веб-приложением phpmyadmin необходимо расширить набор сервисов в файле
+
не нужны в образе для контейнера практической работы №3, следовательно на этапе выполнения практической работы №3 их нужно убрать из команды в Dockerfile
  
docker-compose.yaml
+
===Оптимизация для контейнера в практической работе №3===
  
следующим образом
+
Для сборки образа с готовым приложением можно использовать Runtime-платформу Java (JRE), доступную в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:
  
 
<pre>
 
<pre>
version: '3.9'
+
FROM alt:p10
 
+
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
services:
+
RUN apt-get update -q -y \
  c1:
+
     && apt-get dist-upgrade -q -y \
     container_name: "c1"
+
     && apt-get install java-11-openjdk libGL libgtk+3 libXxf86vm xorg-dri-swrast fonts-ttf-dejavu -q -y \
     hostname: "c1"
+
     && apt-get autoclean \
     image: "mariadb"
+
     && apt-get autoremove \
     restart: "always"
+
     && /bin/rm /var/cache/apt/archives/*.rpm
     environment:
+
 
      MARIADB_ROOT_PASSWORD: "123321"
+
RUN adduser app
      MARIADB_DATABASE: "java_app_db"
 
      MARIADB_USER: "java_app_user"
 
      MARIADB_PASSWORD: "java_app_password"
 
    networks:
 
      - net_c1_c2
 
  
  c2:
+
RUN mkdir /opt/app
    container_name: "c2"
+
COPY app /opt/app
    hostname: "c2"
+
COPY startup.sh /
    image: "vpupkin/java_prod"
+
RUN chmod +x /startup.sh
    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:
+
USER app
    container_name: "c3"
 
    hostname: "c3"
 
    image: phpmyadmin
 
    restart: always
 
    ports:
 
      - 8080:80
 
    environment:
 
      - PMA_ARBITRARY=1
 
    networks:
 
      - net_c1_c2
 
  
 +
CMD /startup.sh
 +
</pre>
 +
 +
Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством. При чём -- только JRE, т.е. без компилятора javac. Компилятор для работы приложения -- не нужен).
  
networks:
+
Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере
  net_c1_c2:
+
Недостатки: более низкая версия платформы Java (11)
    name: net_c1_c2
+
 
 +
Также следует обратить внимание на то, что сборка контейнера производится на другом образе операционной системы (alt:p10) -- официальный образ производителя -- и набор устанавливаемых пакетов отличается от оригинального набора, описанного в практической работе №3.
 +
 
 +
В остальном порядок выполнения практической работы не отличается от практической работы №3.
  
</pre>
+
===Оптимизация композиции контейнеров в практической работе №5===
  
 +
Для добавления к композе контейнера с веб-приложением phpmyadmin необходимо расширить набор сервисов в файле
  
Относительно конфигурации, представленной в практической работе №5, был добавлен сервис c3:
+
docker-compose.yaml
  
 +
следующим образом
  
 
<pre>
 
<pre>
   c3:
+
version: '3.9'
     container_name: "c3"
+
 
     hostname: "c3"
+
services:
     image: phpmyadmin
+
   c1:
     restart: always
+
     container_name: "c1"
    ports:
+
     hostname: "c1"
      - 8080:80
+
     image: "mariadb"
 +
     restart: "always"
 
     environment:
 
     environment:
       - PMA_ARBITRARY=1
+
       MARIADB_ROOT_PASSWORD: "123321"
 +
      MARIADB_DATABASE: "java_app_db"
 +
      MARIADB_USER: "java_app_user"
 +
      MARIADB_PASSWORD: "java_app_password"
 
     networks:
 
     networks:
 
       - net_c1_c2
 
       - net_c1_c2
</pre>
 
  
который был подключен к той же сети, что и остальные контейнеры.
+
  c2:
 
+
    container_name: "c2"
У сервиса c3 экспортирован 80-й порт, на котором работает веб-приложение, на порт 8080 хостовой системы.
+
    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>
  
Следовательно, веб-приложение phpmyadmin можен быть запущена в браузере хостовой машины по адресу
+
 
 +
Относительно конфигурации, представленной в практической работе №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