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

Материал из wiki.nntc.nnov.ru
Перейти к навигации Перейти к поиску
(Создание файлов)
(Docker_IN_ESPD)
 
(не показано 89 промежуточных версий этого же участника)
Строка 1: Строка 1:
 +
=DOCKER_IN_ESPD=
 +
 +
==Прокси сервер==
 +
 +
В ЕСПД каждой организации существует адрес прокси-сервера для доступа в централизованно-ограниченный провайдером интернет.
 +
 +
Например, это может быть адрес и порт:
 +
 +
10.0.52.52:3128
 +
 +
==Настройка сервиса для работы с прокси-сервером в ОС Альт==
 +
 +
Для настройки сервиса docker в ОС Альт на доступ к образам с
 +
 +
hub.docker.com
 +
 +
необходимо:
 +
 +
Импортировать сертификат (подробнее об этом здесь [https://www.altlinux.org/%D0%95%D0%A1%D0%9F%D0%94 здесь]):
 +
 +
Переходим в каталог
 +
 +
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
 +
 +
Было:
 +
<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>
 +
 +
Важно! Адрес и порт прокси сервера могут быть другими!
 +
 +
Затем необходимо перезапустить сервис
 +
 +
systemctl restart docker
 +
 +
Теперь можно пробовать получить образ
 +
 +
docker pull alt:p10
 +
 +
В случае успешной настройки в ответ должно быть что-то вроде этого
 +
 +
<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>
 +
 
=Лабораторные работы по Docker=
 
=Лабораторные работы по Docker=
  
Строка 43: Строка 124:
 
На базе официального стандартного Docker-образа
 
На базе официального стандартного Docker-образа
  
  altlinux/base:p10
+
  alt:p10
  
 
Только получить образ на компьютер можно командой:
 
Только получить образ на компьютер можно командой:
  
  docker pull altlinux/base:p10
+
  docker pull alt:p10
  
 
создайте и запустите Docker-контейнер:
 
создайте и запустите Docker-контейнер:
  
  docker run -it --name=my_first_container --hostname=my-first-container altlinux/base:p10 /bin/bash
+
  docker run -it --name=my_first_container --hostname=my-first-container alt:p10 /bin/bash
  
  
Строка 177: Строка 258:
 
Примеры команды:
 
Примеры команды:
  
  docker run --rm -e USER_NAME=Ivan -it my_first_image /bootstrap.sh
+
  docker run --rm -e USER_NAME=Ivan my_first_image /bootstrap.sh
  
  docker run --rm -e USER_NAME=Maria -it my_first_image /bootstrap.sh
+
  docker run --rm -e USER_NAME=Maria my_first_image /bootstrap.sh
  
  docker run --rm -e USER_NAME=Petr -it my_first_image /bootstrap.sh
+
  docker run --rm -e USER_NAME=Petr my_first_image /bootstrap.sh
  
  docker run --rm -e USER_NAME=Ekaterina -it my_first_image /bootstrap.sh
+
  docker run --rm -e USER_NAME=Ekaterina my_first_image /bootstrap.sh
  
 
===Автоматически (посредством файла Dockerfile)===
 
===Автоматически (посредством файла Dockerfile)===
Строка 195: Строка 276:
 
  cd pr01
 
  cd pr01
  
===Создание файлов===
+
====Создание файлов====
  
 
В рабочем каталоге создайте файл  
 
В рабочем каталоге создайте файл  
Строка 204: Строка 285:
  
 
<pre>
 
<pre>
FROM altlinux/base:p10
+
FROM alt:p10
 
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 
RUN echo '#!/bin/bash' > /bootstrap.sh
 
RUN echo '#!/bin/bash' > /bootstrap.sh
Строка 217: Строка 298:
 
  Dockerfile
 
  Dockerfile
  
===Создание образа контейнера===
+
====Создание образа контейнера====
  
 
Для создания Docker-образа (image) выполните команду:
 
Для создания Docker-образа (image) выполните команду:
Строка 231: Строка 312:
 
  my_second_image        latest              add5d00c3dc0        7 seconds ago      72.9MB
 
  my_second_image        latest              add5d00c3dc0        7 seconds ago      72.9MB
  
===Запуск контейнера на базе образа===
+
====Запуск контейнера на базе образа====
  
 
Запуск контейнеров на базе созданного образа (за исключением имени образа и отсутствием необходимости указывать исполняемый скрипт (он указан непосредственно в Dockerfile)) ни чем не будет отличаться от запуска контейнеров в ходе создания образа вручную:
 
Запуск контейнеров на базе созданного образа (за исключением имени образа и отсутствием необходимости указывать исполняемый скрипт (он указан непосредственно в Dockerfile)) ни чем не будет отличаться от запуска контейнеров в ходе создания образа вручную:
  
  docker run --rm -e USER_NAME=Ivan -it my_second_image
+
  docker run --rm -e USER_NAME=Ivan my_second_image
  
  docker run --rm -e USER_NAME=Maria -it my_second_image
+
  docker run --rm -e USER_NAME=Maria my_second_image
  
  docker run --rm -e USER_NAME=Petr -it my_second_image
+
  docker run --rm -e USER_NAME=Petr my_second_image
  
  docker run --rm -e USER_NAME=Ekaterina -it my_second_image
+
  docker run --rm -e USER_NAME=Ekaterina my_second_image
  
 
==[Практическая работа №2] Создание контейнера для разработки приложения на языке Java==
 
==[Практическая работа №2] Создание контейнера для разработки приложения на языке Java==
Строка 282: Строка 363:
  
 
<pre>
 
<pre>
FROM altlinux/base:p10
+
FROM alt:p10
 
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
RUN apt-get update -q -y && apt-get install nano git
+
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
 
RUN mkdir /opt/jdk-19.0.1
 
COPY jdk-19.0.1 /opt/jdk-19.0.1
 
COPY jdk-19.0.1 /opt/jdk-19.0.1
Строка 436: Строка 517:
 
  cd simple-counter
 
  cd simple-counter
  
 +
Исходя из рекомендаци в файле README.md выполним сборку проекта
  
... дописать про особенности сборки и запуска приложения на Java (TBD) ...
+
bash mvnw install
 
+
bash mvnw dependency:copy-dependencies
 
 
  
 +
В случае успешной сборки в терминале котейнера долждно быть написано что-то похожее на это:
  
 +
<pre>
 +
[INFO] ------------------------------------------------------------------------
 +
[INFO] BUILD SUCCESS
 +
[INFO] ------------------------------------------------------------------------
 +
</pre>
  
 +
На этом этам сборки приложения заврешён.
  
 
Теперь наша задача - запустить приложение прямо на хостовой машине (но выполняться оно будет в контейнере).
 
Теперь наша задача - запустить приложение прямо на хостовой машине (но выполняться оно будет в контейнере).
  
===Делаем образ из контейнера с приложением на языке Java===
+
===Запуск собранного приложения в docker-контейнере на базе образа с JDK===
 
 
Для того, чтобы запустить получившееся приложение внутри контейнера, но графическую часть его иметь на хостовой машине, нужно запустить еще один контейнер. Однако, из какого образа?
 
 
 
Вероятно, из такого, где оно (приложение на языке Java) присутствует. У нас есть такой образ?
 
  
 +
Запустим новый контейнер командой:
  
Верно, нет. У нас есть лишь контейнер, который мы получили на базе подготовленного чистого образа.
+
  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
 
 
 
 
Но мы можем теперь легко получить образ на базе нашего контейнера с приложением на языке Java. Для этого нужно завершить контейнер и выполнить команду в хостовой систиеме:
 
 
 
docker commit -a Vasya java_dev vpupkin/java_test
 
 
 
Убедиться, что образ создался, можно по прежнему командой:
 
 
docker images
 
 
 
 
А вот теперь уже можно запустить контейнер на базе образа:
 
 
 
vpupkin/java_test
 
 
 
, который будет запускать приложение на Lazarus прямо на хостовой системе. Для этого нужно запустить контейнер такой командой:
 
 
 
  docker run --rm -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --mount source=/home/user/pr02/src,target=/root/src,type=bind --name=java_test --hostname=java-test vpupkin/java_test /startup.sh
 
  
 
Для успешного запуска графического приложения, работающего в контейнере, с возможностью отображения графического интерфейса, в этой команде сделано две вещи:
 
Для успешного запуска графического приложения, работающего в контейнере, с возможностью отображения графического интерфейса, в этой команде сделано две вещи:
Строка 494: Строка 561:
  
  
Однако, возможно, не стоит каждый раз содавать контейнер из образа, если изменений в параметрах запуска не требуется?
+
Эта опция сюда добавлена, поскольку сама команда старта контейнера содержит в себе цель запускать именно оболочку /bin/bash для ручного тестирования запуска собранного приложения.
 +
 
 +
Предполагается, что после такого тестирования контейнер не нужен и при выходе из него его логичнее всего автоматически удалять.
 +
 
  
Достаточно убрать параметр
+
Когда работа собранного приложения протестирована и есть понимание, что всё работает корректно, можно приступать к сборке образа для production-контейнера, в котором необходимо оставить необходимое и достаточное количество библиотек, необходимых только для запуска уже собранного приложения, а пакеты и утилиты, необходимые для сборки, не включать в результирующий образ.
  
  --rm
+
Важный момент: В некоторых операционных системах может потребоваться выполнить команду
 +
 
 +
  xhost +
  
из команды запуска контейнера, но следует помнить, что при завершении графического приложения контейнер будет завершён и запускать его уже нужно будет командой старта контейнера (в этом случае контейнер никуда не девается, а просто лежит на хостовой системе в выключенном состоянии).
+
для разрешения подключения контейнера к графической оболочке X-сервера.
  
И включить его можно (т.е. запустить наше java-приложение) так:
+
Тестовый запуск приложения можно выполнить командами:
  
  docker start java_test
+
  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
  
 
===Отвечаем на главный вопрос?===
 
===Отвечаем на главный вопрос?===
Строка 510: Строка 583:
 
Вопрос звучит так:
 
Вопрос звучит так:
  
  Если мы уже разработали приложение, то надо ли конечному пользователю все эти дополнительные инструменты для сборки приложения, которые использовались для создания контейнера с инструментами разработки?
+
  Если мы уже собрали приложение, то нужно ли конечному пользователю инструменты для сборки приложения, которые были нужны в сборочном контейнере, и исходный код приложения?
  
  
Наверное нет. Они сильно загружают систему при том, что больше никогда не понадобятся пользователю.
+
Не нужны по нескольким причинам:
  
Поэтому для конечного пользователя целесообразно создать новый контейнер, исключив оттуда всё лишнее и оставив лишь непосредственно готовое приложение.
+
# Исходный чаще всего остаётся интеллектуальной собственностью компании-разработчика и не должен оказаться у заказчика
 +
# Наличие на Production-системе компилятора какого-либо языка и/или каких-либо средств разработки является потенциальной уязвимостью системы
 +
# Инструменты сборки и тестирования никогда не понадобятся конечному пользователю на  Production-системе, но всегда будут занимать место на файловой системе контейнера
  
 +
Поэтому для конечного пользователя целесообразно создать новый образ, исключив оттуда всё лишнее и оставив лишь непосредственно готовое приложение.
  
 
Как это сделать -- см. в следующей практической работе.
 
Как это сделать -- см. в следующей практической работе.
  
==[Практическая работа №3] Создание контейнера для запуска приложения на Lazarus==
+
==[Практическая работа №3] Создание контейнера для запуска Java-приложения==
Откройте терминал хостовой машины. Если в домашнем каталоге пользователя присутствует каталог
+
Откройте терминал хостовой машины. Создайте рабочий каталог
  
docker
+
  mkdir pr03
 
 
то переместите его в резервную копию командой:
 
 
 
mv docker docker_backup1
 
 
 
затем заново создайте рабочий каталог командой:
 
 
 
  mkdir docker
 
  
 
Перейдите в рабочий каталог
 
Перейдите в рабочий каталог
  
  cd docker
+
  cd pr03
  
 
===Создание файлов===
 
===Создание файлов===
Строка 546: Строка 614:
  
 
<pre>
 
<pre>
FROM ubuntu:20.04
+
FROM alt:p10
 
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 +
RUN apt-get update -q -y \
 +
    && apt-get install nano 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
  
ENV USER ubuntu
+
RUN mkdir /opt/jdk-19.0.1
ENV HOME /home/$USER
+
COPY jdk-19.0.1 /opt/jdk-19.0.1
  
# Install dependencyes
+
RUN mkdir /opt/app
RUN apt-get update \
+
COPY app /opt/app
    && apt-get install -y libgtk2.0-0 \
+
COPY startup.sh /
    && apt-get autoclean \
+
RUN chmod +x /startup.sh
    && apt-get autoremove \
+
 
    && rm -rf /var/lib/apt/lists/*
+
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
  
# Create new user for run app
+
USER app
RUN adduser $USER --disabled-password
 
  
# Copy app to user homedir
+
CMD /startup.sh
COPY mypr /home/$USER/
 
CMD /bin/su -c "/home/ubuntu/mypr" ubuntu
 
 
</pre>
 
</pre>
 +
 +
Создайте каталог app в рабочем каталоге
 +
 +
mkdir app
  
 
Скопируйте исполняемый файл, полученный в предыдущей работе в рабочий каталог
 
Скопируйте исполняемый файл, полученный в предыдущей работе в рабочий каталог
  
  cp ../docker_backup1/lazarus/project_name/mypr ./
+
  /bin/cp -r ../pr02/src/simple-counter/target app/
  
Мы находимся в новом рабочем каталоге хостовой машины:
+
Скачайте в рабочий каталог JDK версии 19.0.1. Это можно сделать командой (рекомендуется использовать в локальной сети колледжа)
  
  /home/user/docker
+
  wget https://wiki.nntc.nnov.ru/download/openjdk-19.0.1_linux-x64_bin.tar.gz
  
В начале этой работы каталог предыдущей работы мы переместили сюда:
+
или командой (при работе вне локальной сети колледжа)
  
  /home/user/docker_backup1
+
  wget https://download.java.net/java/GA/jdk19.0.1/afdd2e245b014143b62ccb916125e3ce/10/GPL/openjdk-19.0.1_linux-x64_bin.tar.gz
  
Следовательно, относительно каталога
+
Распакуйте загруженный файл командой
  
  /home/user/docker
+
  tar -xzpf openjdk-19.0.1_linux-x64_bin.tar.gz
  
команда копирования исполняемого файла требует подняться на уровень выше
+
На этом этапе архив можно удалить командой
  
  ../
+
  rm openjdk-19.0.1_linux-x64_bin.tar.gz
  
и из каталога
+
Создайте в рабочем каталоге файл
  
  docker_backup1
+
  startup.sh
  
уровнем выше относительно
+
со следующим содержимым
  
/home/user/docker
+
<pre>
 +
#!/bin/bash
 +
source /home/app/.bashrc
 +
cd /opt/app
 +
java --module-path=target/dependency/ --add-modules javafx.controls,javafx.fxml -cp target/demo_up04-1.0-SNAPSHOT.jar com.example.demo_up04.DemoApplication
 +
</pre>
  
скопировать необходимый файл в текущий каталог
+
В конце этого этапа в рабочем каталоге должно быть два файла:
  
  ./
+
  Dockerfile_prod
 +
startup.sh
  
В конце этого этапа в рабочем каталоге должно быть два файла:
+
И два каталога:
  
  Dockerfile_prod
+
  jdk-19.0.1
  mypr
+
  app
  
 
===Создание образа контейнера===
 
===Создание образа контейнера===
Строка 621: Строка 703:
 
Для создания Docker-образа (image) выполните команду:
 
Для создания Docker-образа (image) выполните команду:
  
  docker build -t 'vpupkin/lazarus_prod:latest' -f Dockerfile_prod .
+
  docker build -t 'vpupkin/java_prod:latest' -f Dockerfile_prod .
  
  
Строка 630: Строка 712:
 
Среди текста ответа должна появиться строчка с новым контейнером:
 
Среди текста ответа должна появиться строчка с новым контейнером:
  
  vpupkin/lazarus_prod   latest              20bb2900074d        16 seconds ago      217MB
+
  vpupkin/java_prod   latest              20bb2900074d        16 seconds ago      217MB
  
  
 
  ! Обратите внимание на размер контейнера !
 
  ! Обратите внимание на размер контейнера !
  Сравните размер контейнера с размером контейнера lazarus_dev из предыдущей работы
+
  Сравните размер контейнера с размером контейнера java_dev из предыдущей работы
  
 
===Запуск контейнера на базе образа===
 
===Запуск контейнера на базе образа===
  
На базе полученного образа запустите контейнер, пробросив внутрь контейнера локальный каталог хостовой машины и пробросив порт для взаимодействия с графической оболочкой контейнера посредством клиента noVNC:
+
Создадим каталог для обмена данными с контейнером
  
  docker run -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --name=lazarus_prod --hostname=lazarus-prod vpupkin/lazarus_prod
+
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
  
  
Строка 649: Строка 735:
 
строчкой
 
строчкой
  
  CMD /bin/su -c "/home/ubuntu/mypr" ubuntu
+
  CMD /bin/su -c "/startup.sh" app
  
 
Результатом запуска контейнера должно стать запущенное внутри контейнера графическое приложение с отображением графического интерфейса на хостовой машине.
 
Результатом запуска контейнера должно стать запущенное внутри контейнера графическое приложение с отображением графического интерфейса на хостовой машине.
Строка 659: Строка 745:
 
Повторный запуск уже существующего контейнера можно осуществить по имени контейнера командой:
 
Повторный запуск уже существующего контейнера можно осуществить по имени контейнера командой:
  
  docker start lazarus_prod
+
  docker start java_prod
  
==[Практическая работа №4] Взаимодействие двух контейнеров по сети==
+
==[Практическая работа №4] Взаимодействие двух контейнеров по сети (ручной запуск)==
  
Задача: Запустить ПО Moodle в контейнере с именем c2, который взаимодействует с базой данных Mariadb, запущенной в контейнере с именем c1
+
Задача: Запустить Java-приложение в контейнере с именем c2, который взаимодействует с базой данных Mariadb, запущенной в контейнере с именем c1
  
===Загрузить образы контейнеров===
+
===Загрузка образа для контейнера с mariadb===
  
 
  docker pull mariadb
 
  docker pull mariadb
docker pull bitnami/moodle
 
  
 +
===Создание сетевого моста===
 +
 +
docker network create net_c1_c2
 +
 +
Проверить список сетевых мостов можно командой
 +
 +
docker network list
 +
 +
===Запуск контейнера c1 и подготовка базы данных===
  
===Создание и подготовка контейнера C1===
 
 
Создать контейнер с базой данных Mariadb и задать пароль пользователя root через переменную окружения
 
Создать контейнер с базой данных Mariadb и задать пароль пользователя root через переменную окружения
  
  docker run --name=c1 --hostname=c1 -e MYSQL_ROOT_PASSWORD=123321 --network bridge -d mariadb
+
  docker run --name=c1 --hostname=c1 -e MARIADB_ROOT_PASSWORD=123321 -e MARIADB_DATABASE=java_app_db -e MARIADB_USER=java_app_user -e MARIADB_PASSWORD=java_app_password --network net_c1_c2 -d mariadb
 +
 
 +
Проверить корректность подключения к Mariadb с созданным пользователем к созданной базе данных (подключиться к консоли контейнера c1 и воспользоваться клиентом mysql)
 +
 
 +
docker exec -it c1 /bin/bash
 +
 
 +
Внутри контейнера запустить клиент mysql с параметрами подключения к бд:
 +
 
 +
mysql -u java_app_user -pjava_app_password -h localhost java_app_db
 +
 +
Выход из mysql и из контейнера
 +
 
 +
exit
 +
exit
 +
 
 +
===Запуск контейнера c2 с Java-приложением===
 +
 
 +
Запуск контейнера с Java-приложением производится аналогично запуску, подробно описанному в практической работе №3 с учётом ряда нюансов:
  
Создать временный контейнер с ПО Moodle и запустить его с доступом в командную оболочку
+
1. Необходимо учитывать, что имя запускаемого контейнера должно быть
  
  docker run -it --rm --name c2_tmp --network bridge bitnami/moodle:latest /bin/bash
+
  с2
  
Установить во временный контейнер утилиты проверки состояния сети
+
2. Необходимо учитывать, что имя хоста запускаемого контейнера должно быть
  
  apt update
+
  с2
apt install net-tools iputils-ping
 
  
Изнутри контейнера c2_tmp проверить доступ в базу данных (для этого нужно убедиться в корректности ip адреса контейнера c1):
+
3. Необходимо учитывать, что для корректного подключения Java-приложения к базе данных, доступной в контейнере с именем_контейнера=именем_хоста=с1 необходимо при запуске контейнера с2 передать набор переменных окружения для настройки Java-приложения на работу с базой данных в контейнере c1
  
1. Посмотреть ip адрес конейнера c2_tmp (если контейнеры были запущены последовательно, то адрес контейнера c1 будет на единицу меньше)
+
DB_HOST=c1
 +
DB_PORT=3306
 +
DB_NAME=java_app_db
 +
DB_USER=java_app_user
 +
DB_PASS=java_app_password
  
ifconfig
+
Пример команды для запуска контейнера c2 (запуск контейнера осуществляется на базе образа, созданного в практической работе №3)
  
2. Выполнить
+
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
  
ping <предполагаемый адрес контейнера c1>
+
При необходимости монтирования директорий хостовой машины в контейнер также могут быть использованы дополнительные параметры, как было показано в примере запуска контейнера в практической работе №3 с параметром
  
в соседней консоли остановить контейнер c1
+
--mount source="$HOME/data",target=/home/app/data,type=bind
  
docker stop c1
+
В данном примере этот параметр опущен, т.к. тестовое приложение не имеет функций чтения и записи файлов.
  
в предыдущей консоли убедиться что пинги прекратились. Вернуться в соседнюю консоль. Запустить контейнер c1
+
===Самостоятельное задание===
  
docker start c1
+
====Подготовка====
  
в предыдущей консоли убедиться что пинги возобновились.
+
Придумать уникальный префикс для именования названий, завязанный на фамилию и инициалы обучающегося.
  
3. Выполнить проверку подключения к Mariadb посредством клиента mysql в контейнере c2_tmp
+
Например, для обучающегося
  
  mysql -u root -p<пароль, установленный в переменной окружения при запуске контейнера c1> -h <корректный ip адрес контейнера c1>
+
  Иванов Иван Иванович
  
4. Создать базу пользователя и базу данных Mariadb для работы Moodle (из консоли mysql, предварительно подключившись к ней под пользователем root)
+
Префикс (<prefix>) будет состоять из фамилии и инициалов
  
  CREATE DATABASE mdatabase;
+
  ivanov_ii
CREATE USER 'muser'@'%' IDENTIFIED BY '123456';
 
GRANT ALL PRIVILEGES ON mdatabase.* to 'muser'@'%' WITH GRANT OPTION;
 
  
5. Проверить корректность подключения к Mariadb с созданным пользователем к созданной базе данных
+
Тогда в приведённых ниже примерах необходимо
  
  mysql -u muser -p123456 -h <корректный ip адрес контейнера c1> mdatabase
+
  <prefix>
   
+
 
6. Выйти из временного контейнера c2_tmp
+
заменять на
 +
 
 +
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-образа это файл:
  
  exit
+
  Dockerfile
  
===Запуск контейнера C2 с ПО Moodle===
+
, в случае же с автоматическим запуском нескольких контейнеров в композе -- это файл:
  
Поскольку в предыдущем пункте были подготовлены параметры доступа в базу данных Mariadb, используем их для запуска контейнера с ПО Moodle
+
docker-compose.yaml
  
docker run -d --name c2 -p 8080:8080 -p 8443:8443 --env ALLOW_EMPTY_PASSWORD=no --env MOODLE_DATABASE_USER=muser --env MOODLE_DATABASE_PASSWORD=123456 --env MOODLE_DATABASE_NAME=mdatabase --env MOODLE_DATABASE_HOST=<корректный ip адрес контейнера c1> --env MOODLE_USERNAME=user --env MOODLE_PASSWORD=123321 --env MOODLE_EMAIL=user@host.com --env MOODLE_SITE_NAME=user_moodle --network bridge bitnami/moodle:latest
+
Для того, чтобы запустить любую композицию контейнеров, необходимо:
  
Проверка: Открыть в браузере адрес:
+
1. Сконфигурировать файл
  
  http://localhost:8080
+
  docker-compose.yaml
  
Ввести логин и пароль от ПО Moodle, указанные ранее в переменных окружения при старте контейнера.
+
2. Выполнить запуск композы командой
  
Подробное описание по контейнеру: https://hub.docker.com/r/bitnami/moodle
+
docker-compose up ...
  
Важно! Первые несколько минут ПО Moodle не будет доступно по указанному адресу http://localhost:8080
+
===Установка docker-compose===
т.к. будет выполняться его первое развёртывание.
 
  
Проследить процесс развёртывания можно внутри базы данных в контейнере c1, подключившись к ней с хостовой машины
+
В хостовой системе откройте терминал и выполните команду для получения доступа под суперпользователем root
  
  mysql -u muser -p123456 -h <корректный ip адрес контейнера c1> mdatabase
+
  su -
  
и из консоли mysql проверить наличие таблиц в базе данных
+
Введите пароль от суперпользователя. Приглашение должно смениться на суперпользовательское и заканчиваться символом решётки. В этом режиме выполните команду установки пакета из репозитория:
  
  show tables
+
  apt-get install docker-compose -y
  
===Самостоятельное задание===
+
При необходимости, перед выполнением этой команды можно выполнить команду обновления базы данных пакетов в репозитории:
  
Используя справку по утилите docker запустить два аналогичных контейнера, установив статические ip адреса для них.
+
apt-get update
  
==[Практическая работа №5] Взаимодействие двух контейнеров по сети==
+
===Практика===
  
 
Создайте рабочий каталог и перейдите в него
 
Создайте рабочий каталог и перейдите в него
  
  mkdir composemoodle
+
  mkdir compose_с1_с2
  cd composemoodle
+
  cd compose_с1_с2
  
 
Создайте файл
 
Создайте файл
  
  docker-compose.yml
+
  docker-compose.yaml
  
 
со следующим содержимым
 
со следующим содержимым
  
 
<pre>
 
<pre>
version: "2.2"
+
version: '3.9'
 +
 
 
services:
 
services:
   mariadb:
+
   c1:
    image: "mariadb:latest"
+
    container_name: "c1"
    environment:
+
    hostname: "c1"
       - MYSQL_ROOT_PASSWORD=123321
+
    image: "mariadb"
       - MYSQL_ALLOW_EMPTY_PASSWORD=no
+
    restart: "always"
       - MYSQL_DATABASE=mdatabase
+
    environment:
       - MYSQL_USER=muser
+
       MARIADB_ROOT_PASSWORD: "123321"
       - MYSQL_PASSWORD=123456
+
       MARIADB_DATABASE: "java_app_db"
   moodle:
+
       MARIADB_USER: "java_app_user"
     ports:
+
       MARIADB_PASSWORD: "java_app_password"
      - "8080:8080"
+
    networks:
      - "8443:8443"
+
       - net_c1_c2
     image: "bitnami/moodle:latest"
+
 
 +
   c2:
 +
     container_name: "c2"
 +
    hostname: "c2"
 +
     image: "vpupkin/java_prod"
 +
    restart: "no"
 
     environment:
 
     environment:
       - ALLOW_EMPTY_PASSWORD=no
+
       DISPLAY: "$DISPLAY"
       - MOODLE_DATABASE_USER=muser
+
       DB_HOST: "c1"
       - MOODLE_DATABASE_PASSWORD=123456
+
       DB_PORT: "3306"
       - MOODLE_DATABASE_NAME=mdatabase
+
       DB_NAME: "java_app_db"
       - MOODLE_DATABASE_HOST=mariadb
+
       DB_USER: "java_app_user"
       - MOODLE_USERNAME=user
+
       DB_PASS: "java_app_password"
       - MOODLE_PASSWORD=123321
+
    volumes:
      - MOODLE_EMAIL=user@host.com
+
       - /tmp/.X11-unix:/tmp/.X11-unix
       - MOODLE_SITE_NAME=user_moodle
+
    networks:
 +
       - net_c1_c2
 +
 
 +
networks:
 +
  net_c1_c2:
 +
    name: net_c1_c2
 
</pre>
 
</pre>
  
Строка 796: Строка 989:
 
В результате в рабочем каталоге должен быть файл:
 
В результате в рабочем каталоге должен быть файл:
  
  docker-compose.yml
+
  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-compose up
+
Учитывая факт того, что в случае отсутствия имени тега (значения справа от двоеточия) у docker-образа при использовании имени образа в команде
  
=Проблемы под Windows=
+
docker run ...
  
В этом разделе описаны возможные проблемы при использовании Docker и Docker-compose в Windows в случае если до этого была нормальная и понятная работа в системах GNU/Linux или MacOSx, а теперь по каким-то причинам потребовалось работать с Docker из Windows...
+
или при использовании имени образа в файле
  
==Как запускать под виндой синтаксический сахар, если он у вас есть в формате bash скриптов==
+
docker-compose.yaml
  
Поставить GIT отсюда https://git-scm.com (он все равно будет нужен)
+
инфраструктура docker подразумевает использование тега по умолчанию (latest), необходимо задать тег по умолчанию при задании имени образу перед публикацией его на портале hub.docker.com
  
Вместе с ним поставится Git Bash, которому будет передавать управление Power Shell, если из него (из Power Shell) запускать исполняемые *.sh файлы с шебангом:
+
Изменить имя docker-образа с
  
  #!/bin/bash
+
  vpupkin/java_prod
 +
 
 +
на
 +
 
 +
ivanov_ii/java_prod:latest
 +
 
 +
можно командой (дополнительно уточнив в новом имени значение тега -- справа от двоеточия):
 +
 
 +
docker tag vpupkin/java_prod ivanov_ii/java_prod:latest
 +
 
 +
Результат переименования образа можно проверить командой:
 +
 
 +
docker images
 +
 
 +
В ответе можно наблюдать несколько образов с одинаковым IMAGE ID
 +
 
 +
<pre>
 +
REPOSITORY            TAG      IMAGE ID      CREATED        SIZE
 +
ivanov_ii/java_prod  latest    82acd99eb61f  20 hours ago  1.09GB
 +
vpupkin/java_prod    latest    82acd99eb61f  20 hours ago  1.09GB
 +
</pre>
 +
 
 +
При необходимости, образ с предыдущим тегом (vpupkin/java_prod) можно удалить (при отсутствии контейнеров, запущенных на его базе!) командой:
 +
 
 +
docker rmi vpupkin/java_prod
 +
 
 +
===Решаемая задача===
 +
 
 +
Опубликовать подготовленный docker-образ, имеющий имя
 +
 
 +
ivanov_ii/java_prod:latest
 +
 
 +
на hub.docker.com
  
==/bin/bash^M: bad interpreter: No such file or directory==
+
Для этого необходимо иметь логин и пароль от учётной записи на портале hub.docker.com
  
Решение описано здесь: https://forums.docker.com/t/error-while-running-docker-code-in-powershell/34059/5
+
===Публикация docker-образа===
  
Кратко:
+
Выполните аутентификацию на портале. Для этого в терминале (где обычно запускаете команды docker... и другие) выполните команду:
  
Шаг 1
+
docker login
  
удалить репозиторий
+
В ответ будет выведен текстовый диалог, в котором необходимо ввести логин и пароль. В случае корректного ввода логина и пароля в конце диалога будет выведено сообщение
  
Шаг 2
+
Login Succeeded
  
Настроить git командой
+
Полный текст диалога должен быть похож на этот:
  
git config --global core.autocrlf input
+
<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
  
Шаг 3
+
Login Succeeded
 +
</pre>
  
склонировать заново и попробовать ещё раз
 
  
Но есть вероятность что винда не поймёт эту глобальную настройку, если командовать из PowerShell. Поэтому сразу железобетонный вариант -- клонировать с указанием ключа, например:
+
После успешного логина для публикации образа выполните команду
  
  git clone -o core.autocrlf=input https://ну_и_тут_путь_к_репозиторию
+
docker push ivanov_ii/java_prod:latest
  
==Кеширование образов контейнеров виндой==
+
Процедура публикации будет похожа на эту:
  
Вроде бы полностью удален и контейнер и образ, однако, при повторном создании контейнера и докер-файла в консоли видно что он поднимается из кеша и не пересобирается как нужно.
+
<pre>
 +
The push refers to repository [docker.io/ivanov_ii/java_prod]
 +
e1640cc719ff: Pushed
 +
6fb986383f38: Pushed
 +
fbf95f9f9b64: Pushed
 +
9e9e19c988d7: Pushed
 +
fa67c5190d97: Pushed
 +
2b1db325894b: Pushed
 +
60bdc4ff8a54: Mounted from library/alt
 +
9a03b2bc42d8: Mounted from library/alt
 +
latest: digest: sha256:e75a567439afb64a9d3b5b119650e91775e7eb1d9345f5171fefba0cfe18aea3 size: 1990
 +
</pre>
  
Решение - отключить кеширование. Для этого нужно создать пустой файл
+
После завершения процедуры публикации можно проверить наличие образа на портале https://hub.docker.com в личном кабинете, загрузив страницу в браузере выполнив вход в систему.
  
%APPDATA%\Docker\disable-filesystem-caching
+
==Оптимизации==
  
Источник: https://github.com/docker/for-win/issues/5530
+
===Оптимизация для контейнера в практической работе №2===
  
Возможно, способ с созданием файла поможет после перезагрузки ОС.
+
Для сборки приложения можно использовать компилятор Java, доступный в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:
  
Если способ не помогает, то можно попробовать остановить Docker (пкм на иконке Docker Desktop в трее), затем перейти в каталог
+
<pre>
 +
FROM alt:p10
 +
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 +
RUN apt-get update -q -y \
 +
    && apt-get dist-upgrade -q -y \
 +
    && apt-get install java-11-openjdk-devel nano git java-11-openjdk libGL libgtk+3 libXxf86vm xorg-dri-swrast fonts-ttf-dejavu -q -y
 +
</pre>
  
%APPDATA%\
+
Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством)
  
и удалить там оба каталога, имя которых начинается на
+
затем на этапе клонирования проекта командой
  
  Docker
+
  git clone https://gitlab.nntc.nnov.ru/vlad.tancev/simple-counter
  
Затем запустить Docker Desktop тыком в ярлык
+
нужно сменить ветку для использования кода, адаптированного под платформу Java-11 (вместо Java-19 по умолчанию)
  
=NVIDIA IN DOCKER=
+
git checkout jdk11
  
https://nvidia.github.io/nvidia-container-runtime/
 
  
https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/user-guide.html
+
Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере
 +
Недостатки: более низкая версия платформы Java (11)
  
=Backup and Restore docker volumes=
+
Также следует обратить внимание на то, что сборка контейнера производится на другом образе операционной системы (alt:p10) -- официальный образ производителя -- и набор устанавливаемых пакетов отличается от оригинального набора, описанного в практической работе №3.
  
==Backup==
+
В остальном порядок выполнения практической работы не отличается от практической работы №3.
  
Допустим, у нас был запущен контейнер с локальным volume такой командой:
+
Следует обратить внимание, что в операционной системе Alt для получения компилятора javac нужно установить пакет
  
  docker run -v /dbdata --name dbstore ubuntu /bin/bash
+
  java-11-openjdk-devel
  
/dbdata
+
, что и сделано в соответствюущей RUN-команде в Dockerfile. Также для целей сборки приложения установлены утилиты git и nano.
  
здесь это указание на то, что внутри контейнера в каталоге /dbdata будут находиться данные, которые docker будет физически хранить в одном из volumes. Эти данные мы и будем резервировать.
+
Пакеты
  
 +
java-11-openjdk-devel nano git
  
Общая суть заключается в том, что мы забрасываем все volumes из определённого контейнера (в данном случае имя контейнера -- dbstore) в новый промежуточный контейнер (как можно заметить, он запускается с ключом самоуничтожения --rm), который, в свою очередь, монтирует текущий каталог пользователя (вне контейнера, на хосте, который управляет контейнерами) в каталог /backup (это уже внутри контейнера, который временно запускается). Затем происходит процедура создания архива tar из содержимого /dbdata внутри контейнера. Таким образом сам контейнер уничтожается, но в рабочем каталоге пользователя на хост-машине остаётся файл резервной копии backup.tar
+
не нужны в образе для контейнера практической работы №3, следовательно на этапе выполнения практической работы №3 их нужно убрать из команды в Dockerfile
  
docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata
+
===Оптимизация для контейнера в практической работе №3===
  
 +
Для сборки образа с готовым приложением можно использовать Runtime-платформу Java (JRE), доступную в репозитории операционной системы. Для этого нужно скорректировать Dockerfile следующим образом:
  
==Restore==
+
<pre>
 +
FROM alt:p10
 +
MAINTAINER Vasya I Pupkin <vasya@pupkin.com>
 +
RUN apt-get update -q -y \
 +
    && apt-get dist-upgrade -q -y \
 +
    && apt-get install java-11-openjdk libGL libgtk+3 libXxf86vm xorg-dri-swrast fonts-ttf-dejavu -q -y \
 +
    && apt-get autoclean \
 +
    && apt-get autoremove \
 +
    && /bin/rm /var/cache/apt/archives/*.rpm
 +
 
 +
RUN adduser app
 +
 
 +
RUN mkdir /opt/app
 +
COPY app /opt/app
 +
COPY startup.sh /
 +
RUN chmod +x /startup.sh
 +
 
 +
USER app
  
Допустим у нас есть бэкап, сделанный в предыдущем пункте и он у нас лежит в текущем каталоге и называется backup.tar
+
CMD /startup.sh
 +
</pre>
  
Теперь нам нужно этот бэкап распаковать в определённый каталог внутри контейнера. На текущем этапе нам без разницы: каталог назначения (куда мы будем распаковывать архив backup.tar) находится на volume или это маппинг каталога в каталог хостовой системы без использования volume -- смотрим на этот каталог назначения как на обычный каталог дерева внутри контейнера. При необходимости можно воспользоваться опцией
+
Шаг по загрузке Java-19 с внешнего сервера и интеграция платформы в контейнер выполнять не нужно (Java-11 будет установлена штатным для дистрибутива средством. При чём -- только JRE, т.е. без компилятора javac. Компилятор для работы приложения -- не нужен).
  
--volumes-from
+
Преимущества: не нужно отдельно закачивать платформу Java-19 и заниматься её настройкой в контейнере
 +
Недостатки: более низкая версия платформы Java (11)
  
при старте контейнера, чтобы "подкинуть" в этот контейнер volume из другого контейнера. Всё зависит от задачи.
+
Также следует обратить внимание на то, что сборка контейнера производится на другом образе операционной системы (alt:p10) -- официальный образ производителя -- и набор устанавливаемых пакетов отличается от оригинального набора, описанного в практической работе №3.
  
И так, мы собираемся распаковать backup.tar в каталог /dbdata нового контейнера. Для этого примерная команда будет выглядеть так:
+
В остальном порядок выполнения практической работы не отличается от практической работы №3.
  
docker run -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar /dbdata
+
===Оптимизация композиции контейнеров в практической работе №5===
  
Если предполагается, что контейнер, из которого даётся команда для распаковки, временный и его задача на время зацепить volume из другого контейнера (в примере этот контейнер называется dbstorecopy), то есть смысл использовать ключ самоуничтожения контейнера (--rm) и зацепить из другого контейнера volume опцией --volumes-from dbstorecopy. Тогда команда будет такой:
+
Для добавления к композе контейнера с веб-приложением phpmyadmin необходимо расширить набор сервисов в файле
  
  docker run --rm --volumes-from dbstorecopy -v $(pwd):/backup ubuntu tar xvf /backup/backup.tar /dbdata
+
  docker-compose.yaml
  
==Перемещение данных между двумя контейнерами==
+
следующим образом
Кейс для 12.12.2022
 
  
 
<pre>
 
<pre>
# [1] stop two containers
+
version: '3.9'
docker stop nntc_de_mobd_c1_1 nntc_de_mobd_c2_1
 
  
# [2] make dir for backups
+
services:
mkdir /root/containers/nntc-jupyter/backup
+
  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
  
# [3] backup dir `/opt/notebooks` from nntc_de_mobd_c1_1 to /root/containers/nntc-jupyter/backup/q.tar
+
  c2:
docker run --rm --volumes-from nntc_de_mobd_c1_1 -v /root/containers/nntc-jupyter/backup:/backup --workdir /opt/notebooks ubuntu tar -cpf /backup/q.tar .
+
    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>
  
# [4] restore dir `/opt/notebooks` in nntc_de_mobd_c2_1 from /root/containers/nntc-jupyter/backup/q.tar
 
docker run --rm --volumes-from nntc_de_mobd_c2_1 -v /root/containers/nntc-jupyter/backup:/backup --workdir /opt/notebooks ubuntu tar -xpf /backup/q.tar
 
  
# [5] start two containers
+
Относительно конфигурации, представленной в практической работе №5, был добавлен сервис c3:
docker start nntc_de_mobd_c1_1 nntc_de_mobd_c2_1
+
 
 +
 
 +
<pre>
 +
  c3:
 +
    container_name: "c3"
 +
    hostname: "c3"
 +
    image: phpmyadmin
 +
    restart: always
 +
    ports:
 +
      - 8080:80
 +
    environment:
 +
      - PMA_ARBITRARY=1
 +
    networks:
 +
      - net_c1_c2
 
</pre>
 
</pre>
 +
 +
который был подключен к той же сети, что и остальные контейнеры.
 +
 +
У сервиса c3 экспортирован 80-й порт, на котором работает веб-приложение, на порт 8080 хостовой системы.
 +
 +
Следовательно, веб-приложение phpmyadmin можен быть запущена в браузере хостовой машины по адресу
 +
 +
http://localhost:8080
 +
 +
Для подключения необходимо использовать следующие данные:
 +
 +
Сервер: c1
 +
Пользователь: root или java_app_user
 +
Пароль: 123321 или java_app_password
 +
 +
Почему так? Смотрите внимательно в файл
 +
 +
docker-compose.yaml

Текущая версия на 12:06, 12 октября 2024

Содержание

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 командой

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 и компилятора должны возвращать примерно следующее:

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

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

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 и воспользоваться клиентом mysql)

docker exec -it c1 /bin/bash

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

mysql -u java_app_user -pjava_app_password -h localhost java_app_db

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

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)

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 ...

Установка docker-compose

В хостовой системе откройте терминал и выполните команду для получения доступа под суперпользователем root

su -

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

apt-get install docker-compose -y

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

apt-get update

Практика

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

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

Оптимизации

Оптимизация для контейнера в практической работе №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