Использование docker-compose
В отличие от docker, с помощью docker-compose можно разворачивать проекты, состоящие из нескольких контейнеров, одной командой.
И так, автоматизируем запуск наших контейнеров с использованием docker-compose. Необходимо, чтобы он был .
Сначала удалим контейнеры, которые создали на предыдущих этапах:
docker rm -f web_server maria_db
Переходим в каталог для наших сборок:
cd /opt/docker/
Создаем yml-файл с инструкциями сборки контейнеров через docker-compose:
vi docker-compose.yml
—
version: «3.8»
services:
web_server:
build:
context: ./web-server/
args:
buildno: 1
container_name: web_server
restart: always
environment:
TZ: «Europe/Moscow»
ports:
— 80:80
maria_db:
image: mariadb
container_name: maria_db
restart: always
environment:
TZ: «Europe/Moscow»
volumes:
— /var/lib/docker/volumes/mariadb/_data/:/var/lib/mysql
* в формате yml очень важное значение имеют отступы. Если сделать лишний пробел, то мы получим ошибку.
* где:
- version — версия файла yml. На странице docs.docker.com представлена таблица, позволяющая понять, какую версию лучше использовать, в зависимости от версии docker (docker -v).
- services — docker-compose оперирует сервисами, где для каждого создается свой блок описания. Все эти блоки входят в раздел services.
- build — опции сборки. В нашем примере для веб-сервера мы должны собрать имидж.
- context — указываем путь до Dockerfile.
- args — позволяет задать аргументы, которые доступны только в процессе сборки. В данном примере мы используем только аргумент с указанием номера сборки.
- container_name — задаем имя, которое будет задано контейнеру после его запуска.
- restart — режим перезапуска. В нашем случае всегда, таким образом, после перезагрузки сервера, наши контейнеры запустятся.
- ports — при необходимости, указываем порт, который будет наш сервер пробрасывать запрос внутрь контейнера.
- environment — задает системные переменные. В данном примере, временную зону.
- volumes — позволяет внутрь контейнера прокинуть каталог сервера. Таким образом, важные данные не будут являться частью контейнера и не будут удалены после его остановки.
Запускаем сборку наших контейнеров с помощью docker-compose:
docker-compose build
Запускаем контейнеры в режиме демона:
docker-compose up -d
Проверяем, какие контейнеры запущены:
docker ps
При внесении изменений можно перезапускать контейнеры командой:
docker-compose up —force-recreate —build -d
Просто пересоздать контейнеры:
docker-compose restart
или только для одного из сервисов:
docker-compose restart web_server
* где web_server — название сервиса в файле docker-compose.
Как работать с образами Docker
Запуск контейнеров выполняется из образов. Изначально Docker берет образы в хабах Docker Hub (реестр образов, поддерживаемый разработчиком). Любой имеет возможность создавать и загружать собственные образы. Так что для большей части дистрибутивов и программ уже имеются необходимые образы в Docker Hub.
Приведенная ниже команда позволяет проверить, есть ли возможность получить доступ и скачивать образы в Docker Hub (на примере образа hello-world):
docker run hello-world
Этот вывод данных указывает, что Docker работает правильно:
Сначала сервис не мог найти образ hello-world на локальной машине, из-за чего ему приходилось загрузить образ в хабе (репозитории по умолчанию). После его скачивания Docker создал отдельный контейнер из образа и уже затем запускал в нем программу контейнере.
Представленные в хабе образы можно найти при помощи команд docker и search. К примеру, найти образ Ubuntu можно следующим образом:
docker search ubuntu
Далее скрипт просмотрит содержимое хаба и покажет все образы, соответствующие заданным критериям. В предложенном примере результат будет примерно таков:
Строчка OK в столбце OFFICIAL говорит о том, что образ создан и его поддержка осуществляется компанией, ответственной за этот проект. Выбрав требуемый образ, его можно скачать на компьютер, используя подкоманду pull.
Загрузка официального образа Ubuntu на компьютер выполняется такой командой:
docker pull ubuntu
По завершении операции отобразится такой результат:
Когда образ будет скачан, станет возможным выполнить запуск контейнера из образа при помощи команды run. На примере hello-world видно, что если после ввода run образ не был скачан, сначала клиент загрузит его и уже запустит контейнер с образом.
Чтобы посмотреть, какие образы были загружены на компьютер, используется команда:
docker images
Результат будет похожим на следующий:
Ниже можно увидеть, что образы для запуска контейнеров можно менять и использовать при создании других образов. Причем последние можно загрузить в Docker Hub или другие репозитории. Далее будет рассмотрено более подробно, как работать с контейнерами.
Четвёртый шаг: nginx.conf и entrypoint.sh
Перед тем как создавать эти файлы, нам понадобится папка conf. Структура в итоге выходит вот такая:
В файл entrypoint.sh вешаем запуск php-fpm, nginx и чтение лога.
#!/bin/bash echo "Запускаю nginx & php-fpm" nginx && php-fpm7.4 #Здесь мы вешаем бесконечный просмотр лога nginx который будет показывать ошибки пока контейнер запущен tail -f /var/log/nginx/error.log
Ну а файл nginx.conf заполняем практически стоковой для таких файлов конфигурацией.
server { listen 80; listen :80; server_name localhost; root /var/www/html/; location / { try_files $uri /index.php$is_args$args; } location ~ ^/index\.php(/|$) { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_index index.php; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; include fastcgi_params; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; internal; } location ~ \.php$ { return 404; } error_log /var/log/nginx/project_error.log; access_log /var/log/nginx/project_access.log; }
Очистка ресурсов
В этом учебнике описано, как создать контейнеры и образы. При желании эти ресурсы можно удалить. Ниже представлены команды, которые позволяют сделать следующее:
-
Вывести список всех контейнеров.
-
Остановить запущенные контейнеры по имени.
-
Удалить контейнер.
Затем удалите все ненужные образы на компьютере. Удалите образ, созданный с помощью файла Dockerfile, а затем удалите образ .NET Core, на основе которого был создан файл Dockerfile. Вы можете использовать значение IMAGE ID или строку в формате РЕПОЗИТОРИЙ:МЕТКА.
С помощью команды просмотрите список установленных образов.
Совет
Файлы образов могут иметь большой размер. Как правило, удаляются временные контейнеры, созданные в ходе тестирования и разработки приложения. При этом рекомендуется оставить базовые образы с установленной средой выполнения, если на ее основе вы планируете создавать другие образы.
Запуск обораза
Вы запускаете контейнер Docker, запустив образ. Существует несколько способов запуска контейнера, которые влияют на то, как легко будет управлять всеми контейнерами. Когда контейнер запускается, он обычно выполняет команду, определенную в Dockerfile. Вот Dockerfile для контейнера hello-world:
Команда просто запускает двоичный файл «hello», который был скопирован в корень контейнера при создании образа.
Foreground vs. Detached
Контейнер может работать на переднем плане, где он блокируется, пока процесс не завершится, и контейнер перестанет работать. В режиме переднего плана контейнер выводит свой вывод на консоль и может читать стандартный ввод. В отключенном режиме (когда вы указываете флаг -d), управление возвращается немедленно, а контейнер
Запуск контейнера «Без названия»
Самый простой способ запуска контейнера:
Когда вы запускаете контейнер с помощью этой команды, Docker назначает ему имя, состоящее из двух случайных слов. Например: .
Если у вас уже есть образ hello-world, то Docker запустит его. Если такого образа нет, он вытащит его из официального Docker-хранилища DockerHub, а затем запустит его. Результат должен выглядеть так:
Программа приветствия выйдет после отображения сообщения, которое завершает процесс, выполняющийся внутри контейнера, и завершает работу самого контейнера. Контейнер все еще торчит, если вы хотите подключиться к нему, изучить журналы или что-то еще. Чтобы просмотреть контейнер, вы можете запустить следующую команду:
Ниже я расскажу, как получить все контейнеры и все соответствующие параметры. Теперь давайте сосредоточимся на разделе «Names». Docker автоматически генерирует имя «clever_liskov», и мне придется использовать его или идентификатор контейнера для обращения к этому контейнеру для любых целей, таких как перезагрузка, удаление или выполнение команды.
Запуск именованного контейнера
Использование идентификаторов контейнеров или автогенерированных имен иногда неудобно. Если вы часто взаимодействуете с контейнером, который вы часто повторно создаете, тогда он получит другой идентификатор и автогенерированное имя. Кроме того, имя будет случайным.
Docker позволяет вам называть свои контейнеры, когда вы запускаете их, предоставляя аргумент командной строки «—name <имя контейнера>». В простых случаях, когда у вас есть только один контейнер на образ, вы можете назвать контейнер по имени вашего образа: .
Теперь, если мы посмотрим на процесс (я удалил clever_liskov ранее), мы увидим, что контейнер называется hello-world:
Существует несколько преимуществ для именованного контейнера:
- У вас есть стабильное имя для ваших контейнеров, которые вы используете как в интерактивном режиме, так и в сценариях.
- Вы можете выбрать значащее имя.
- Вы можете выбрать краткое имя для удобства при работе в интерактивном режиме.
- Это предотвращает случайное наличие нескольких контейнеров одного и того же образа (при условии, что вы всегда указываете одно и то же имя).
Давайте посмотрим на последний вариант. Если я попытаюсь снова запустить ту же команду запуска с тем же именем «hello-world», я получаю сообщение об ошибке:
Запуск автоматического удаления образа
По умолчанию контейнеры придерживаются. Иногда они вам не нужны. Вместо того, чтобы вручную удалять выведенные контейнеры, вы можете это автоматизировать. Аргумент командной строки сделает что нужно: .
Запуск другой команды
По умолчанию Docker запускает команду, указанную в Dockerfile , который используется для сборки образа (или непосредственно в точке входа, если команда не найдена). Вы всегда можете переопределить ее, предоставив свою собственную команду в конце команды run. Давайте запустим на образе busybox (образ hello-world не имеет исполняемого файла ):
Резюме
Комбинирование SSH с контейнерами Docker в целом считается анти-шаблоном, но по-прежнему находит свое применение в средах разработки, тестирования и унаследованных средах. Когда нет альтернативы, вы можете добавить SSH-сервер в свой контейнер, скопировать открытый ключ и подключиться через IP-адрес контейнера или привязку порта хоста.
Системные администраторы, которые хотят удаленно управлять большим количеством контейнеров Docker, могут попробовать Dockssh. Он позволяет запускать знакомые команды ssh с помощью бесшовного скрытого сопоставления с docker exec, предоставляя вам лучшее из обоих миров с использованием немодифицированных образов.
Установка Docker Desktop
если серверная часть WSL 2 поддерживается в docker Desktop для Windows, вы можете работать в среде разработки на основе linux и создавать контейнеры на основе linux, используя Visual Studio Code для редактирования кода и отладки и запуска контейнера в Microsoft Edge браузере на Windows.
Чтобы установить DOCKER (после установки WSL), выполните следующие действия.
-
Скачайте и следуйте инструкциям по установке.
-
после установки запустите приложение docker Desktop из Windows меню, а затем выберите значок docker в меню «скрытые значки» панели задач. щелкните правой кнопкой мыши значок, чтобы открыть меню команд docker, и выберите «Параметры».
-
убедитесь, что в Параметрыобщие установлен флажок «использовать ядро на основе WSL 2» .
-
выберите из установленных дистрибутивов WSL 2, для которых вы хотите включить интеграцию с docker, перейдя по: ПараметрыресурсыWSL integration.
-
Чтобы убедиться, что DOCKER установлен, откройте дистрибутив WSL (например, Ubuntu) и отобразите версию и номер сборки, введя следующее:
-
Проверьте, правильно ли работает установка, выполнив простой встроенный образ DOCKER с помощью:
Совет
Вот несколько полезных команд DOCKER для получения сведений:
- Перечислить команды, доступные в интерфейсе командной строки Docker, можно, выполнив команду .
- Просмотреть сведения о конкретной команде можно, выполнив команду .
- Перечислить образы Docker на вашем компьютере (сейчас только образ Hello-World) можно, используя следующие команды .
- Перечислите контейнеры на компьютере с помощью: или (без флага Показать все, будут отображаться только выполняющиеся контейнеры).
- Перечислите системную информацию об установке DOCKER, включая статистику и ресурсы (память ЦП & ), доступные в контексте WSL 2, с помощью:
Выполнение контейнера Windows
В этом простом примере будет создан и развернут образ контейнера «Hello World». Для вашего удобства лучше выполнять эти команды в окне командной строки с повышенными привилегиями. Не используйте интегрированную среду сценариев Windows PowerShell, так как она не работает для интерактивных сеансов с контейнерами и в результате контейнеры перестают отвечать на запросы.
-
Запустите контейнер с интерактивным сеансом из образа . Для этого введите следующую команду в окне командной строки:
-
После запуска контейнера окно командной строки переходит в контекст контейнера. Внутри контейнера мы создадим простой текстовый файл «Hello World», а затем выйдем из контейнера с помощью следующих команд:
-
Получите идентификатор контейнера, из которого вы только что вышли, выполнив команду docker ps:
-
Создайте новый образ HelloWorld с учетом тех изменений, которые внесли в первом запущенном контейнере. Для этого выполните команду docker commit, заменив идентификатором реального контейнера:
После завершения вы получите пользовательский образ, содержащий скрипт «Привет мир». Это можно проверить с помощью команды docker images.
Ниже приведен пример выходных данных.
-
Наконец, запустите новый контейнер с помощью команды docker run с параметром , который позволяет автоматически удалить контейнер по завершении работы командной оболочки (cmd.exe).
В результате Docker создает контейнер на основе образа HelloWorld. В этом контейнере Docker запускает экземпляр командной строки cmd.exe, которая считывает указанный файл и выводит его содержимое в оболочку. В конце Docker приостанавливает работу контейнера и удаляет его.
Отсоединение без остановки
Docker поддерживает комбинацию клавиш для изящного отсоединения от контейнера. Нажмите Ctrl-P, а затем Ctrl-Q, чтобы отключить соединение.
Вы вернетесь в свою оболочку, но ранее присоединенный процесс останется живым, поддерживая работу вашего контейнера. Вы можете проверить это, используя docker ps, чтобы получить список запущенных контейнеров.
Нажатие Ctrl-C или запуск команды выхода обычно завершает процесс переднего плана контейнера, если он не был специально настроен. Контейнер Docker должен иметь работающий процесс переднего плана; контейнер без него перейдет в остановленное состояние.
Запуск приложения с помощью MySQL
Приложение Todo поддерживает настройку нескольких переменных среды для указания параметров подключения MySQL. К ним относятся:
- — имя узла для работающего сервера MySQL.
- — имя пользователя, используемое для подключения.
- — пароль, используемый для подключения.
- — база данных, которая будет использоваться после подключения.
Aviso
Настройка параметров подключения с помощью переменных среды. Использование переменных среды для установки параметров подключения обычно подходит для разработки, тогда как при запуске приложений в рабочей среде это не рекомендуется. Чтобы понять причину, см. раздел Почему не следует использовать переменные среды для данных секрета.
Более безопасный механизм заключается в использовании поддержки секрета, предоставляемой платформой оркестрации контейнеров. В большинстве случаев эти секреты подключаются как файлы в работающем контейнере. Вы увидите, что многие приложения (включая образ MySQL и приложение Todo) также поддерживают переменные среды с суффиксом , который указывает на файл, содержащий файл.
Например, установка переменной приведет к тому, что приложение будет использовать содержимое файла, на который указывает ссылка, в качестве пароля подключения. Docker не делает ничего для поддержки этих переменных среды. Приложение должно знать, что нужно найти переменную и получить содержимое файла.
Используя все эти объяснения, запустите контейнер, готовый для разработки.
-
Укажите каждую из переменных среды, приведенных выше, и подключите контейнер к сети приложений (замените символы на в Windows PowerShell).
-
Если просмотреть журналы для контейнера (), вы увидите сообщение, указывающее, что используется база данных MySQL.
-
Откройте приложение в браузере и добавьте несколько элементов в список дел.
-
Подключитесь к базе данных MySQL и подтвердите, что элементы записываются в базу данных. Помните, что пароль — secret.
В оболочке MySQL выполните следующую команду:
Очевидно, что таблица будет выглядеть иначе, так как она содержит элементы. Но вы должны увидеть, что они хранятся!
Если взглянуть на расширение Docker, вы увидите, что у вас работают два контейнера приложений. Но нет никакой реальной индикации того, что они сгруппированы в одном приложении. Вы узнаете, как сделать это лучше в ближайшее время!
Запуск контейнера Docker
Запущенный ранее hello-world представляет собой пример контейнера, который открывается и закрывается после отображения тестового сообщения. При этом контейнеры предназначены для выполнения более полезных задач. Они имеют много общего с виртуальными машинами, однако требуют намного меньше ресурсов для работы.
Можно рассмотреть, как запустить контейнер при помощи последней версии образа Ubuntu. Добавление опций -i и -t предоставляет доступ в интерактивном режиме к командному процессору:
docker run -it ubuntu
Командная строка изменится, указывая на переход в контейнер, и будет выглядеть таким образом:
Следует обратить внимание, что также отображается идентификатор контейнера. Здесь это 2c88170e5391
Он понадобится позже, чтобы сообщить клиенту, какой именно удалить контейнер.
После этого можно запустить любую команду в контейнере. К примеру, можно обновить базу данных пакетов. Для этого нет необходимости пользоваться командой sudo, поскольку работа ведется от имени пользователя с root-правами:
apt update
Затем появится возможность установки приложений. Рассмотрим пример установки Node.js:
apt install nodejs
Эта команда выполнит установку Node.js в контейнер, используя репозиторий Ubuntu. По завершении установки можно проверить, была ли она успешно выполнена:
node -v
Будет показан номер текущей версии Node.js:
Проведенные изменения в контейнере распространяются только на него. Завершить работу с контейнером можно командой exit.
Аутентификация
При необходимости, мы можем настроить аутентификацию при использовании репозитория. Сначала сгенерируем сертификат с помощью утилиты htpasswd — установим ее.
* В официальной документации для генерирования файла с паролем рекомендуется применять контейнер, однако, у меня приведенная в пример команда вернула ошибку. Поэтому в данной инструкции я предлагаю универсальное решение.
а) для Ubuntu / Debian:
apt-get install apache2-utils
б) для CentOS / Red Hat:
yum install httpd-tools
Создадим каталог, в котором разместим файл с логинами и паролями:
mkdir /etc/docker/auth
Создадим пользователя:
htpasswd -Bbn repouser password > /etc/docker/auth/htpasswd
* в данном примере мы создадим пользователя repouser с паролем password. Мы поместим данные в файл /etc/docker/auth/htpasswd.
Уничтожим ранее созданный контейнер:
docker container stop registry && docker container rm -v registry
И запустим его снова с параметрами аутентификации:
docker run -d -p 5000:5000 —restart=always —name registry -v /dockerrepo:/var/lib/registry -v /etc/ssl/dmosk:/certs -v /etc/docker/auth:/auth -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/dmosk.local.pem -e REGISTRY_HTTP_TLS_KEY=/certs/dmosk.local.key -e REGISTRY_AUTH=htpasswd -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd -e «REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm» registry:2
* мы добавили:
- -v /etc/docker/auth:/auth — монтируем каталог с файлом-паролем в каталог контейнера /auth.
- -e REGISTRY_AUTH=htpasswd — указываем системную переменную для указания необходимости способа аутентификации.
- -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd — создаем переменную с путем до файла аутентификации.
- -e «REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm» — имя области аутентификации htpasswd (если я правильно понял, может быть произвольным).
Репозиторий готов. На компьютере, с которого мы захотим к нему подключиться, вводим:
docker login docrepo.dmosk.local:5000
Система запросит пароль — вводим тот, что создавали с помощью утилиты htpasswd. Теперь можно работать с нашим репозиторием. Удалим загруженный ранее образ:
docker image rm docrepo.dmosk.local:5000/nginx:latest
И загрузим его:
docker pull docrepo.dmosk.local:5000/nginx
Как пережить динамическую айпишку.
Есть аж три способа:
- использовать
—link - использовать имя контейнера и свою сеть
- использовать сетевой псевдоним
—link
Link уже сегодня считается устаревшей фичей, но при этом всё еще работает, так что иногда — почему бы и нет.
У всех контейнеров есть имя — динамически сгенерированное, либо явно заданное. Я запускал nginx контейнер без
—name параметра, поэтому Docker обозвал его вместо меня — nauseous_aryabhata. Если запустить второй контейнер с параметром
—link=nauseous_aryabhata , то он получит целую кучу переменных среды и запись в
/etc/hosts впридачу — всё для того, чтобы найти связанный контейнер:
ZSH
docker run -ti —link=nauseous_aryabhata busybox
env | grep tcp://
#NAUSEOUS_ARYABHATA_PORT=tcp://172.17.0.2:80
#NAUSEOUS_ARYABHATA_PORT_80_TCP=tcp://172.17.0.2:80
#NAUSEOUS_ARYABHATA_PORT_443_TCP=tcp://172.17.0.2:443
cat /etc/hosts | grep nauseous_aryabhata
#172.17.0.2 nauseous_aryabhata 6e47c39f797a
1 |
docker run-ti—link=nauseous_aryabhata busybox env|grep tcp// #NAUSEOUS_ARYABHATA_PORT=tcp://172.17.0.2:80 cat/etc/hosts|grep nauseous_aryabhata #172.17.0.2 nauseous_aryabhata 6e47c39f797a |
Теперь, если мне нужно отправить запрос ко второму контейнеру, можно просто воспользоваться его именем.
ZSH
wget -qO- http://nauseous_aryabhata
#<!DOCTYPE html>
#<html>
#<head>
#<title>Welcome to nginx!</title>
#<style>
#…
1 |
wget-qO-http//nauseous_aryabhata #<!DOCTYPE html> |
Использовать имя контейнера и создать свою сеть.
Что мне не нравится в приятных фичах, так это слово legacy, поэтому
—link всё-таки хорош больше с эстетической точки зрения. Есть другой способ: если не использовать bridge-сеть по умолчанию, в создать свою (user defined network), то Docker добавит к ней маленький невидимый DNS сервис, через который можно общаться внутри своей сети со всеми контейнерами по имени. И тут же быстрый пример:
Шаг первый. Создаём свою сеть:
ZSH
docker network create mynetwork
1 | docker network create mynetwork |
Шаг второй. Запускаем в этой сети nginx. В этот раз с явно указанным именем web:
ZSH
docker run -d —net=mynetwork —name=web nginx
1 | docker run-d—net=mynetwork—name=web nginx |
Шаг третий. Запустим в этой же сети еще один контейнер, и проверим, видит ли он web:
ZSH
docker run -ti —net=mynetwork busybox
wget -qO- web
#<!DOCTYPE html>
#…
1 |
docker run-ti—net=mynetwork busybox wget-qO-web #<!DOCTYPE html> |
Та-дааам!
Использовать сетевой псевдоним.
Этот способ очень похож на второй, только вместо имени контейнеру можно задать сетевой псевдоним:
ZSH
docker run -d \
—net=mynetwork \
—network-alias=webserver nginx
1 |
docker run-d\ —net=mynetwork\ —network-alias=webserver nginx |
Теперь все запросы к http://webserver встроенный DNS так же перенаправит к nginx-контейнеру. Можно также задавать одновременно и имя, и псевдоним, и использовать оба.
Сервер 1С
Внимание! Данный образ предназначен только для тестов. Для того, чтобы информация о наших кластерах сохранялась на локальном компьютере и ее можно было подключить в другой контейнер, создадим папку c:\srvinfo
Для того, чтобы информация о наших кластерах сохранялась на локальном компьютере и ее можно было подключить в другой контейнер, создадим папку c:\srvinfo
Выполним команду powershell
Все готово. Вот тут меня ждал сюрприз. Я давно использовал mssql в контейнере на тестовой машине и всегда обращался к нему по localhost. Сейчас это или поломали, или звезды так сошлись, но работать так перестало. Здесь и здесь можно почитать почему. Так что пока это чинят, либо пробрасываем контейнер в нашу сеть(при запуске контейнера указываем —network host в место кучи портов), либо определяем ip выданные внутри сети и подключаемся к ним. Для этого нужно выполнить две простых команды. В примере я буду показывать вместе с выводом
Первая команда выводит список контейнеров, вторая получает ip адрес контейнера по его id.
Итак, адреса у нас есть. Теперь открываем консоль администрирования и добавим нашу базу как обычно.
Немного теории ¶
Основная идея докера, это запуск приложений в изолированном пространстве. Виртуальные контейнеры нужны, чтобы окружение одного процесса не мешало другому. Каждый контейнер по умолчанию изолирован от других контейнеров и от машины, на которой он работает. Данные внутри контейнера существуют, пока жив сам контейнер. Если контейнер удалить, то удалятся и данные, которые в нём были. При этом образ, из которого был запущен контейнер, никак не изменится.
Именно на идеи изоляции процесса построена основная часть логики докера. Контейнер работает, пока работает начальный процесс (его называют entry point или command). Как только процесс завершается, контейнер останавливается. Это ключевое отличие докера от привычных виртуальных машин (вроде VirtualBox).
Благодаря изоляции процессов, на одной машине можно запускать много версий приложения, которое в обычных условиях будет конфликтовать. Например, можно запустить сразу MySQL 8 и MySQL 5, nodejs 8 и nodejs 10. Без докера сделать это тоже можно, но проблематичней.
Ещё одним важным отличием докера от обычных виртуальных машин является то, что он не эмулирует аппаратную часть. Он использует ресурсы системы, но изолирует сам процесс. Поэтому не рекомендуют запускать контейнеры из образов, которые были собраны под платформы, отличные от той, где запущен докер.
SSL и подключение по сети
Репозиторий образов Docker не будет работать по сети и обслуживать другие узлы, если мы не зашифруем подключения. Для этого необходимо подключить сертификат безопасности к нашему контейнеру. Рассмотрим варианты его получения и запуска последнего с нужными опциями.
Получение сертификата
Есть 4 стандартных способа получения сертификата, которые нам подойдут. У каждого из них свои преимущества и недостатки.
1. Получение бесплатного сертификата у Let’s Encrypt.
Мы можем получить бесплатный легитимный сертификат от Let’s Encrypt. Для этого наш сервер должен быть доступен из внешней сети по порту 80 (для выполнения проверки домена) или мы должны перевыпускать сертификат вручную каждые 3 месяца. Подробнее о способах получения в инструкции Получение бесплатного SSL сертификата Let’s Encrypt.
2. Покупка.
Если мы хотим получить валидный сертификат, но при этом не можем обеспечить доступность сервера по 80 порту (или не хотим заниматься ручным обновлением сертификата каждые 3 месяца), мы можем купить сертификат. Поставщиков данной услуги, достаточно, много, например REG.RU.
3. Самоподписанный сертификат.
Мы можем сгенерировать самозаверенный сертификат. Это простой способ, но такой сертификат не будет валидным, так как мы получим последовательность от узла, к которому нет доверия у разработчиков программного обеспечения.
Чтобы создать такой сертификат, вводим команды:
mkdir -p /etc/ssl/docrepo
openssl req -new -x509 -days 1461 -nodes -out /etc/ssl/docrepo/public.pem -keyout /etc/ssl/docrepo/private.key -subj «/C=RU/ST=SPb/L=SPb/O=Global Security/OU=IT Department/CN=docrepo.dmosk.local»
* первой командой мы создадим каталог, в котором разместим наши сертификаты. Второй — сам сертификат.
4. Использование внутреннего центра сертификации.
Мы также можем сгенерировать валидный для нашей внутренней инфраструктуры сертификат, используя свой центр сертификации. Подробнее читайте в инструкции Сертификат для Linux в центре сертификации Active Directory Certificate Services.
Запуск внешнего репозитория
После получения сертификата, можно поднять контейнер для обслуживания сетевых запросов. Предполагается, что наши сертификаты находятся в каталоге на сервере /etc/ssl/docrepo.
Сначала уничтожим ранее созданный:
docker container stop registry && docker container rm -v registry
И запустим новый:
docker run -d -p 5000:5000 —restart=always —name registry -v /dockerrepo:/var/lib/registry -v /etc/ssl/docrepo:/certs -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/public.pem -e REGISTRY_HTTP_TLS_KEY=/certs/private.key registry:2
* к нашей команде добавлены опции:
- -v /etc/ssl/docrepo:/certs — монтирует каталог на сервере /etc/ssl/docrepo (с сертификатами) в каталог контейнера /certs.
- -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/public.pem — создает системную переменную REGISTRY_HTTP_TLS_CERTIFICATE в контейнере, которая содержит в качестве значения путь до сертификата с открытым ключом.
- -e REGISTRY_HTTP_TLS_KEY=/certs/private.key — создает системную переменную REGISTRY_HTTP_TLS_KEY в контейнере, которая содержит в качестве значения путь до сертификата с закрытым ключом.
Подключаемся к другому компьютеру и пробуем загрузить наш образ для nginx:
docker pull docrepo.dmosk.local:5000/nginx
Если мы используем неподтвержденный сертификат (самоподписанный), то команда вернет нам ошибку:
Error response from daemon: Get https://docrepo.dmosk.local:5000/v2/: x509: certificate signed by unknown authority
Тогда на каждом компьютере, который должен обращаться к общему репозиторию Docker, открываем файл:
vi /etc/docker/daemon.json
И добавляем к настройке:
{
«insecure-registries» :
}
* где docrepo.dmosk.local:5000 — адрес и порт нашего сервера, к которому мы будем обращаться.
Перезапускаем сервис докера:
systemctl restart docker
Можно снова пробовать загрузить образ с центрального Hub-сервера.