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

Материал из wiki.nntc.nnov.ru
Перейти к навигации Перейти к поиску
(Создание файлов)
(Загрузка образов Docker из архивного файла)
 
(не показано 29 промежуточных версий этого же участника)
Строка 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 my_second_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_second_image
+
  docker run --rm -e USER_NAME=Maria my_first_image /bootstrap.sh
  
  docker run --rm -e USER_NAME=Petr my_second_image
+
  docker run --rm -e USER_NAME=Petr my_first_image /bootstrap.sh
  
  docker run --rm -e USER_NAME=Ekaterina my_second_image
+
  docker run --rm -e USER_NAME=Ekaterina my_first_image /bootstrap.sh
  
==[Практическая работа №2] Создание контейнера для разработки приложения на языке Java==
+
===Автоматически (посредством файла 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 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>
 
  
В конце этого этапа в рабочем каталоге должны быть файл:
+
====Запуск контейнера на базе образа====
  
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 attach java_dev
+
  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 8e5f4fd0a99b
+
В случае успешного создания контейнера в эмуляторе терминала приглашение должно смениться на такое:
  
 +
root@java-dev:/#
  
Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать
+
Проверка версии Java RE и компилятора должны возвращать примерно следующее:
  
exit
+
<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>
  
 +
Внимание! Сейчас вы внутри контейнера и можете командовать им! Если скомандовать
  
Однако есть способ отключиться от терминала и не завершить контейнер:
+
exit
  
Для этого нужно последовательно нажать сочетания клавиш:
+
, то контейнер завершит свою работу и найти и запустить его можно таким образом:
  
Ctrl + P
+
Найти:
  
затем
+
docker ps -a
  
Ctrl + Q
+
в ответе среди возможных прочих контейнеров должен быть такой:
  
 +
8e5f4fd0a99b        vpupkin/java_dev  "/bin/bash"        3 minutes ago      Exited (0) 6 seconds ago                      java_dev
  
После этого приглашение командной строки контейнера должно заменить приглашение хостовой системы.
+
Имя его в данном случае:
  
 +
java_dev
  
На этом этапе мы научились создавать образ контейнера и запускать контейнер на его базе.
+
Идентификатор его в данном случае:
  
===Сборка приложения на языке Java в docker-контейнере===
+
8e5f4fd0a99b
  
Перейдём в каталог
+
Остальное пока не важно, однако можно догадаться за что отвечают остальные параметры...
  
cd /root/src/
 
  
Склонируем проект приложения на Java
+
Запустить:
  
  git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter
+
  docker start java_dev
  
Перейдём в проект
+
или:
  
  cd simple-counter
+
  docker start 8e5f4fd0a99b
  
Исходя из рекомендаци в файле README.md выполним сборку проекта
+
Естественно, в конкретном случае идентификатор будет другой.
  
bash mvnw install
 
bash mvnw dependency:copy-dependencies
 
  
В случае успешной сборки в терминале котейнера долждно быть написано что-то похожее на это:
+
Подключиться к терминалу:
  
<pre>
+
docker attach java_dev
[INFO] ------------------------------------------------------------------------
 
[INFO] BUILD SUCCESS
 
[INFO] ------------------------------------------------------------------------
 
</pre>
 
  
На этом этам сборки приложения заврешён.
+
или
  
Теперь наша задача - запустить приложение прямо на хостовой машине (но выполняться оно будет в контейнере).
+
docker attach 8e5f4fd0a99b
  
===Запуск собранного приложения в 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
+
  exit
  
Для успешного запуска графического приложения, работающего в контейнере, с возможностью отображения графического интерфейса, в этой команде сделано две вещи:
+
, то контейнер завершит свою работу придётся опять читать выше по тексту как его запускать...
  
Первая: установлена (внутрь контейнера) переменная окружения
 
  
DISPLAY
+
Однако есть способ отключиться от терминала и не завершить контейнер:
  
равная значению аналогичной переменной окружения хостовой системы.
+
Для этого нужно последовательно нажать сочетания клавиш:
  
Вторая: проброшено устройство
+
Ctrl + P
  
/tmp/.X11-unix
+
затем
  
из хостовой системы в контейнер.
+
Ctrl + Q
  
Также добавлено монтирование каталога src для обмена файлами межу контейнером и хостовой системой, а также добавлена опция
 
  
--rm
+
После этого приглашение командной строки контейнера должно заменить приглашение хостовой системы.
  
которая уничтожает контейнер после его завершения (за данные мы не переживаем, они же лежат локально в каталоге src, который каждый раз монтируется при старте в новый контейнер).
 
  
 +
На этом этапе мы научились создавать образ контейнера и запускать контейнер на его базе.
  
Эта опция сюда добавлена, поскольку сама команда старта контейнера содержит в себе цель запускать именно оболочку /bin/bash для ручного тестирования запуска собранного приложения.
+
===Сборка приложения на языке Java в docker-контейнере===
  
Предполагается, что после такого тестирования контейнер не нужен и при выходе из него его логичнее всего автоматически удалять.
+
Перейдём в каталог
  
 +
cd /root/src/
  
Когда работа собранного приложения протестирована и есть понимание, что всё работает корректно, можно приступать к сборке образа для production-контейнера, в котором необходимо оставить необходимое и достаточное количество библиотек, необходимых только для запуска уже собранного приложения, а пакеты и утилиты, необходимые для сборки, не включать в результирующий образ.
+
Склонируем проект приложения на Java
  
Важный момент: В некоторых операционных системах может потребоваться выполнить команду
+
git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter
  
xhost +
+
Перейдём в проект
  
для разрешения подключения контейнера к графической оболочке X-сервера.
+
cd simple-counter
  
Тестовый запуск приложения можно выполнить командами:
+
Исходя из рекомендаци в файле README.md выполним сборку проекта
  
  cd /root/src/simple-counter/
+
  bash mvnw install
  java --module-path=target/dependency/ --add-modules javafx.controls,javafx.fxml -cp target/demo_up04-1.0-SNAPSHOT.jar com.example.demo_up04.DemoApplication
+
  bash mvnw dependency:copy-dependencies
  
===Отвечаем на главный вопрос?===
+
В случае успешной сборки в терминале котейнера долждно быть написано что-то похожее на это:
  
Вопрос звучит так:
+
<pre>
 +
[INFO] ------------------------------------------------------------------------
 +
[INFO] BUILD SUCCESS
 +
[INFO] ------------------------------------------------------------------------
 +
</pre>
  
Если мы уже собрали приложение, то нужно ли конечному пользователю инструменты для сборки приложения, которые были нужны в сборочном контейнере, и исходный код приложения?
+
На этом этам сборки приложения заврешён.
  
 +
Теперь наша задача - запустить приложение прямо на хостовой машине (но выполняться оно будет в контейнере).
  
Не нужны по нескольким причинам:
+
===Запуск собранного приложения в docker-контейнере на базе образа с JDK===
  
# Исходный чаще всего остаётся интеллектуальной собственностью компании-разработчика и не должен оказаться у заказчика
+
Запустим новый контейнер командой:
# Наличие на Production-системе компилятора какого-либо языка и/или каких-либо средств разработки является потенциальной уязвимостью системы
 
# Инструменты сборки и тестирования никогда не понадобятся конечному пользователю на  Production-системе, но всегда будут занимать место на файловой системе контейнера
 
  
Поэтому для конечного пользователя целесообразно создать новый образ, исключив оттуда всё лишнее и оставив лишь непосредственно готовое приложение.
+
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
  
Как это сделать -- см. в следующей практической работе.
+
Для успешного запуска графического приложения, работающего в контейнере, с возможностью отображения графического интерфейса, в этой команде сделано две вещи:
  
==[Практическая работа №3] Создание контейнера для запуска Java-приложения==
+
Первая: установлена (внутрь контейнера) переменная окружения
Откройте терминал хостовой машины. Создайте рабочий каталог
 
  
  mkdir pr03
+
  DISPLAY
  
Перейдите в рабочий каталог
+
равная значению аналогичной переменной окружения хостовой системы.
  
cd pr03
+
Вторая: проброшено устройство
  
===Создание файлов===
+
/tmp/.X11-unix
  
В рабочем каталоге создайте файл
+
из хостовой системы в контейнер.
  
Dockerfile_prod
+
Также добавлено монтирование каталога src для обмена файлами межу контейнером и хостовой системой, а также добавлена опция
  
по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):
+
--rm
  
<pre>
+
которая уничтожает контейнер после его завершения (за данные мы не переживаем, они же лежат локально в каталоге src, который каждый раз монтируется при старте в новый контейнер).
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
+
Эта опция сюда добавлена, поскольку сама команда старта контейнера содержит в себе цель запускать именно оболочку /bin/bash для ручного тестирования запуска собранного приложения.
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
+
Когда работа собранного приложения протестирована и есть понимание, что всё работает корректно, можно приступать к сборке образа для production-контейнера, в котором необходимо оставить необходимое и достаточное количество библиотек, необходимых только для запуска уже собранного приложения, а пакеты и утилиты, необходимые для сборки, не включать в результирующий образ.
  
CMD /startup.sh
+
Важный момент: В некоторых операционных системах может потребоваться выполнить команду
</pre>
 
  
Создайте каталог app в рабочем каталоге
+
  xhost +
   
 
mkdir app
 
  
Скопируйте исполняемый файл, полученный в предыдущей работе в рабочий каталог
+
для разрешения подключения контейнера к графической оболочке X-сервера.
  
/bin/cp -rf ../pr02/src/simple-counter/target app/
+
Тестовый запуск приложения можно выполнить командами:
  
Скачайте в рабочий каталог JDK версии 19.0.1. Это можно сделать командой (рекомендуется использовать в локальной сети колледжа)
+
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
  
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
+
Не нужны по нескольким причинам:
  
На этом этапе архив можно удалить командой
+
# Исходный код чаще всего остаётся интеллектуальной собственностью компании-разработчика и не должен оказаться у заказчика;
 +
# Наличие на Production-системе компилятора какого-либо языка и/или каких-либо средств разработки является потенциальной уязвимостью системы;
 +
# Инструменты сборки и тестирования никогда не понадобятся конечному пользователю на Production-системе, но всегда будут занимать место на файловой системе контейнера.
  
rm openjdk-19.0.1_linux-x64_bin.tar.gz
+
Поэтому для конечного пользователя целесообразно создать новый образ, исключив оттуда всё лишнее и оставив лишь непосредственно готовое приложение.
  
Создайте в рабочем каталоге файл
+
Как это сделать -- см. в следующей практической работе.
  
startup.sh
+
==[Практическая работа №3] Создание контейнера для запуска Java-приложения==
 +
Откройте терминал хостовой машины. Создайте рабочий каталог
  
со следующим содержимым
+
mkdir 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>
 
  
В конце этого этапа в рабочем каталоге должно быть два файла:
+
cd pr03
  
Dockerfile_prod
+
===Создание файлов===
startup.sh
 
  
И два каталога:
+
В рабочем каталоге создайте файл
  
  jdk-19.0.1
+
  Dockerfile_prod
app
 
  
===Создание образа контейнера===
+
по следующему шаблону (в файле нужно изменить имя и емэйл разработчика на собственное):
  
Далее в этом разделе будем исходить из условия, что ваш логин на https://hub.docker.com/ будет
+
<pre>
 
+
FROM alt:p10
vpupkin
+
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
 +
</pre>
  
Для создания Docker-образа (image) выполните команду:
+
Создайте каталог app в рабочем каталоге
 +
 +
mkdir app
  
docker build -t 'vpupkin/java_prod:latest' -f Dockerfile_prod .
+
Скопируйте исполняемый файл, полученный в предыдущей работе в рабочий каталог
  
 +
/bin/cp -r ../pr02/src/simple-counter/target app/
  
Для проверки существования созданного контейнера выполните команду:
+
Скачайте в рабочий каталог JDK версии 19.0.1. Это можно сделать командой (рекомендуется использовать в локальной сети колледжа)
  
  docker images
+
  wget https://wiki.nntc.nnov.ru/download/openjdk-19.0.1_linux-x64_bin.tar.gz
  
Среди текста ответа должна появиться строчка с новым контейнером:
+
или командой (при работе вне локальной сети колледжа)
  
  vpupkin/java_prod  latest              20bb2900074d        16 seconds ago      217MB
+
  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
Сравните размер контейнера с размером контейнера java_dev из предыдущей работы
 
  
===Запуск контейнера на базе образа===
+
На этом этапе архив можно удалить командой
  
Создадим каталог для обмена данными с контейнером
+
rm openjdk-19.0.1_linux-x64_bin.tar.gz
  
mkdir $HOME/data
+
Создайте в рабочем каталоге файл
  
На базе полученного образа запустите контейнер, пробросив внутрь контейнера локальный каталог хостовой машины:
+
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
+
со следующим содержимым
  
 +
<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
  
строчкой
+
И два каталога:
  
  CMD /bin/su -c "/startup.sh" app
+
  jdk-19.0.1
 +
app
  
Результатом запуска контейнера должно стать запущенное внутри контейнера графическое приложение с отображением графического интерфейса на хостовой машине.
+
===Создание образа контейнера===
  
При закрытии окна графического приложения контейнер будет завершён и будет доступен среди списка контейнеров
+
Далее в этом разделе будем исходить из условия, что ваш логин на https://hub.docker.com/ будет
  
  docker ps -a
+
  vpupkin
  
Повторный запуск уже существующего контейнера можно осуществить по имени контейнера командой:
+
а пароль
  
  docker start java_prod
+
  ну, вы сами знаете...
  
==[Практическая работа №4] Взаимодействие двух контейнеров по сети (ручной запуск)==
 
  
Задача: Запустить Java-приложение в контейнере с именем c2, который взаимодействует с базой данных Mariadb, запущенной в контейнере с именем c1
 
  
===Загрузка образа для контейнера с mariadb===
+
! Также стоит помнить, что в эмуляторе терминала находиться нужно в рабочем каталоге !
  
docker pull mariadb
 
  
===Создание сетевого моста===
+
Для создания Docker-образа (image) выполните команду:
  
  docker network create net_c1_c2
+
  docker build -t 'vpupkin/java_prod:latest' -f Dockerfile_prod .
  
Проверить список сетевых мостов можно командой
 
  
docker network list
+
Для проверки существования созданного контейнера выполните команду:
  
===Запуск контейнера c1 и подготовка базы данных===
+
docker images
  
Создать контейнер с базой данных 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
+
  vpupkin/java_prod  latest              20bb2900074d        16 seconds ago      217MB
  
Проверить корректность подключения к Mariadb с созданным пользователем к созданной базе данных (подключиться к консоли контейнера c1 и воспользоваться клиентом mysql)
 
  
  docker exec -it c1 /bin/bash
+
  ! Обратите внимание на размер контейнера !
 +
Сравните размер контейнера с размером контейнера java_dev из предыдущей работы
  
Внутри контейнера запустить клиент mysql с параметрами подключения к бд:
+
===Запуск контейнера на базе образа===
  
mysql -u java_app_user -pjava_app_password -h localhost java_app_db
+
Создадим каталог для обмена данными с контейнером
 
Выход из mysql и из контейнера
 
  
  exit
+
  mkdir $HOME/data
exit
 
  
===Запуск контейнера c2 с Java-приложением===
+
На базе полученного образа запустите контейнер, пробросив внутрь контейнера локальный каталог хостовой машины:
  
Запуск контейнера с Java-приложением производится аналогично запуску, подробно описанному в практической работе №3 с учётом ряда нюансов:
+
docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --mount source="$HOME/data",target=/home/app/data,type=bind --name=java_prod --hostname=java-prod vpupkin/java_prod
  
1. Необходимо учитывать, что имя запускаемого контейнера должно быть
 
  
с2
+
При запуске контейнера таким образом не указывается команда, т.к. она задаётся в файле
  
2. Необходимо учитывать, что имя хоста запускаемого контейнера должно быть
+
Dockerfile_prod
  
с2
+
строчкой
  
3. Необходимо учитывать, что для корректного подключения Java-приложения к базе данных, доступной в контейнере с именем_контейнера=именем_хоста=с1 необходимо при запуске контейнера с2 передать набор переменных окружения для настройки Java-приложения на работу с базой данных в контейнере c1
+
CMD /bin/su -c "/startup.sh" app
  
DB_HOST=c1
+
Результатом запуска контейнера должно стать запущенное внутри контейнера графическое приложение с отображением графического интерфейса на хостовой машине.
DB_PORT=3306
 
DB_NAME=java_app_db
 
DB_USER=java_app_user
 
DB_PASS=java_app_password
 
  
Пример команды для запуска контейнера c2 (запуск контейнера осуществляется на базе образа, созданного в практической работе №3)
+
При закрытии окна графического приложения контейнер будет завершён и будет доступен среди списка контейнеров
  
  docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --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
+
  docker ps -a
  
При необходимости монтирования директорий хостовой машины в контейнер также могут быть использованы дополнительные параметры, как было показано в примере запуска контейнера в практической работе №3 с параметром
+
Повторный запуск уже существующего контейнера можно осуществить по имени контейнера командой:
  
  --mount source="$HOME/data",target=/home/app/data,type=bind
+
  docker start java_prod
  
В данном примере этот параметр опущен, т.к. тестовое приложение не имеет функций чтения и записи файлов.
+
==[Практическая работа №4] Взаимодействие двух контейнеров по сети (ручной запуск)==
  
===Самостоятельное задание===
+
Задача: Запустить Java-приложение в контейнере с именем c2, который взаимодействует с базой данных Mariadb, запущенной в контейнере с именем c1
  
====Подготовка====
+
===Загрузка образа для контейнера с mariadb===
  
Придумать уникальный префикс для именования названий, завязанный на фамилию и инициалы обучающегося.
+
docker pull mariadb
  
Например, для обучающегося
+
===Создание сетевого моста===
  
  Иванов Иван Иванович
+
  docker network create net_c1_c2
  
Префикс (<prefix>) будет состоять из фамилии и инициалов
+
Проверить список сетевых мостов можно командой
  
  ivanov_ii
+
  docker network list
  
Тогда в приведённых ниже примерах необходимо
+
===Запуск контейнера c1 и подготовка базы данных===
  
<prefix>
+
Создать контейнер с базой данных 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
  
ivanov_ii
+
Проверить корректность подключения к Mariadb с созданным пользователем к созданной базе данных (подключиться к консоли контейнера c1 и воспользоваться клиентом mariadb)
  
Например
+
docker exec -it c1 /bin/bash
  
ivanov_ii_container_db
+
Внутри контейнера запустить клиент mariadb (ранее это был клиент mysql) с параметрами подключения к бд:
  
 +
mariadb -u java_app_user -pjava_app_password -h localhost java_app_db
 +
 +
Выход из mariadb и затем из контейнера
  
====Выполнение задания====
+
exit
 +
exit
  
Используя справку по docker и набор выполненных практических работ запустить тестовое Java-приложение в двух контейнерах, аналогичных контейнерам с1 и с2, исходя из следующих параметров:
+
===Запуск контейнера c2 с Java-приложением===
  
0. Сетевой мост должен иметь имя
+
Запуск контейнера с Java-приложением производится аналогично запуску, подробно описанному в практической работе №3 с учётом ряда нюансов:
  
net_<prefix>
+
1. Необходимо учитывать, что имя запускаемого контейнера должно быть
  
1. Контейнер с базой данных должен иметь имя
+
с2
  
<prefix>_container_db
+
2. Необходимо учитывать, что имя хоста запускаемого контейнера должно быть
  
и хостовое имя
+
с2
  
<prefix>-container-db
+
3. Необходимо учитывать, что для корректного подключения Java-приложения к базе данных, доступной в контейнере с именем_контейнера=именем_хоста=с1 необходимо при запуске контейнера с2 передать набор переменных окружения для настройки Java-приложения на работу с базой данных в контейнере c1
  
2. Контейнер с Java-приложением должен иметь имя
+
DB_HOST=c1
 +
DB_PORT=3306
 +
DB_NAME=java_app_db
 +
DB_USER=java_app_user
 +
DB_PASS=java_app_password
  
<prefix>_container_app
+
Пример команды для запуска контейнера c2 (запуск контейнера осуществляется на базе образа, созданного в практической работе №3)
  
и хостовое имя
+
Не забудем про
  
  <prefix>-container-app
+
  xhost +
  
3. База данных должна иметь название
+
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
  
<prefix>_application_db
+
При необходимости монтирования директорий хостовой машины в контейнер также могут быть использованы дополнительные параметры, как было показано в примере запуска контейнера в практической работе №3 с параметром
  
имя пользователя
+
--mount source="$HOME/data",target=/home/app/data,type=bind
  
<prefix>_application_user
+
В данном примере этот параметр опущен, т.к. тестовое приложение не имеет функций чтения и записи файлов.
  
пароль
+
===Самостоятельное задание===
  
<prefix>_applicationPassw0rd123
+
====Подготовка====
  
Ход работы отразить в отчёте по практической работе №4
+
Придумать уникальный префикс для именования названий, завязанный на фамилию и инициалы обучающегося.
  
==[Практическая работа №5] Взаимодействие двух контейнеров по сети (docker-compose)==
+
Например, для обучающегося
  
===Предисловие===
+
Иванов Иван Иванович
  
Решаемая в данной практической работе задача аналогична задаче из практической работы №4. Отличия состоят лишь в том, что в практической работе №4 запуск двух контейнеров, взаимодействующих между собой внутри изолированной сети, осуществляется вручную, путём выполнения команд:
+
Префикс (<prefix>) будет состоять из фамилии и инициалов
  
  docker run ...
+
  ivanov_ii
  
Для автоматизации запуска приложений, компоненты которых разделены по контейнерам (их (приложения в контейнерах) ещё называют микросервисами) может быть использован инструмент:
+
Тогда в приведённых ниже примерах необходимо
  
  docker-compose
+
  <prefix>
  
Инструмент docker-compose (смысл названия можно перевести как "композиция из докер контейнеров") предназначен для того, чтобы автоматически запустить несколько docker-контейнеров в одном контексте (как правило, под контекстом подразумевается общая сеть, изолированная от хостовой системы но доступная для всех контейнеров композиции (как говорят DevOps-инженеры -- "композы")).
+
заменять на
  
В практической работе №2 мы изучали два способа создания docker-образа: ручной и автоматический.
+
ivanov_ii
  
Ручной способ подразумевал создание контейнера на базе стандартного образа, выполнение ряда действий внутри этого контейнера вручную, с последующим созданием образа на базе изменённого вручную контейнера. В результате получался новый образ, на базе которого можно запускать новые контейнеры.
+
Например
  
Автоматический способ подразумевал решение аналогичной задачи, но без участия пользователя. Т.е. пользователь один раз описывал файл (Dockerfile), который включал в себя все необходимые команды (которые в ручном режиме пользователь выполнял вручную) и директивы, которых минимально необходимо и достаточно для сборки образа в автоматическом режиме. После того, как был подготовлен Dockerfile, на его базе командой:
+
ivanov_ii_container_db
  
docker build...
 
  
производилась сборка образа
+
====Выполнение задания====
  
 +
Используя справку по docker и набор выполненных практических работ запустить тестовое Java-приложение в двух контейнерах, аналогичных контейнерам с1 и с2, исходя из следующих параметров:
  
Между ручным запуском двух контейнеров, описанным в практической работе №4, и автоматическим запуском композиции из докер контейнеров (композы), описываемой в этой практической работе, можно провести такую же аналогию, как между созданием образа контейнера вручную и созданием образа контейнера автоматически. Два этих способа (ручной и автоматический) объединяет наличие специального конфигурационного файла. В случае с автоматической сборкой docker-образа это файл:
+
0. Сетевой мост должен иметь имя
  
  Dockerfile
+
  net_<prefix>
  
, в случае же с автоматическим запуском нескольких контейнеров в композе -- это файл:
+
1. Контейнер с базой данных должен иметь имя
  
  docker-compose.yaml
+
  <prefix>_container_db
  
Для того, чтобы запустить любую композицию контейнеров, необходимо:
+
и хостовое имя
  
1. Сконфигурировать файл
+
<prefix>-container-db
  
docker-compose.yaml
+
2. Контейнер с Java-приложением должен иметь имя
  
2. Выполнить запуск композы командой
+
<prefix>_container_app
  
docker-compose up ...
+
и хостовое имя
  
===Установка docker-compose===
+
<prefix>-container-app
  
В хостовой системе откройте терминал и выполните команду для получения доступа под суперпользователем root
+
3. База данных должна иметь название
  
  su -
+
  <prefix>_application_db
  
Введите пароль от суперпользователя. Приглашение должно смениться на суперпользовательское и заканчиваться символом решётки. В этом режиме выполните команду установки пакета из репозитория:
+
имя пользователя
  
  apt-get install docker-compose -y
+
  <prefix>_application_user
  
При необходимости, перед выполнением этой команды можно выполнить команду обновления базы данных пакетов в репозитории:
+
пароль
  
  apt-get update
+
  <prefix>_applicationPassw0rd123
 +
 
 +
Ход работы отразить в отчёте по практической работе №4
 +
 
 +
==[Практическая работа №5] Взаимодействие двух контейнеров по сети (docker compose)==
  
===Практика===
+
===Предисловие===
  
Создайте рабочий каталог и перейдите в него
+
Решаемая в данной практической работе задача аналогична задаче из практической работы №4. Отличия состоят лишь в том, что в практической работе №4 запуск двух контейнеров, взаимодействующих между собой внутри изолированной сети, осуществляется вручную, путём выполнения команд:
  
  mkdir compose_с1_с2
+
  docker run ...
cd compose_с1_с2
 
  
Создайте файл
+
Для автоматизации запуска приложений, компоненты которых разделены по контейнерам (их (приложения в контейнерах) ещё называют микросервисами) может быть использован инструмент:
  
  docker-compose.yaml
+
  docker compose
  
со следующим содержимым
+
Инструмент docker compose (смысл названия можно перевести как "композиция из докер контейнеров") предназначен для того, чтобы автоматически запустить несколько docker-контейнеров в одном контексте (как правило, под контекстом подразумевается общая сеть, изолированная от хостовой системы но доступная для всех контейнеров композиции (как говорят DevOps-инженеры -- "композы")).
  
<pre>
+
В практической работе №2 мы изучали два способа создания docker-образа: ручной и автоматический.
version: '3.9'
+
 
 +
Ручной способ подразумевал создание контейнера на базе стандартного образа, выполнение ряда действий внутри этого контейнера вручную, с последующим созданием образа на базе изменённого вручную контейнера. В результате получался новый образ, на базе которого можно запускать новые контейнеры.
 +
 
 +
Автоматический способ подразумевал решение аналогичной задачи, но без участия пользователя. Т.е. пользователь один раз описывал файл (Dockerfile), который включал в себя все необходимые команды (которые в ручном режиме пользователь выполнял вручную) и директивы, которых минимально необходимо и достаточно для сборки образа в автоматическом режиме. После того, как был подготовлен Dockerfile, на его базе командой:
 +
 
 +
docker build...
 +
 
 +
производилась сборка образа
  
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:
+
Между ручным запуском двух контейнеров, описанным в практической работе №4, и автоматическим запуском композиции из докер контейнеров (композы), описываемой в этой практической работе, можно провести такую же аналогию, как между созданием образа контейнера вручную и созданием образа контейнера автоматически. Два этих способа (ручной и автоматический) объединяет наличие специального конфигурационного файла. В случае с автоматической сборкой docker-образа это файл:
    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:
+
Dockerfile
  net_c1_c2:
 
    name: net_c1_c2
 
</pre>
 
  
 +
, в случае же с автоматическим запуском нескольких контейнеров в композе -- это файл:
  
В результате в рабочем каталоге должен быть файл:
+
docker-compose.yaml
  
docker-compose.yaml
+
Для того, чтобы запустить любую композицию контейнеров, необходимо:
  
Для запуска композиции выполните в рабочем каталоге команду
+
1. Сконфигурировать файл
  
  docker-compose up -d
+
  docker-compose.yaml
  
В результате по описанной в файле docker-compose.yaml схеме сервисов будут запущены два контейнера: с1 и с2. В том числе из контейнера с2 будет запущено графическое приложение, которое будет работать с базой данных, запущенной в контейнере с1.
+
2. Выполнить запуск композы командой
  
====Возможные проблемы и их решения====
+
docker compose up ...
  
Проблема №1: не запускается графический интерфейс Java-приложения.
+
===Практика===
Решение: Открыть терминал хостовой системы и выполнить в нём команду для разрешения подключения к графической системы извне (в частности -- из контейнера):
 
  
xhost +
+
Создайте рабочий каталог и перейдите в него
  
Проблема №2: Java-приложение не может подключиться к базе данных.
+
mkdir compose_с1_с2
Решение: Повторно запустить контейнер c2. При первом запуске композы в контейнере c1 сервис базы данных не успевает запуститься к моменту, когда в контейнере c2 стартует Java-приложение. Поэтому приложение показывает ошибку. Когда окно приложение закрывается -- контейнер c2 прекращает свою работу, однако контейнер c1 по прежнему работает (и в нём с высокой долей вероятности уже запустилась СУБД). Поэтому повторный запуск контейнера c2 запустит Java-приложение, в котором уже не будет ошибки подключения к базе данных (конечно, при условии, что всё верно настроено).
+
cd compose_с1_с2
  
====Работа с контейнерами в контексте docker-compose====
+
Создайте файл
 
 
Если мы находимся в каталоге с файлом (Это важно! Все команды этого раздела актуальны, если соблюдается простое правило -- мы стоим в каталоге с этим файлом):
 
  
 
  docker-compose.yaml
 
  docker-compose.yaml
  
то для упрощения работы с контейнерами (сервисами микросервисной архитектуры), входящими в состав композы, можно вместо команды
+
со следующим содержимым
  
docker
+
<pre>
 +
version: '3.9'
  
использовать команду
+
services:
 
+
  c1:
docker-compose
+
    container_name: "c1"
 
+
    hostname: "c1"
В случае с нашей композой сервисы имеют названия c1 и с2, следовательно, для их остановки можно применять команды:
+
    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 stop c1
+
  c2:
 +
    container_name: "c2"
 +
    hostname: "c2"
 +
    image: "vpupkin/java_prod"
 +
    restart: "no"
 +
    environment:
 +
      DISPLAY: "$DISPLAY"
 +
      DB_HOST: "c1"
 +
      DB_PORT: "3306"
 +
      DB_NAME: "java_app_db"
 +
      DB_USER: "java_app_user"
 +
      DB_PASS: "java_app_password"
 +
    volumes:
 +
      - /tmp/.X11-unix:/tmp/.X11-unix
 +
    networks:
 +
      - net_c1_c2
  
или
+
networks:
 +
  net_c1_c2:
 +
    name: net_c1_c2
 +
</pre>
  
docker-compose stop c2
 
  
а для остановки всей композы -- команду:
+
В результате в рабочем каталоге должен быть файл:
  
  docker-compose stop
+
  docker-compose.yaml
  
а для запуска, соответственно
+
Для запуска композиции выполните в рабочем каталоге команду
  
  docker-compose start c1
+
  docker compose up -d
  
или
+
В результате по описанной в файле docker-compose.yaml схеме сервисов будут запущены два контейнера: с1 и с2. В том числе из контейнера с2 будет запущено графическое приложение, которое будет работать с базой данных, запущенной в контейнере с1.
  
docker-compose start c2
+
====Возможные проблемы и их решения====
  
а для запуска всей композы -- команду:
+
Проблема №1: не запускается графический интерфейс Java-приложения.
 +
Решение: Открыть терминал хостовой системы и выполнить в нём команду для разрешения подключения к графической системы извне (в частности -- из контейнера):
  
  docker-compose start
+
  xhost +
  
 +
Проблема №2: Java-приложение не может подключиться к базе данных.
 +
Решение: Повторно запустить контейнер c2. При первом запуске композы в контейнере c1 сервис базы данных не успевает запуститься к моменту, когда в контейнере c2 стартует Java-приложение. Поэтому приложение показывает ошибку. Когда окно приложение закрывается -- контейнер c2 прекращает свою работу, однако контейнер c1 по прежнему работает (и в нём с высокой долей вероятности уже запустилась СУБД). Поэтому повторный запуск контейнера c2 запустит Java-приложение, в котором уже не будет ошибки подключения к базе данных (конечно, при условии, что всё верно настроено).
  
Для развёртывания (поднятия -- up) композы выше использовалась команда:
+
====Работа с контейнерами в контексте docker compose====
  
docker-compose up -d
+
Если мы находимся в каталоге с файлом (Это важно! Все команды этого раздела актуальны, если соблюдается простое правило -- мы стоим в каталоге с этим файлом):
  
 +
docker-compose.yaml
  
Существует обратная операция, которую условно можно назвать свёртыванием (опускания -- down) композы. Для этого может быть использована команда:
+
то для упрощения работы с контейнерами (сервисами микросервисной архитектуры), входящими в состав композы, можно вместо команды
  
  docker-compose down
+
  docker
  
Выполнение этой команды приводит к остановке и удалению всех контейнеров композы. При этом образы остаются в системе.
+
использовать команду
  
После операции свёртывания композы в системе остаются занятые виртуальные диски, которые резервируются для контейнеров в момент запуска композы. Для очистки этих дисков, а следовательно для увеличения свободного места на диске, можно выполнить команду:
+
docker compose
  
docker volume prune
+
В случае с нашей композой сервисы имеют названия c1 и с2, следовательно, для их остановки можно применять команды:
  
Эта команда удалит все не занятые контейнерами виртуальные диски (volumes) подсистемы docker.
+
docker compose stop c1
  
 +
или
  
Также посредством команды
+
docker compose stop c2
  
docker-compose
+
а для остановки всей композы -- команду:
  
помимо остановки и запуска контейнеров можно выполнять другие действия над контенерами композы. Например, просмотр журналов (логов) и другие.
+
docker compose stop
  
 +
а для запуска, соответственно
  
Изучите справочную систему команды
+
docker compose start c1
  
docker-compose
+
или
  
для ознакомления с другим её функционалом.
+
docker compose start c2
  
===Самостоятельное задание===
+
а для запуска всей композы -- команду:
  
====Подготовка====
+
docker compose start
  
Придумать уникальный префикс для именования названий, завязанный на фамилию и инициалы обучающегося.
 
  
Например, для обучающегося
+
Для развёртывания (поднятия -- up) композы выше использовалась команда:
  
  Иванов Иван Иванович
+
  docker compose up -d
  
Префикс (<prefix>) будет состоять из фамилии и инициалов
 
  
ivanov_ii
+
Существует обратная операция, которую условно можно назвать свёртыванием (опускания -- down) композы. Для этого может быть использована команда:
  
Тогда в приведённых ниже примерах необходимо
+
docker compose down
  
<prefix>
+
Выполнение этой команды приводит к остановке и удалению всех контейнеров композы. При этом образы остаются в системе.
  
заменять на
+
После операции свёртывания композы в системе остаются занятые виртуальные диски, которые резервируются для контейнеров в момент запуска композы. Для очистки этих дисков, а следовательно для увеличения свободного места на диске, можно выполнить команду:
  
  ivanov_ii
+
  docker volume prune
  
Например
+
Эта команда удалит все не занятые контейнерами виртуальные диски (volumes) подсистемы docker.
  
ivanov_ii_container_db
 
  
 +
Также посредством команды
  
====Выполнение задания====
+
docker compose
  
Используя справку по docker, docker-compose и набор выполненных практических работ запустить тестовое Java-приложение в композиции из двух контейнеров, аналогичных контейнерам с1 и с2, описанных в практической работе №5, исходя из следующих параметров:
+
помимо остановки и запуска контейнеров можно выполнять другие действия над контенерами композы. Например, просмотр журналов (логов) и другие.
  
0. Сеть должна иметь имя
 
  
net_<prefix>
+
Изучите справочную систему команды
  
1. Контейнер с базой данных должен иметь имя
+
docker compose
  
<prefix>_container_db
+
для ознакомления с другим её функционалом.
  
и хостовое имя
+
===Самостоятельное задание===
  
<prefix>-container-db
+
====Подготовка====
  
2. Контейнер с Java-приложением должен иметь имя
+
Придумать уникальный префикс для именования названий, завязанный на фамилию и инициалы обучающегося.
  
<prefix>_container_app
+
Например, для обучающегося
  
и хостовое имя
+
Иванов Иван Иванович
  
<prefix>-container-app
+
Префикс (<prefix>) будет состоять из фамилии и инициалов
  
3. База данных должна иметь название
+
ivanov_ii
  
<prefix>_application_db
+
Тогда в приведённых ниже примерах необходимо
  
имя пользователя
+
<prefix>
  
<prefix>_application_user
+
заменять на
  
пароль
+
ivanov_ii
  
<prefix>_applicationPassw0rd123
+
Например
  
На основе этих данных должен быть создан файл
+
ivanov_ii_container_db
  
docker-compose.yaml
 
  
а ход работы по его созданию и процедуре запуска работоспособной композы должен быть отражён в отчёте по практической работе №5
+
====Выполнение задания====
  
==[Практическая работа №6] Загрузка образа на hub.docker.com==
+
Используя справку по docker, docker-compose и набор выполненных практических работ запустить тестовое Java-приложение в композиции из двух контейнеров, аналогичных контейнерам с1 и с2, описанных в практической работе №5, исходя из следующих параметров:
  
===Исходные данные===
+
0. Сеть должна иметь имя
  
У нас есть docker-образ с Java-приложением. Скорее всего он называется
+
net_<prefix>
  
vpupkin/java_prod
+
1. Контейнер с базой данных должен иметь имя
  
В практических работах 1-5 изучение работы с docker и docker-compose осуществлялось исходя из идеи о том, что в будущем для выгрузки docker-образов на hub.docker.com имя образа должно обязательно содержать префикс в виде логина на портале hub.docker.com, отделённый от имени самого образа символом
+
<prefix>_container_db
  
/
+
и хостовое имя
  
В общем виде имя docker-образа, пригодного для загрузки на портал hub.docker.com выглядит так:
+
<prefix>-container-db
  
<username>/<imagename>:<tag>
+
2. Контейнер с Java-приложением должен иметь имя
  
Например, для пользователя с логином
+
<prefix>_container_app
  
vpupkin
+
и хостовое имя
  
и смысловым названием контейнера с Java-приложением:
+
<prefix>-container-app
  
java_prod
+
3. База данных должна иметь название
  
полное имя docker-образа будет следующим:
+
<prefix>_application_db
  
vpupkin/java_prod
+
имя пользователя
  
Ещё более полное имя docker-образа может быть таким:
+
<prefix>_application_user
  
vpupkin/java_prod:some_tag_name
+
пароль
  
, где
+
<prefix>_applicationPassw0rd123
  
some_tag_name
+
На основе этих данных должен быть создан файл
  
это любое имя тега, которое может быть придумано создателем образа.
+
docker-compose.yaml
  
Обычно, для production-образов значением тега по умолчанию является:
+
а ход работы по его созданию и процедуре запуска работоспособной композы должен быть отражён в отчёте по практической работе №5
  
latest
+
==[Практическая работа №6] Загрузка образа на hub.docker.com==
  
Следовательно, если на портале hub.docker.com предполагается публиковать единственный вариант образа контейнера, то в полном имени образа будем использовать рекомендованный вариант тега. Тогда общий вид имени образа приобретёт следующий вид:
+
===Исходные данные===
  
vpupkin/java_prod:latest
+
У нас есть docker-образ с Java-приложением. Скорее всего он называется
  
===Изменение имени docker-образа===
+
vpupkin/java_prod
  
Если в процессе выполнения практических работ 1-5 у docker-образа имя осталось шаблонным (т.е. в качестве пользователя остался собирательный образ пользователя -- vpupkin), то перед публикацией образа на hub.docker.com необходимо его изменить.
+
В практических работах 1-5 изучение работы с docker и docker-compose осуществлялось исходя из идеи о том, что в будущем для выгрузки docker-образов на hub.docker.com имя образа должно обязательно содержать префикс в виде логина на портале hub.docker.com, отделённый от имени самого образа символом
  
Если ваш образ называется
+
/
  
vpupkin/java_prod
+
В общем виде имя docker-образа, пригодного для загрузки на портал hub.docker.com выглядит так:
  
, а ваш настоящий аккаунт на hub.docker.com имеет логин:
+
<username>/<imagename>:<tag>
  
ivanov_ii
+
Например, для пользователя с логином
  
, то прежде чем выполнять публикацию образа его необходимо переименовать. Новое имя образа может быть, например, таким:
+
vpupkin
  
ivanov_ii/java_prod
+
и смысловым названием контейнера с Java-приложением:
  
В целом, не имеет значения какое название образ будет иметь справа от символа
+
java_prod
  
/
+
полное имя docker-образа будет следующим:
  
Главное, не давать контейнеру названий, совпадающих с уже загруженными в hub.docker.com контейнерами под вашим именем пользователя (в данном случае -- под логином ivanov_ii).
+
vpupkin/java_prod
Строго говоря, значение тега справа от двоеточия в имени образа предназначено для того, чтобы у пользователя была возможность не придумывать новые названия для разновидностей docker-образа (при необходимости их публикации на портале), а просто тегировать эти названия.
 
  
Учитывая факт того, что в случае отсутствия имени тега (значения справа от двоеточия) у docker-образа при использовании имени образа в команде
+
Ещё более полное имя docker-образа может быть таким:
  
  docker run ...
+
  vpupkin/java_prod:some_tag_name
  
или при использовании имени образа в файле
+
, где
  
  docker-compose.yaml
+
  some_tag_name
  
инфраструктура docker подразумевает использование тега по умолчанию (latest), необходимо задать тег по умолчанию при задании имени образу перед публикацией его на портале hub.docker.com
+
это любое имя тега, которое может быть придумано создателем образа.
  
Изменить имя docker-образа с
+
Обычно, для production-образов значением тега по умолчанию является:
  
  vpupkin/java_prod
+
  latest
  
на
+
Следовательно, если на портале hub.docker.com предполагается публиковать единственный вариант образа контейнера, то в полном имени образа будем использовать рекомендованный вариант тега. Тогда общий вид имени образа приобретёт следующий вид:
  
  ivanov_ii/java_prod:latest
+
  vpupkin/java_prod:latest
  
можно командой (дополнительно уточнив в новом имени значение тега -- справа от двоеточия):
+
===Изменение имени docker-образа===
  
docker tag vpupkin/java_prod ivanov_ii/java_prod:latest
+
Если в процессе выполнения практических работ 1-5 у docker-образа имя осталось шаблонным (т.е. в качестве пользователя остался собирательный образ пользователя -- vpupkin), то перед публикацией образа на hub.docker.com необходимо его изменить.
  
Результат переименования образа можно проверить командой:
+
Если ваш образ называется
  
  docker images
+
  vpupkin/java_prod
  
В ответе можно наблюдать несколько образов с одинаковым IMAGE ID
+
, а ваш настоящий аккаунт на hub.docker.com имеет логин:
  
<pre>
+
ivanov_ii
REPOSITORY            TAG      IMAGE ID      CREATED        SIZE
 
ivanov_ii/java_prod  latest    82acd99eb61f  20 hours ago  1.09GB
 
vpupkin/java_prod    latest    82acd99eb61f  20 hours ago  1.09GB
 
</pre>
 
  
При необходимости, образ с предыдущим тегом (vpupkin/java_prod) можно удалить (при отсутствии контейнеров, запущенных на его базе!) командой:
+
, то прежде чем выполнять публикацию образа его необходимо переименовать. Новое имя образа может быть, например, таким:
  
  docker rmi vpupkin/java_prod
+
  ivanov_ii/java_prod
  
===Решаемая задача===
+
В целом, не имеет значения какое название образ будет иметь справа от символа
  
Опубликовать подготовленный docker-образ, имеющий имя
+
/
  
ivanov_ii/java_prod:latest
+
Главное, не давать контейнеру названий, совпадающих с уже загруженными в hub.docker.com контейнерами под вашим именем пользователя (в данном случае -- под логином ivanov_ii).
 +
Строго говоря, значение тега справа от двоеточия в имени образа предназначено для того, чтобы у пользователя была возможность не придумывать новые названия для разновидностей docker-образа (при необходимости их публикации на портале), а просто тегировать эти названия.
  
на hub.docker.com
+
Учитывая факт того, что в случае отсутствия имени тега (значения справа от двоеточия) у docker-образа при использовании имени образа в команде
  
Для этого необходимо иметь логин и пароль от учётной записи на портале hub.docker.com
+
docker run ...
  
===Публикация docker-образа===
+
или при использовании имени образа в файле
  
Выполните аутентификацию на портале. Для этого в терминале (где обычно запускаете команды docker... и другие) выполните команду:
+
docker-compose.yaml
  
docker login
+
инфраструктура docker подразумевает использование тега по умолчанию (latest), необходимо задать тег по умолчанию при задании имени образу перед публикацией его на портале hub.docker.com
  
В ответ будет выведен текстовый диалог, в котором необходимо ввести логин и пароль. В случае корректного ввода логина и пароля в конце диалога будет выведено сообщение
+
Изменить имя docker-образа с
  
  Login Succeeded
+
  vpupkin/java_prod
  
Полный текст диалога должен быть похож на этот:
+
на
  
<pre>
+
ivanov_ii/java_prod:latest
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
 
Username: ivanov_ii
 
Password:
 
WARNING! Your password will be stored unencrypted in /home/student/.docker/config.json.
 
Configure a credential helper to remove this warning. See
 
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
 
  
Login Succeeded
+
можно командой (дополнительно уточнив в новом имени значение тега -- справа от двоеточия):
</pre>
 
  
 +
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
  
java-11-openjdk-devel nano git
+
Процедура публикации будет похожа на эту:
  
не нужны в образе для контейнера практической работы №3, следовательно на этапе выполнения практической работы №3 их нужно убрать из команды в Dockerfile
+
<pre>
 
+
The push refers to repository [docker.io/ivanov_ii/java_prod]
===Оптимизация для контейнера в практической работе №3===
+
e1640cc719ff: Pushed
 +
6fb986383f38: Pushed
 +
fbf95f9f9b64: Pushed
 +
9e9e19c988d7: Pushed
 +
fa67c5190d97: Pushed
 +
2b1db325894b: Pushed
 +
60bdc4ff8a54: Mounted from library/alt
 +
9a03b2bc42d8: Mounted from library/alt
 +
latest: digest: sha256:e75a567439afb64a9d3b5b119650e91775e7eb1d9345f5171fefba0cfe18aea3 size: 1990
 +
</pre>
 +
 
 +
После завершения процедуры публикации можно проверить наличие образа на портале https://hub.docker.com в личном кабинете, загрузив страницу в браузере выполнив вход в систему.
 +
 
 +
==Загрузка образов Docker из архивного файла==
 +
 
 +
Скачать архивный файл
 +
 
 +
wget https://wiki.nntc.nnov.ru/download/images.tar.xz
 +
 
 +
Распаковать и загрузить образы в docker
 +
 
 +
unxz -c images.tar.xz | docker load
 +
 
 +
==Оптимизации==
 +
 
 +
===Оптимизация для контейнера в практической работе №2===
  
Для сборки образа с готовым приложением можно использовать Runtime-платформу Java (JRE), доступную в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:
+
Для сборки приложения можно использовать компилятор Java, доступный в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:
  
 
<pre>
 
<pre>
Строка 1280: Строка 1319:
 
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
+
Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством)
  
RUN adduser app
+
затем на этапе клонирования проекта командой
  
RUN mkdir /opt/app
+
git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter
COPY app /opt/app
 
COPY startup.sh /
 
RUN chmod +x /startup.sh
 
  
USER app
+
нужно сменить ветку для использования кода, адаптированного под платформу Java-11 (вместо Java-19 по умолчанию)
  
CMD /startup.sh
+
git checkout jdk11
</pre>
 
  
Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством. При чём -- только JRE, т.е. без компилятора javac. Компилятор для работы приложения -- не нужен).
 
  
 
Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере
 
Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере
Строка 1306: Строка 1340:
 
В остальном порядок выполнения практической работы не отличается от практической работы №3.
 
В остальном порядок выполнения практической работы не отличается от практической работы №3.
  
===Оптимизация композиции контейнеров в практической работе №5===
+
Следует обратить внимание, что в операционной системе Alt для получения компилятора javac нужно установить пакет
  
Для добавления к композе контейнера с веб-приложением phpmyadmin необходимо расширить набор сервисов в файле
+
java-11-openjdk-devel
  
docker-compose.yaml
+
, что и сделано в соответствюущей RUN-команде в Dockerfile. Также для целей сборки приложения установлены утилиты git и nano.
  
следующим образом
+
Пакеты
 +
 
 +
java-11-openjdk-devel nano git
 +
 
 +
не нужны в образе для контейнера практической работы №3, следовательно на этапе выполнения практической работы №3 их нужно убрать из команды в Dockerfile
 +
 
 +
===Оптимизация для контейнера в практической работе №3===
 +
 
 +
Для сборки образа с готовым приложением можно использовать Runtime-платформу Java (JRE), доступную в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:
  
 
<pre>
 
<pre>
version: '3.9'
+
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
  
services:
+
RUN adduser app
  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:
+
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>
  
networks:
+
Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством. При чём -- только JRE, т.е. без компилятора javac. Компилятор для работы приложения -- не нужен).
  net_c1_c2:
 
    name: net_c1_c2
 
  
</pre>
+
Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере
 +
Недостатки: более низкая версия платформы Java (11)
  
 +
Также следует обратить внимание на то, что сборка контейнера производится на другом образе операционной системы (alt:p10) -- официальный образ производителя -- и набор устанавливаемых пакетов отличается от оригинального набора, описанного в практической работе №3.
  
Относительно конфигурации, представленной в практической работе №5, был добавлен сервис c3:
+
В остальном порядок выполнения практической работы не отличается от практической работы №3.
  
 +
===Оптимизация композиции контейнеров в практической работе №5===
  
<pre>
+
Для добавления к композе контейнера с веб-приложением phpmyadmin необходимо расширить набор сервисов в файле
  c3:
 
    container_name: "c3"
 
    hostname: "c3"
 
    image: phpmyadmin
 
    restart: always
 
    ports:
 
      - 8080:80
 
    environment:
 
      - PMA_ARBITRARY=1
 
    networks:
 
      - net_c1_c2
 
</pre>
 
  
который был подключен к той же сети, что и остальные контейнеры.
+
docker-compose.yaml
  
У сервиса c3 экспортирован 80-й порт, на котором работает веб-приложение, на порт 8080 хостовой системы.
+
следующим образом
  
Следовательно, веб-приложение phpmyadmin можен быть запущена в браузере хостовой машины по адресу
+
<pre>
 +
version: '3.9'
 +
 
 +
services:
 +
  c1:
 +
    container_name: "c1"
 +
    hostname: "c1"
 +
    image: "mariadb"
 +
    restart: "always"
 +
    environment:
 +
      MARIADB_ROOT_PASSWORD: "123321"
 +
      MARIADB_DATABASE: "java_app_db"
 +
      MARIADB_USER: "java_app_user"
 +
      MARIADB_PASSWORD: "java_app_password"
 +
    networks:
 +
      - net_c1_c2
 +
 
 +
  c2:
 +
    container_name: "c2"
 +
    hostname: "c2"
 +
    image: "vpupkin/java_prod"
 +
    restart: "no"
 +
    environment:
 +
      DISPLAY: "$DISPLAY"
 +
      DB_HOST: "c1"
 +
      DB_PORT: "3306"
 +
      DB_NAME: "java_app_db"
 +
      DB_USER: "java_app_user"
 +
      DB_PASS: "java_app_password"
 +
    volumes:
 +
      - /tmp/.X11-unix:/tmp/.X11-unix
 +
    networks:
 +
      - net_c1_c2
 +
 
 +
  c3:
 +
    container_name: "c3"
 +
    hostname: "c3"
 +
    image: phpmyadmin
 +
    restart: always
 +
    ports:
 +
      - 8080:80
 +
    environment:
 +
      - PMA_ARBITRARY=1
 +
    networks:
 +
      - net_c1_c2
 +
 
 +
 
 +
networks:
 +
  net_c1_c2:
 +
    name: net_c1_c2
 +
 
 +
</pre>
 +
 
 +
 
 +
Относительно конфигурации, представленной в практической работе №5, был добавлен сервис c3:
 +
 
 +
 
 +
<pre>
 +
  c3:
 +
    container_name: "c3"
 +
    hostname: "c3"
 +
    image: phpmyadmin
 +
    restart: always
 +
    ports:
 +
      - 8080:80
 +
    environment:
 +
      - PMA_ARBITRARY=1
 +
    networks:
 +
      - net_c1_c2
 +
</pre>
 +
 
 +
который был подключен к той же сети, что и остальные контейнеры.
 +
 
 +
У сервиса c3 экспортирован 80-й порт, на котором работает веб-приложение, на порт 8080 хостовой системы.
 +
 
 +
Следовательно, веб-приложение phpmyadmin можен быть запущена в браузере хостовой машины по адресу
  
 
  http://localhost:8080
 
  http://localhost:8080
  
Для подключения необходимо использовать следующие данные:
+
Для подключения необходимо использовать следующие данные:
 
+
 
  Сервер: c1
+
  Сервер: c1
  Пользователь: root или java_app_user
+
  Пользователь: root или java_app_user
  Пароль: 123321 или java_app_password
+
  Пароль: 123321 или java_app_password
 
+
 
Почему так? Смотрите внимательно в файл
+
Почему так? Смотрите внимательно в файл
 
+
 
  docker-compose.yaml
+
  docker-compose.yaml
 
+
 
===Работа docker через прокси-сервер===
+
===Оптимизация №6 (запуск графического приложения в Docker под Windows)===
 
+
 
отредактировать файл
+
1. Установить VcXsrv Windows X Server: https://sourceforge.net/projects/vcxsrv/
 
+
 
  ~/.docker/config.json
+
2. Запустить приложение в режиме "Multiple windows", Display Number = 0, Start no client, поставить галочку "Disable Access Control"
 
+
 
привести его к следующему виду:
+
3. Приложение будет запущено в трее.
 
+
 
<pre>
+
Команда для запуска приложения (на примере Практической работы №2)
{
+
 
"auths": {
+
docker run --rm -it -e DISPLAY=<здесь ip адрес вашей windows-машины>:0 --mount source=C:\Users\student\pr02\src,target=/root/src,type=bind --name=java_test --hostname=java-test vpupkin/java_dev /bin/bash
"https://index.docker.io/v1/": {
+
 
"auth": "ЗДЕСЬ_БУДЕТ_TOKEN_ОТ_HUB.DOCKER.COM_У_КАЖДОГО_--СВОЙ"
+
==Примеры==
}
+
 
},
+
===Lazarus приложение===
"proxies": {
+
 
"default": {
+
https://hub.docker.com/r/vslugin/lazarus_prod
"httpProxy": "http://10.0.52.52:3128",
+
 
"httpsProxy": "http://10.0.52.52:3128",
+
docker pull vslugin/lazarus_prod:latest
"noProxy": "127.0.0.0/8"
+
  docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --name=lazarus_prod --hostname=lazarus-prod vslugin/lazarus_prod
}
+
 
}
+
Пример запуска контейнера
}
+
 
 +
docker start lazarus_prod
 +
 
 +
===Java приложение с базой данных (два контейнера)===
 +
 
 +
https://hub.docker.com/r/vslugin/java_prod
 +
 
 +
====Развёртывание и запуск вручную====
 +
 
 +
=====Команда для разрешения подключения к X-серверу=====
 +
 
 +
На докер-хосте под пользователем, под которым планируется запускать приложение из контейнера, выполнить команду:
 +
 
 +
xhost +
 +
 
 +
=====Команда для ручного развёртывания=====
 +
 
 +
docker network create net_c1_c2;docker run --name=c1 --hostname=c1 -e MARIADB_ROOT_PASSWORD=123321 -e MARIADB_DATABASE=java_app_db -e MARIADB_USER=java_app_user -e MARIADB_PASSWORD=java_app_password --network net_c1_c2 -d mariadb;sleep 5s;docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --name=c2 --hostname=c2 -e DB_HOST=c1 -e DB_PORT=3306 -e DB_NAME=java_app_db -e DB_USER=java_app_user -e DB_PASS=java_app_password --network net_c1_c2 vslugin/java_prod:latest
 +
 
 +
=====Команда запуска приложения=====
 +
 
 +
`docker start c2`
 +
 
 +
====Развёртывание и запуск в docker-compose====
 +
 
 +
=====Развёртывание=====
 +
 
 +
Просто бросьте это в консоль:
 +
<pre>
 +
cd
 +
mkdir compose_c1_c2
 +
cd compose_c1_c2
 +
cat << EOF > docker-compose.yaml
 +
version: '3.9'
 +
 
 +
services:
 +
  c1:
 +
    container_name: "c1"
 +
    hostname: "c1"
 +
    image: "mariadb"
 +
    restart: "always"
 +
    environment:
 +
      MARIADB_ROOT_PASSWORD: "123321"
 +
      MARIADB_DATABASE: "java_app_db"
 +
      MARIADB_USER: "java_app_user"
 +
      MARIADB_PASSWORD: "java_app_password"
 +
    networks:
 +
      - net_c1_c2
 +
 
 +
  c2:
 +
    container_name: "c2"
 +
    hostname: "c2"
 +
    image: "vslugin/java_prod:latest"
 +
    restart: "no"
 +
    environment:
 +
      DISPLAY: "$DISPLAY"
 +
      DB_HOST: "c1"
 +
      DB_PORT: "3306"
 +
      DB_NAME: "java_app_db"
 +
      DB_USER: "java_app_user"
 +
      DB_PASS: "java_app_password"
 +
    volumes:
 +
      - /tmp/.X11-unix:/tmp/.X11-unix
 +
    networks:
 +
      - net_c1_c2
 +
 
 +
networks:
 +
  net_c1_c2:
 +
    name: net_c1_c2
 +
EOF
 +
 
 +
docker-compose up -d
 
</pre>
 
</pre>
  
===Лайвхаки===
+
==== Команда запуска ====
 
 
Настроить доступ к registry-1.docker.io через статический маршрут
 
 
 
su -
 
 
 
echo '44.205.64.79 registry-1.docker.io' >> /etc/hosts
 
 
 
ip ro add 44.205.64.79 via 192.168.66.66
 
 
 
 
 
Переключить основной шлюз
 
 
 
su -
 
 
 
ip ro del default
 
 
 
ip ro add default via 10.207.151.253
 
  
  echo 'nameserver 8.8.8.8' > /etc/resolv.conf
+
  docker start c2

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

Содержание

DOCKER_IN_ESPD

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

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

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

10.0.52.52:3128

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

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

hub.docker.com

необходимо:

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

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

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

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

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

Приминяем

update-ca-trust

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

HTTP_PROXY

и

HTTPS_PROXY

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

/etc/sysconfig/docker

Было:

cat /etc/sysconfig/docker
OPTIONS=""

Стало:

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

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

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

systemctl restart docker

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

docker pull alt:p10

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

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

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

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

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

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

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

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

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

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

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

usermod -a -Gdocker student

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

systemctl start docker
systemctl enable docker

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

reboot

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

Вручную

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

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

alt:p10

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

docker pull alt:p10

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

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


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

root@my-first-container:/#

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

exit

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

Найти:

docker ps -a

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

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

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

my_first_container

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

f0a3cc6a8b63

Запустить:

docker start my_first_container

или:

docker start f0a3cc6a8b63

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


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

docker attach my_first_container

или

docker attach f0a3cc6a8b63


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

exit

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


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

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

Ctrl + P

затем

Ctrl + Q


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


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

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

Задача

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

Ход работы

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

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

apt-get update
apt-get install nano

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

bootstrap.sh

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

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

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

chmod +x /bootstrap.sh

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

USER_NAME=Ivan /bootstrap.sh

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

Hello, Ivan

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

exit

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

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

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

docker images

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

USER_NAME

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

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

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

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

mkdir pr01

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

cd pr01

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

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

Dockerfile

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

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


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

Dockerfile

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

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

docker build -t 'my_second_image:latest' .

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

docker images

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

my_second_image        latest              add5d00c3dc0        7 seconds ago       72.9MB

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

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

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

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

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

mkdir pr02

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

cd pr02

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

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

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

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

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

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

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

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

jdk-19.0.1

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

rm openjdk-19.0.1_linux-x64_bin.tar.gz

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

Dockerfile_dev

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

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

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

Dockerfile_dev

и каталог

jdk-19.0.1

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

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

vpupkin

а пароль

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


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


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

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


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

docker images

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

vpupkin/java_dev   latest              fa1a63896356        9 seconds ago       2.42GB


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

mkdir /home/student/pr02/src

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

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

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

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

root@java-dev:/#

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

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

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

exit

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

Найти:

docker ps -a

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

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

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

java_dev

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

8e5f4fd0a99b

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


Запустить:

docker start java_dev

или:

docker start 8e5f4fd0a99b

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


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

docker attach java_dev

или

docker attach 8e5f4fd0a99b


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

exit

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


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

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

Ctrl + P

затем

Ctrl + Q


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


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

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

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

cd /root/src/

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

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

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

cd simple-counter

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

bash mvnw install
bash mvnw dependency:copy-dependencies

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

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

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

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

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

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

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

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

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

DISPLAY

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

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

/tmp/.X11-unix

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

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

--rm

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


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

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


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

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

xhost +

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

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

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

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

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

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


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

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

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

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

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

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

mkdir pr03

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

cd pr03

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

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

Dockerfile_prod

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

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

RUN adduser app

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

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

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

USER app

CMD /startup.sh

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

mkdir app

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

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

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

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

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

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

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

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

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

rm openjdk-19.0.1_linux-x64_bin.tar.gz

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

startup.sh

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

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

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

Dockerfile_prod
startup.sh

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

jdk-19.0.1
app

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

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

vpupkin

а пароль

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


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


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

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


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

docker images

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

vpupkin/java_prod   latest              20bb2900074d        16 seconds ago      217MB


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

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

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

mkdir $HOME/data

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

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


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

Dockerfile_prod

строчкой

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

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

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

docker ps -a

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

docker start java_prod

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

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

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

docker pull mariadb

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

docker network create net_c1_c2

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

docker network list

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

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

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

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

docker exec -it c1 /bin/bash

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

mariadb -u java_app_user -pjava_app_password -h localhost java_app_db

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

exit
exit

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

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

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

с2

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

с2

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

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

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

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

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

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

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

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

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

Подготовка

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

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

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

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

ivanov_ii

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

<prefix>

заменять на

ivanov_ii

Например

ivanov_ii_container_db


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

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

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

net_<prefix>

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

<prefix>_container_db

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

<prefix>-container-db

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

<prefix>_container_app

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

<prefix>-container-app

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

<prefix>_application_db

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

<prefix>_application_user

пароль

<prefix>_applicationPassw0rd123

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

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

Предисловие

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

docker run ...

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

docker compose

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

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

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

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

docker build...

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


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

Dockerfile

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

docker-compose.yaml

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

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

docker-compose.yaml

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

docker compose up ...

Практика

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

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

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

docker-compose.yaml

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

version: '3.9'

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

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

networks:
  net_c1_c2:
    name: net_c1_c2


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

docker-compose.yaml

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

docker compose up -d

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

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

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

xhost +

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

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

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

docker-compose.yaml

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

docker

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

docker compose

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

docker compose stop c1

или

docker compose stop c2

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

docker compose stop

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

docker compose start c1

или

docker compose start c2

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

docker compose start


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

docker compose up -d


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

docker compose down

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

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

docker volume prune

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


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

docker compose

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


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

docker compose

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

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

Подготовка

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

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

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

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

ivanov_ii

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

<prefix>

заменять на

ivanov_ii

Например

ivanov_ii_container_db


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

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

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

net_<prefix>

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

<prefix>_container_db

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

<prefix>-container-db

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

<prefix>_container_app

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

<prefix>-container-app

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

<prefix>_application_db

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

<prefix>_application_user

пароль

<prefix>_applicationPassw0rd123

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

docker-compose.yaml

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

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

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

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

vpupkin/java_prod

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

/

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

<username>/<imagename>:<tag>

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

vpupkin

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

java_prod

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

vpupkin/java_prod

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

vpupkin/java_prod:some_tag_name

, где

some_tag_name

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

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

latest

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

vpupkin/java_prod:latest

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

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

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

vpupkin/java_prod

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

ivanov_ii

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

ivanov_ii/java_prod

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

/

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

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

docker run ...

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

docker-compose.yaml

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

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

vpupkin/java_prod

на

ivanov_ii/java_prod:latest

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

docker tag vpupkin/java_prod ivanov_ii/java_prod:latest

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

docker images

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

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

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

docker rmi vpupkin/java_prod

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

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

ivanov_ii/java_prod:latest

на hub.docker.com

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

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

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

docker login

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

Login Succeeded

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

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

Login Succeeded


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

docker push ivanov_ii/java_prod:latest

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

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

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

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

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

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

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

unxz -c images.tar.xz | docker load

Оптимизации

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

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

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

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

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

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

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

git checkout jdk11


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

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

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

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

java-11-openjdk-devel

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

Пакеты

java-11-openjdk-devel nano git

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

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

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

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

RUN adduser app

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

USER app

CMD /startup.sh

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

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

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

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

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

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

docker-compose.yaml

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

version: '3.9'

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

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

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


networks:
  net_c1_c2:
    name: net_c1_c2


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


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

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

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

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

http://localhost:8080

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

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

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

docker-compose.yaml

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

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

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

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

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

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

Примеры

Lazarus приложение

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

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

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

docker start lazarus_prod

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

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

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

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

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

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

`docker start c2`

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

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

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

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

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

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

networks:
  net_c1_c2:
    name: net_c1_c2
EOF

docker-compose up -d

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

docker start c2