Где находится docker linux

Установка и настройка Docker

Введение

Docker – это система управления контейнерами. Платформа, которая используется для запуска и работы с приложениями в контейнерах. Использование контейнеров популярно среди разработчиков, сетевых администраторов и других специалистов из-за той гибкости, которую предлагают контейнеры.

Docker имеет три важных компонента:

  • Docker Engine – клиент-серверное приложение, которое предоставляет основные возможности работы с контейнерами;
  • Docker Tools – набор инструментов для командной строки, которые используются для запуска контейнеров, создания новых образов и т.д.;
  • Docker Registry – место, где находятся образы контейнеров.

Требования

Для того чтобы выполнить необходимые действия, вам понадобятся:

  • установленная ОС Ubuntu 16.04 с пользователем, который может выполнять команды sudo, и фаерволом;
  • аккаунт Docker Hub .

По умолчанию для выполнения команды docker необходимо иметь root-привилегии. Однако команду можно выполнять и без добавления sudo, если работать от имени пользователя, который находится в группе docker.

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

Для такой настройки вам нужно ввести:

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

Шаг 1: Установка Docker

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

А затем уже перейти к установке самого Docker:

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

Она показывает информацию о Docker Engine, развернутом в окружении. Для того чтобы посмотреть версию Docker Engine и Tools, введите:

Шаг 2: Запуск контейнеров

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

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

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

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

Так как вы еще не запустили ни одного контейнера, образов пока нет. Загрузите и запустите образ:

Если вы введете команду docker run без загрузки образа, то Docker Engine все равно загрузит образ, а затем запустит его. Если вы еще раз запустите команду docker images, то увидите, что образ hello-world теперь доступен локально.

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

Тут можно увидеть несколько дополнительных ключей:

  • -p – указывает, какой порт хоста будет привязан к порту контейнера (в данном случае это 80);
  • —name – указывает имя запущенного контейнера. Если не указать этот параметр, то Docker Engine назначит случайное имя;
  • -d – указывает на то, что контейнер будет запущен в фоновом режиме.

Введите команду ниже для того, чтобы убедиться, что контейнер работает:

В выводе вы увидите, что контейнер под названием web работает по 80 порту и привязан к 80 порту хоста.

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

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

Шаг 3: Добавление хранилища для контейнеров

Контейнеры сами по себе эфемерны – всё, что находится внутри контейнера, будет потеряно после удаления этого контейнера. Для того чтобы данные существовали дольше, чем контейнер, к нему необходимо добавить том (volume). Том используется для длительного хранения нужных файлов (данных). Том – это директория файловой системы хоста.

Для начала нужно создать новую директорию:

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

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

Эта команда привязывает терминал к оболочке контейнеров в интерактивном режиме. Вы увидите, что теперь находитесь внутри контейнера. Перейдите в htdocs и создайте в нем какой-нибудь простой html-файл:

Затем выйдите из оболочки:

Выполнение команды curl localhost покажет, что веб-сервер возвращает страницу, которую вы только что создали.

К этому файлу можно не только получать доступ, но и редактировать его:

Если теперь ввести команду curl localhost, то вы увидите, что веб-сервер использует последнюю версию сайта.

Теперь удалите контейнер при помощи следующей команды:

Шаг 4: Создание образов

Вы можете не только запускать существующие образы, но и создавать собственные, а также хранить их в репозитории.

Новые образы можно создавать из существующих контейнеров. Запустите еще раз контейнер httpd и измените начальный документ:

Контейнер запущен с отредактированным файлом index.html. Проверить это можно командой curl localhost .

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

А вот после этого можно ввести команду commit, которая фактически превратит контейнер в неизменяемый образ.

Подтвердите создание образа командой docker images. Она покажет образ doweb, который только что был создан.

Вы можете присвоить образу тег, а также поместить его в Docker Hub. Для этого выполните следующие команды (вместо your_docker_hub_username нужно написать имя пользователя вашего Docker Hub):

Теперь новый образ можно найти в Docker Hub или в командной строке.

Шаг 5: Запуск частного репозитория

Если вы хотите, чтобы образы были более защищенными, то лучше использовать частный репозиторий.

Читайте также:  Устранение размытости windows 10

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

Обратите внимание на то, что контейнер запускается в фоновом режиме с использованием порта 5000, а директория registry привязана к файловой системе хоста. Используйте команду docker ps для проверки запуска контейнера.

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

Команда выше подтверждает, что контейнер busybox теперь имеет тег localhost:5000, поэтому передавайте образ в приватный репозиторий:

Теперь, когда образ отправлен, можно проделать следующее – удалить его из окружения, а потом вновь загрузить из репозитория:

Вы выполнили полный цикл работы с образом: загрузку, присвоение тега, выгрузку в репозиторий и новую загрузку.

Заключение

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

Источник

Docker: как развернуть фуллстек-приложение и не поседеть

«Нам нужен DevOps!»
(самая популярная фраза в конце любого хакатона)

Сначала немного лирики.

Когда разработчик является отличным девопсом, умеющим развернуть своё детище на любой машине под любой OC, это плюс. Однако, если он вообще ничего не смыслит дальше своей IDE, это не минус — в конце концов, деньги ему платят за код, а не за умение его разворачивать. Узкий глубокий специалист на рынке ценится выше, чем средней квалификации «мастер на все руки». Для таких, как мы, «пользователей IDE», хорошие люди придумали Docker.

Принцип Docker следующий: «работает у меня — работает везде». Единственная программа, необходимая для деплоя копии Вашего приложения где угодно — это Docker. Если Вы запустили своё приложение в докере у себя на машине, оно гарантированно с тем же успехом запустится в любом другом докере. И ничего, кроме докера, устанавливать не нужно. У меня, к примеру, на виртуальном сервере даже Java не стоит.

Как работает Docker?

Docker создаёт образ виртуальной машины с установленными в ней приложениями. Дальше этот образ разворачивается как абсолютно автономная виртуальная машина. Запущенная копия образа называется «контейнер». Вы можете запустить на сервере любое количество образов, и каждый из них будет отдельной виртуальной машиной со своим окружением.

Что такое виртуальная машина? Это инкапсулированное место на сервере с операционкой, в которой установлены приложения. В любой операционке обычно крутится большое количество приложений, в нашей же находится одно.

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

Для каждого приложения мы создаём свой образ, а потом разворачиваем каждый контейнер отдельно. Также, можно положить все приложения в один образ и развернуть как один контейнер. Причём, чтобы не разворачивать каждый контейнер отдельно, мы можем использовать отдельную утилиту docker-compose, которая конфигурирует контейнеры и взаимосвязь между ними через отдельный файл. Тогда структура всего приложения может выглядеть так:

Я намеренно не стал вносить базу данных в общую сборку Docker, по нескольким причинам. Во-первых, база данных полностью независима от приложений, которые с ней работают. Это может быть далеко не одно приложение, это могут быть ручные запросы из консоли. Лично я не вижу смысла ставить базу данных в зависимость от сборки Docker, в которой она находится. Поэтому я её и вынес. Впрочем, очень часто практикуется подход, при котором база данных помещается в отдельный образ и запускается отдельным контейнером. Во-вторых, хочется показать, как Docker-контейнер взаимодействует с системами вне контейнера.

Впрочем, довольно лирики, давайте писать код. Мы напишем простейшее приложение на спринге и реакте, которое будет записывать наши обращения к фронту в базу данных, и поднимем всё это через Docker. Структура нашего приложения будет выглядеть так:

Реализовать такую структуру можно разными путями. Мы реализуем один из них. Мы создадим два образа, запустим из них два контейнера, причём, бэкенд будет подключаться к базе данных, которая установлена на конкретном сервере где-то в интернете (да, такие запросы к базе будут ходить не быстро, но нами движет не жажда оптимизации, а научный интерес).

Пост будет разбит на части:

0. Устанавливаем Docker.
1. Пишем приложения.
2. Собираем образы и запускаем контейнеры.
3. Собираем образы и запускаем контейнеры на удалённом сервере.
4. Решаем проблемы с сетью.

0. Устанавливаем Docker

Для того, чтобы установить Docker, нужно зайти на сайт и следовать тому, что там написано. При установка Docker на удалённом сервере будьте готовы к тому, что с серверами на OpenVZ Docker может не работать. Равно как могут быть проблемы, если у Вас не включён iptables. Желательно заводить сервер на KVM с iptables. Но это мои рекомендации. Если у Вас всё заработает и так, я буду рад, что Вы не потратили кучу времени на выяснение, почему не работает, как это пришлось сделать мне.

1. Пишем приложения

Напишем простое приложение с самым примитивным бэкендом на Spring Boot, очень простым фронтендом на ReactJS и базой данных MySQL. Приложение будет иметь Single-Page с одной-единственной кнопкой, которая будет записывать время нажатия по ней в базу данных.

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

Backend на Spring Boot

LogController, который будет работать по упрощённой логике и сразу писать в базу данных. Сервис мы опускаем.

Всё, как мы видим, очень просто. По GET-запросу мы делаем запись в базу и возвращаем результат.

Читайте также:  Windows блокирует скачанные файлы

Файл настроек приложения обсудим отдельно. Их два.

Как это работает, Вы, наверняка, знаете, сначала Spring сканирует файл application.properties или application.yml — какой найдёт. В нём мы указываем одну-единственную настройку — какой профиль будем использовать. Обычно во время разработки у меня накапливается несколько профилей, и очень удобно их переключать при помощи дефолтного профиля. Далее Spring находит application.yml с нужным суффиксом и пользует его.

Мы указали датасорс, настройки JPA и, что важно, внешний порт нашего бэкенда.

Фронтенд на ReactJS

Фронтенд тоже можно посмотреть в проекте на git, а можно даже не смотреть, а клонировать и запустить.

Отдельную работу фронтенда можно проверить, скачав проект, перейдя в терминале в корневую папку проекта (туда, где лежит файл package.json) и выполнив последовательно две команды:

Конечно, для этого Вам нужен установленный Node Package Manager (npm), и это тот самый трудный путь, которого мы избегаем при помощи Docker. Если Вы всё-таки запустили проект, Вы увидите следующее окошко:

Ну да ладно, настало время посмотреть код. Укажу лишь часть, которая обращается к бэкенду.

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

Стоит акцентировать внимание на следующих пунктах:

  1. Фронт открыт внешнему миру через порт 3000. Это порт по умолчанию для React.
  2. Бэк открыт по порту 8099. Мы его задали в настройках приложения.
  3. Бэк стучится к БД через внешний интернет.

Приложение готово.

2. Собираем образы и запускаем контейнеры

Структура нашей сборки будет следующая. Мы создадим два образа — фронтенд и бэкенд, которые будут общаться друг с другом через внешние порты. Для базы мы не будем создавать образ, мы установим её отдельно. Почему так? Почему для базы мы не создаём образ? У нас есть два приложения, которые постоянно изменяются и не хранят в себе данные. База данных хранит в себе данные, и это может быть результат нескольких месяцев работы приложения. Более того, к данной базе данных может обращаться не только наше бэкенд-приложение, но и многие другие — на то она и база данных, и мы не будем её постоянно пересобирать. Опять же, это возможность поработать с внешним API, чем, безусловно, является подключение к нашей БД.

Сборка front-end

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

  1. Установить NodeJS.
  2. Скопировать приложение в определённую папку.
  3. Проинсталлировать необходимые пакеты (команда npm install).
  4. Запустить приложение командой npm start.

Именно эту последовательность действий нам и предстоит выполнить в докере. Для этого в корне проекта (там же, где находится package.json) мы должны разместить файл Dockerfile со следующим содержанием:

Разберём, что означает каждая строчка.

Этой строчкой мы даём понять докеру, что при запуске контейнера первым делом нужно будет скачать из репозитория Docker и установить NodeJS, причём, самую лёгкую (все самые лёгкие версии популярных фреймворков и библиотек в докере принято называть alpine).

В линуксе контейнера будут созданы те же стандартные папки, что и в других линуксах — /opt, /home, /etc, /usr и проч. Мы задаём рабочую директорию, с которой будем работать — /usr/app/front.

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

Копируем содержимое исходного проекта в рабочую папку контейнера.

Устанавливаем все пакеты, необходимые для запуска приложения.

Запускаем приложение командой npm start.

Именно этот сценарий будет выполнен в нашем приложении при запуске контейнера.

Давайте сразу соберём фронт. Для этого нужно в терминале, находясь в корневой папке проекта (там, где находится Dockerfile), выполнить команду:

docker — вызов приложения docker, ну, это вы знаете.
build — сборка образа из целевых материалов.
-t — в дальнейшем, приложение будет доступно по тегу, указанному здесь. Можно не указывать, тогда Docker сгенерирует собственный тег, но отличить его от других будет невозможно.
. — указывает, что собирать проект нужно именно из текущей папки.

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

Если мы видим, что последний шаг выполнен и всё Successfull, значит, образ у нас есть. Мы можем проверить это, запустив его:

Смысл этой команды, я думаю, в целом понятен, за исключением записи -p 8080:3000.
docker run rebounder-chain-frontend — означает, что мы запускаем такой-то докер-образ, который мы обозвали rebounder-chain-frontend. Но такой контейнер не будет иметь выхода наружу, ему нужно задать порт. Именно команда ниже его задаёт. Мы помним, что наше React-приложение запускается на порте 3000. Команда -p 8080:3000 указывает докеру, что нужно взять порт 3000 и пробросить его на порт 8080 (который будет открыт). Таким образом, приложение, которое работает по порту 3000, будет открыто по порту 8080, и на локальной машине будет доступно именно по этому порту.

Пусть вас не смущает запись

Так думает React. Он действительно доступен в пределах контейнера по порту 3000, но мы пробросили этот порт на порт 8080, и из контейнера приложение работает по порту 8080. Можете запустить приложение локально и проверить это.

Итак, у нас есть готовый контейнер с фронтенд-приложением, теперь давайте соберём бэкенд.

Сборка back-end.

Сценарий запуска приложения на Java существенно отличается от предыдущей сборки. Он состоит из следующих пунктов:

  1. Устанавливаем JVM.
  2. Собираем jar-архив.
  3. Запускаем его.

В Dockerfile этот процесс выглядит так:

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

Процесс сборки и запуска второго образа принципиально ничем не отличается от сборки и запуска первого.

Читайте также:  Заставки при включении для windows

Теперь, если у Вас запущены оба контейнера, а бэкенд подключён к БД, всё заработает. Напоминаю, что подключение к БД из бэкенда Вы должны прописать сами, и оно должно работать через внешнюю сеть.

3. Собираем образы и запускаем контейнеры на удалённом сервере

Для того, чтобы всё заработало на удалённом сервере, нам необходимо, чтобы на нём был уже установлен Docker, после чего, достаточно запустить образы. Мы пойдём правильным путём и закоммитим наши образы в свой аккаунт в облаке Docker, после чего, они станут доступны из любой точки мира. Конечно, альтернатив данному подходу, как и всему, что описано в посте, предостаточно, но давайте ещё немного поднажмём и сделаем свою работу хорошо. Плохо, как говорил Андрей Миронов, мы всегда успеем сделать.

Создание аккаунта на хабе Docker

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

Далее, нам нужно зайти в терминал и авторизоваться в Docker.

Вас попросят ввести логин и пароль. Если всё ок, в терминале появится уведомление, что Login Succeeded.

Коммит образов на Docker Hub

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

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

В моём случае, это выглядело так:

Мы можем проверить наличие данного образа в локальном репозитории при помощи команды:

Наш образ готов к коммиту. Коммитим:

Должна появиться запись об успешном коммите.
Делаем то же самое с фронтендом:

Теперь, если мы зайдём на hub.docker.com, мы увидим два закоммиченных образа. Которые доступны откуда угодно.

Поздравляю. Нам осталось перейди к заключительной части нашей работы — запустить образы на удалённом сервере.

Запускаем образы на удалённом сервере

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

У такого запуска есть, правда, один минус. При закрытии терминала процесс завершится и приложение прекратит работу. Чтобы этого избежать, мы можем запустить приложение в «откреплённом» режиме:

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

4. Решаем проблемы с сетью

Если Вы всё сделали правильно, Вас, возможно, ожидает самое большое разочарование на всём пути следования этому посту — вполне может так получиться, что ничего не работает. Например, у Вас всё великолепно собралось и заработало на локальной машине (как, например, у меня на маке), но при развёртывании на удалённом сервере контейнеры перестали друг друга видеть (как, например, у меня на удалённом сервере на Linux). В чём проблема? А проблема вот в чём, и я в начале о ней намекал. Как уже было сказано раньше, при запуске контейнера Docker создаёт отдельную виртуальную машину, накатывает туда Linux, и потом в этот Linux устанавливает приложение. Это значит, что условный localhost для запущенного контейнера ограничивается самим контейнером, и о существовании других сетей приложение не подозревает. Но нам нужно, чтобы:

а) контейнеры видели друг друга.
б) бэкенд видел базу данных.

Решения проблемы два.

1. Создание внутренней сети.
2. Вывод контейнеров на уровень хоста.

1. На уровне Docker можно создавать сети, причём, три из них в нём есть по умолчанию — bridge, none и host.

Bridge — это внутренняя сеть Docker, изолированная от сети хоста. Вы можете иметь доступ к контейнерам только через те порты, которые открываете при запуске контейнера командой -p. Можно создавать любое количество сетей типа bridge.

None — это отдельная сеть для конкретного контейнера.

Host — это сеть хоста. При выборе этой сети, Ваш контейнер полностью доступен через хост — здесь попросту не работает команда -p, и если Вы развернули контейнер в этой сети, то Вам незачем задавать внешний порт — контейнер доступен по своему внутреннему порту. Например, если в Dockerfile EXPOSE задан как 8090, именно через этот порт будет доступно приложение.

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

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

Подключение к базе я указал

Подключение фронта к бэку пришлось указать целиком, внешнее:

Если вы пробрасываете внутренний порт на внешний, что часто бывает для удалённых серверов, то для базы нужно указывать внутренний порт, а для контейнера — внешний порт.

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

Заключение

Есть масса способов собрать и запустить образ Docker. Интересующимся советую изучить docker-compose. Здесь мы разобрали лишь один из способов работы с докером. Конечно, такой подход поначалу кажется не таким уж и простым. Но вот пример — в ходе написания поста у меня возникли с исходящими подключениями на удалённом сервере. И в процессе дебага мне пришлось несколько раз менять настройки подключения к БД. Вся сборка и деплой умещались у меня в набор 4 строчек, после ввода которых я видел результат на удалённом сервере. В режиме экстремального программирования Docker окажется незаменим.

Как и обещал, выкладываю исходники приложений:

Источник

Оцените статью