Docker — основы

основы docker

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

Если Вы пользовались виртуальной машиной — то поймете быстрее. Поскольку, Докер это приложение, которое позволяет отделить приложения от инфраструктуры. Например, есть у Вас Windows система и Вы хотите попробовать поработать с Ubuntu. Для этого совсем не обязательно удалять свою систему и устанавливать другую. Достаточно поднять виртуальную машину: приложение внутри которого будет полноценная операционная система. Вы сможете туда зайти и посмотреть как оно там устроено. Если интересен этот вопрос — советую погуглить VMware или просто виртуальная машина.

Теперь, что касается непосредственно Docker. Он позволяет создавать мини виртуальные машины и помещать в них все что нужно для выполнения Вашего приложения вместе с самим приложением, запаковать все это в контейнер и использовать сколько угодно раз.

Например: есть у нас простое java приложение. Допустим это веб приложение, которое имеет свою реляционную базу данных. Пусть будет PostgreSQL. И еще наше приложение использует не реляционную базу (NoSql) MongoDB. В принципе, стандартный набор. Вот мы запустили наше приложение локально и полны счастья и радости. Но что если нам нужно показать приложение товарищу? Не вопрос. Мы можем сбросить ему ссылку на гит или вообще перебросить код. Вот он пытается запустить наше приложение а ему нужна база данных. Наш товарищ устанавливает PostgreSQL, потом MongoDB. Приложение запустилось.

Потом мы сбрасываем приложение другому товарищу. У него уже есть PostgreSQL, но только не версии 9.2 как у нас, а 6.4. Он не может удалить старую версию потому что у него другое приложение использует его старую версию базы. Что делать в этом случае? А что если наши товарищи — это не люди, а разные сервера?

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

Таким образом мы получаем ситуацию, когда было бы удобно использовать некую формальную оболочку, чтобы можно было запускать приложения только в ней. И чтобы можно было запускать сколько угодно таких оболочек на одном физическом сервере и чтобы они не пересекались по зависимостям. Чтобы была возможность на одной оболочке использовать базу данных версии 6.4, на другой версии 7.8, а на третьей версии 9.2.

Для вышеописанных решений и был придуман Докер. Только в контексте Docker, оболочка — это контейнер (container).

Это как аналогия с корабельным контейнером.

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

Когда нужно перевезти большое количество разного груза — его помещают в контейнер. Таким образом груз не смешивается и его очень удобно транспортировать. Это тоже самое только в разрезе запуска приложений.

С docker container (контейнером) теперь вопросов быть не должно. Это инкапсулированная среда в которой выполняются приложения.

К стати, контейнеры могут общаться как между собой так и с внешней средой.

Сам по себе пустой контейнер вещь бесполезная. Чтобы он стал полезным в него нужно положить наше приложение, а также все что нужно приложению для запуска. Основа для контейнера — образ (image).

Чтобы было понятно, образ — это набор команд которые будут выполняться для запуска контейнера. Docker images — это наполнения наших контейнеров, их содержимое. Чтобы было еще проще — это можно представить как аналогию с репозиторием кода. Например, есть определенный код на гитхаб который автор выложил для общего пользования. Например приложение на спринг бут. Это приложение может скачать и запустить любой желающий. Потому что я выложил его в общий доступ. Вы можете его скачать себе, изменить там любой участок кода и залить на свой гит аккаунт.

В контексте Docker существует Docker Hub, где также есть готовые образы, которые вы сможете себе закачать. Туда же вы сможете залить свои созданные образы. Советую там зарегистрироваться.

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

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

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

Чтобы проверить что все работает можно запустить хело ворлд команду: docker run hello-world в командной строке.

результат работы docker run hello-world
результат работы docker run hello-world

Если Вы видите результат как на скрине выше — значит докер установлен и работает корректно.

Чтобы посмотреть активные контейнеры нужно выполнить комманду docker ps

Для того, чтобы посмотреть все контейнеры которые вы когда-то запускали есть расширенная комманда: docker ps -a

Если Вы запускали комманду docker run hello-world, то после запуска docker ps -a должны увидеть этот контейнер в выводе:

результат запуска docker ps -a
результат запуска docker ps -a

CONTAINER ID — это уникальный идентификатор контейнера. По этому айди можно будет потом управлять контейнером (удалять, запускать, останавливать).

IMAGE — имя образа который запускался в этом контейнере. Для того чтобы посмотреть все образы нужно выполнить комманду docker images.

Теперь осталось контейнеризировать наше приложение чтобы увидеть результат работы докера. Предлагаю для примера использовать простое Spring Boot приложение. В данном случае, что именно мы будем отправлять в контейнер большого значения иметь не будет. Docker позволяет контейнеризировать любое приложение.

Я захожу на сайт https://start.spring.io/ выбираю зависимости веб и нажимаю сгенерировать:

генерация Spring Boot приложения
генерация Spring Boot приложения

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

простое рест приложение
простое REST приложение

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

результат работы приложения
результат работы приложения

Вот теперь мы готовы задеплоить наше приложение на Docker. У нас есть установленный и корректно работающий Докер и корректно работающее java приложение.

Для того, чтобы написать свой образ используется Dockerfile.

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

Вот пример докер файла для помещения нашего приложения в Docker:

FROM openjdk:8-jdk-alpine
#за основу взята 8 версия джавы
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

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

Команды выполняются по порядку сверху вниз. Сначала будет выполнена команда FROM. Она определяет базовый образ контейнера. В нашем примере, за базовый образ у нас openjdk:8-jdk-alpine. Ведь, для того чтобы запускать java приложения нам необходима установлена джава.

Знаком # объявляют комментарии. Это как аналогия // в java.

ARG — используется для объявления аргументов. Если брать аналогию с языком java: String file = «filename»;. В докере это будет ARG JAR_FILE=target/*.jar Где JAR_FILE — это имя переменной, а target/*.jar — ее значение. Именно в папке target находиться сгенерированный jar файл после билда мавеном.

Дальше, идет команда COPY. Она говорит докеру что нужно скопировать из папки target файл с расширением jar в контейнер и дать ему новое имя app.jar.

Хотелось бы обратить внимание на использование докер переменной. ${JAR_FILE} — переменную нужно помещать в специальный синтаксис: ${имя_файла}.

ENTRYPOINT — это команда которая принимает массив указаний, который буду выполнены после поднятия контейнера. Это один из способов получить доступ к командной строке. То что Вы поместите в массив будет выполняться в командной строке. «java»,»-jar»,»/app.jar» — будет аналогией если бы Вы просто запустили java -jar app.jar из командной строки на своем компьютере. Только теперь эта команда будет выполняться в контейнере.

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

docker build . 

Запускать ее нужно находясь в одной директории с Dockerfile. Когда докер начнет выполнять ваш файл он скачает в контейнер либы джавы, скопирует jar-ник с папки target и збилдит контейнер.

результат выполнения docker build .
результат выполнения docker build .

Запустите команду docker images чтобы увидеть вновь созданный образ:

созданный образ
созданный образ

Мы не запушили наш образ в репозиторий поэтому в строке REPOSITORY пусто. Строка TAG тоже пуста поскольку мы не задавали тегов нашему образу. Нас сейчас больше всего интересует IMAGE ID. С помощью этого айди мы можем запустить контейнер.

Для запуска контейнера существует команда docker run айди_образа. Таким образом, чтобы запустить наш контейнер нужно выполнить команду docker run 6c8a153530ff

Приложение запуститься, но при попытке получить велкам страницу http://localhost:8080/welcome мы ничего не увидим. Дело в том, что контейнер пока не доступен из-вне. Приложение работает себе внутри контейнера, но достучаться к нему можно только через контейнер. Чтобы исправить эту ситуацию нужно добавить в строку запуска порт. И теперь строка запуска будет: docker run -p 8080:8080 6c8a153530ff

результат запуска команды docker run 6c8a153530ff 
результат запуска команды docker run 6c8a153530ff

После запуска все должно работать отлично. Чтобы остановить контейнер в данном случае нужно просто нажать Ctrl+C. Теперь выполните команду docker ps -a:


Чтобы запустить контейнер в фоновом режиме нужно добавить к строке запуска флаг -d: docker run -d -p 8080:8080 6c8a153530ff

Теперь, когда Вы выполните команду docker ps, то увидите свой запущенный контейнер:

Чтобы остановить запущенный контейнер нужно воспользоваться командой: docker stop контейнер_айди.

Вот таким образом мы подняли наше java приложение в Docker. Тема докера очень обширна и многообразна. Уместить все в одну статью просто не получиться. Но, что касается основ докера — этого достаточно.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *