Переосмысляем виртуализацию java приложений при использовании Docker. Часть 2

Первая часть: часть 1

Теперь вернемся к изучению образов.

Dockerfile

Докерфайлы — это инструкции для создания образа. Инструкции определяют точку старта и действия по конфигурированию образа. Рассмотрим пример:

Листинг 1. CentOS Dockerfile

FROM scratch
MAINTAINER The CentOS Project <cloud -ops@centos.org> - ami_creator
ADD centos-7-20150616_1752-docker.tar.xz /
# Volumes for systemd
# VOLUME ["/run", "/tmp"]
# Environment for systemd
# ENV container=docker
# For systemd usage this changes to /usr/sbin/init
# Keeping it as /bin/bash for compatibility with previous
CMD ["/bin/bash"]

Как видим, большинство инструкций — это комментарии. Есть, однако, 4 инструкции, не являющиеся комментариями:

1. FROM scratch. Все Dockerfile-ы происходят от базового образа. В нашем случае, образ CentOS происходит от “scratch” — корня всех образов. В общем-то это не операция, это указание на то, что данный образ (CentOS) является одним из корневых.
2. MAINTAINER … Указывает хозяина образа. В данном случае это владелец CentOS Project.
3. ADD centos…tar.xz: Директива ADD начинает загрузку файла внутрь образа, и, если он сжат, распаковку в указанный путь. В нашем случае начнется распаковка в корень файловой системы.
4. CMD [«/bin/bash»]: Этой командой запускается Bourne Again Shell (bash).

После того, как вы получили представление о структуре dockerfile, давайте разберем такой файл для Tomcat. Иерархия файла такая:


docker-fig02

Она сложнее, чем можно ожидать, но при разборе понимаешь ее логику. Как вы уже знаете, корнем всех докерфайлов является scratch, который присутствует и тут. Первый смысловой образ — это debian:jessie. Официальные образы создаются из build pack, или стандартных образов. Это означает, что Docker не должен изобретать велосипед каждый раз при создании нового образа, ведь докер имеет прочное основание, на котором собирается новый образ. В нашем случае debian:jessie — это образ Debian который устанавливается точно так же, как CoreOS. Его докерфайл состоит из 3 строк:

Листинг 2. debian:jessie Dockerfile

FROM scratch
ADD rootfs.tar.xz /
CMD ["/bin/bash"]

Для этого образа указаны 2 зависимости CURL и Source Code Management. Для buildpack-deps:jessie-curl докерфайл такой:

Листинг 3. buildpack-deps:jessie-curl Dockerfile

FROM debian:jessie
RUN apt-get update && apt-get install -y --no-install-recommends \
                ca-certificates \
                curl \
                wget \
        && rm -rf /var/lib/apt/lists/*

Этот файл докера использует apt-get для установки curl и wget – они нужны для скачивания исходников и бинарников из интернета. Директива RUN запускает команду. В нашем случае, она обновляет библиотеки и устанавливает curl и wget.

Докерфайл для buildpack-deps:jessie-scp:

Листинг 4. buildpack-deps:jessie-scp Dockerfile

FROM buildpack-deps:jessie-curl
RUN apt-get update && apt-get install -y --no-install-recommends \
                bzr \
                git \
                mercurial \
                openssh-client \
                subversion \
        && rm -rf /var/lib/apt/lists/*

Этот файл докера устанавливает средства совместной разработки: Git, Mercurial, и Subversion.

Докерфайл для Java более навороченный:

Листинг 5. Java Dockerfile

FROM buildpack-deps:jessie-scm
# A few problems with compiling Java from source:
#  1. Oracle.  Licensing prevents us from redistributing the official JDK.
#  2. Compiling OpenJDK also requires the JDK to be installed, and it gets
#       really hairy.
RUN apt-get update && apt-get install -y unzip && rm -rf /var/lib/apt/lists/*
RUN echo 'deb http://httpredir.debian.org/debian jessie-backports main' > /etc/apt/sources.list.d/jessie-backports.list
# Default to UTF-8 file.encoding
ENV LANG C.UTF-8
ENV JAVA_VERSION 8u66
ENV JAVA_DEBIAN_VERSION 8u66-b01-1~bpo8+1
# see https://bugs.debian.org/775775
# and https://github.com/docker-library/java/issues/19#issuecomment-70546872
ENV CA_CERTIFICATES_JAVA_VERSION 20140324
RUN set -x \
        && apt-get update \
        && apt-get install -y \
                openjdk-8-jdk="$JAVA_DEBIAN_VERSION" \
                ca-certificates-java="$CA_CERTIFICATES_JAVA_VERSION" \
        && rm -rf /var/lib/apt/lists/*
# see CA_CERTIFICATES_JAVA_VERSION notes above
RUN /var/lib/dpkg/info/ca-certificates-java.postinst configure
# If you're reading this and have any feedback on how this image could be
#   improved, please open an issue or a pull request so we can discuss it!

Из него нужно обратить внимание на команду apt-get install -y openjdk-8-jdk для скачивания и установки Java и добавочные действия для того, чтоб установка была секьюрной.

И, наконец, докерфайл для Tomcat:

Листинг 6. Tomcat Dockerfile

FROM java:7-jre
ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME
# see https://www.apache.org/dist/tomcat/tomcat-8/KEYS
RUN gpg --keyserver pool.sks-keyservers.net --recv-keys \
        05AB33110949707C93A279E3D3EFE6B686867BA6 \
        07E48665A34DCAFAE522E5E6266191C37C037D42 \
        47309207D818FFD8DCD3F83F1931D684307A10A5 \
        541FBE7D8F78B25E055DDEE13C370389288584E7 \
        61B832AC2F1C5A90F0F9B00A1C506407564C17A3 \
        79F7026C690BAA50B92CD8B66A3AD3F4F22C4FED \
        9BA44C2621385CB966EBA586F72C284D731FABEE \
        A27677289986DB50844682F8ACB77FC2E86E29AC \
        A9C5DF4D22E99998D9875A5110C01C5A2F6059E7 \
        DCFD35E0BF8CA7344752DE8B6FB21E8933C60243 \
        F3A04C595DB5B6A5F1ECA43E3B7BBB100D811BBE \
        F7DA48BB64BCB84ECBA7EE6935CD23C10D498E23
ENV TOMCAT_MAJOR 8
ENV TOMCAT_VERSION 8.0.26
ENV TOMCAT_TGZ_URL https://www.apache.org/dist/tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz
RUN set -x \
        && curl -fSL "$TOMCAT_TGZ_URL" -o tomcat.tar.gz \
        && curl -fSL "$TOMCAT_TGZ_URL.asc" -o tomcat.tar.gz.asc \
        && gpg --verify tomcat.tar.gz.asc \
        && tar -xvf tomcat.tar.gz --strip-components=1 \
        && rm bin/*.bat \
        && rm tomcat.tar.gz*
EXPOSE 8080
CMD ["catalina.sh", "run"]

Строго говоря, Tomcat использует родительский докерфайл Java 7 ссылка на dockerfile (версия latest для Java = 8, как видно из докерфайла для Java – листинг 5). Докерфайл устанавливает переменные окружения CATALINA_HOME и PATH с помощью директивы ENV. После этого он создает папку CATALINA_HOME. Директива WORKDIR меняет рабочую папку на CATALINA_HOME. Команда RUN выполняет ряд действий:

1. Скачивает TAR для Tomcat
2. Скачивает контрольную сумму
3. Проверяет, была ли успешной загрузка Tomcat TAR
4. Распаковывает TAR
5. Удаляет BAT файлы (работаем в linux, как никак)
6. Удаляет TAR (если распаковка прошла нормально, он больше не нужен).

Инструкции задаются в одной команде: докер видит ее и кеширует образ, который получается при выполнении команды. У Docker есть стратегия определения, какие образы нужно пересобрать и каждая инструкция проверяется во время сборки. Результат каждого шага кешируется для оптимизации, таким образом, если последний шаг в докерфайле изменен, докер может взять за основу наиболее завершенный образ и применить к нему только последний шаг. Недостатком такого подхода является то, что при изменении одной единственной команды из цепочки придется пересобирать весь образ.

Директива EXPOSE застявляет докер выставить наружу определенный порт после запуска контейнера. Как мы уже видели, надо было задать отображение физического порта на порт контейнера (параметр -p). Теперь командой EXPOSE мы указываем доступный порт на инстансе Docker.

После всего запускаем Tomcat, выполнив catalina.sh (он ожидается в папке PATH)

Короткое повторение пройденного

Построение докерфайла от начала до Томката было долгим процессом, нужно обобщить шаги:

1. Install Debian Linux.
2. Устанавливаем curl и wget.
3. Если вам нужны системы управления версиями, ставим их
4. Скачиваем и ставим Java.
5. Скачиваем и ставим Tomcat.
6. Прокидываем порт 8080 на инстансе Docker.
7. Запускаем Tomcat catalina.sh run.

Теперь вы стали экспертом по докеру — или, по крайне мере, кем-то реально крутым!
Будем пробовать собрать кастомный образ (custom image) докера с нашим приложением.

Разворачиваем свое приложение в Docker

Данное руководство больше посвящено разворачиванию приложения на Java, нежели написанию настоящего бизнес приложения на Java. Поэтому будет устанавливаться простое приложение с сервлетом Hello World. Вы можете посмотреть проект на Github ссылка. Никаких наворотов в исходниках: сервлет выводит банальное «Hello, World!». Гораздо интереснее используемый Dockerfile ссылка:

Листинг 7. Докерфайл для сервлета

FROM tomcat
ADD deploy /usr/local/tomcat/webapps

Ключевые моменты:

FROM tomcat показывает, что докерфайл берет за основу образ Tomcat
ADD deploy /usr/local/tomcat/webapps указывает докеру скопировать файлы из deploy в /usr/local/tomcat/webapps.

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

mvn clean install

После сборки появится файл target/helloworld.war, скопируйте его в папку проекта docker/deploy (ее надо будет создать). Теперь надо создать образ по инструкциям в докерфайле. Запустите из папки docker:

docker build -t lygado/docker-tomcat .

Это инструкция сохдать новый образ из текущей папки (точка в конце команды) с тегом lygado/docker-tomcat. В данном случае lygado – это имя пользователя DockerHub, docker-tomcat – это имя образа. После выполения смотрим, что получилось:

$ docker images
REPOSITORY                      TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
lygado/docker-tomcat            latest              ccb455fabad9        42 seconds ago      849.5 MB

Образ создан, запускаем:

docker run -d -p 8080:8080 lygado/docker-tomcat

После запуска процесса смотрим работу сервлета по адресу (ваш IP может отличаться):

http://192.168.99.100:8080/helloworld/hello

Вы можете остановить этот контейнер командой docker stop INSTANCE_ID.

Отправка образа в DockerHub

Если вы протестировали собранный образ и довольны результатами, вы можете сохранить его в репозитории:

docker push lygado/docker-tomcat

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

В следующей части мы сделаем Docker частью процесса сборки: результатом сборки будет образ с нашим приложением.

Продолжение: часть 3

You can leave a response, or trackback from your own site.

Leave a Reply