
Мы продолжаем цикл обучающих статей для начинающих системных администраторов. В серии «Настройка LEMP сервера с помощью docker для простых проектов» мы разберем docker и docker-compose, рассмотрим, как поднять стек LAMP+Nginx с помощью docker, а также расскажем вам, в чем преимущество контейнеризации и виртуализации.
Несмотря на то, что тема уже достаточно подробно отражена в сети, мы решили подробно описать общие стандарты администрирования с нуля, поскольку регулярно получаем большое количество базовых вопросов от людей, так или иначе связанных с нашей сферой. Цель серии статей — не показать, как развернуть идеальное окружение, а лишь указать на нюансы в работе и защитить начинающих специалистов от базовых ошибок при настройке.
Серия статей будет полезна начинающим системным администраторам и инженерам, поэтому если вы опытный админ, то можете смело пропускать данный материал.
Итак, в этой статье мы разберем:
-
Сравнение виртуализации и контейнеризации.
-
Что такое виртуализация?
-
Для чего и когда она необходима?
-
Какие минусы виртуализации?
-
Что такое контейнеризация?
-
-
Масштабирование и его виды.
-
Горизонтальное масштабирование.
-
Когда использовать горизонтальное масштабирование?
-
Вертикальное масштабирование.
-
-
Как связаны контейнеризация и масштабирование.
-
Docker. БАЗА.
-
Устанавливаем docker.
-
Начинаем работать с контейнерами.
-
Что мы можем сделать с контейнером?
-
Как нам сделать запрос в контейнер?
-
Настройка nginx и apache2 для работы в контейнере.
-
1. Сравнение виртуализации и контейнеризации.
Что такое виртуализация?
Виртуализация — это набор инструментов, который позволяет нам разбить физический сервер на 2, 3 и более сервера. С разными операционными системами, сервисами, зависимостями, библиотеками, модулями и т.д.
Пример: У нас имеется сервер 48 CPU 128 RAM. С использованием виртуализации можно разбить физический сервер на два отдельных от друг-друга сервера.

Для чего и когда она необходима?
Чаще всего это используется для разделения DEV- и PROD-окружения, так как проводить тестирование в DEV-окружении будет более безопасно на отдельном сервере. Также это подойдет, когда необходимо развернуть сервисы, которые используют разные зависимости и библиотеки.
Пример: PROD окружение работает на php7.2+apache, а для тестов необходима площадка на php8.1+apache. В этом случае apache2 как интерпретатор php не может работать с разными версиями php, поэтому нам необходим отдельный сервер.
Какие минусы виртуализации?
-
Ограничение в ресурсах. Инструмент виртуализации не сможет добавлять виртуальные машины свыше наших физический ядер CPU и RAM.
Пример: Были созданы 2 сервера вместо одного с 20 CPU и 60 RAM. Соответственно, если необходим еще один виртуальный сервер, инструмент виртуализации сможет добавить сервер, состоящий только из 8 CPU и 8 RAM. Если в конфигурацию добавить параметры, которые будут превышать доступные ресурсы, инструмент виртуализации будет выдавать ошибку.
Пример: Вместо 8 доступных CPU будут указаны 9.
-
Резервирование ядер под виртуальную машину. Будет создана ВМ с 20 СPU, соответственно данные CPU на хост машине будут использоваться только ВМ. Ресурсы не смогут быть задействованы на физическом сервере.
-
Отказоустойчивость. Если что-то случиться с физическим сервером, то это повлияет и на наши ВМ.
Пример: Упал наш сервер. -> Упали наши виртуальные машины.
Итог: Если у нас имеются свободные ресурсы нашего физического сервера и нам необходимо новое окружение для тестов. Виртуализация нам в помощь.
Что такое контейнеризация?
Контейнеризация — это улучшенное видение виртуализации. Контейнеризация тоже позволяет создавать отдельные виртуальные машины, только с одним важным отличием: контейнеризация использует ядро операционной системы, установленной на физическом сервере. В контейнере будет запущен только тот сервис, который необходим, и ничего лишнего.
Пример: В контейнере будет исключен запуск других сервисов (например GUI), что обеспечивает минимальное потребление ресурсов.

Огромными плюсом контейнеризации также выступает быстрое развертывание контейнера, так как поднимается только базовая ОС без зависимостей и ненужных пакетов. В контейнере будет развертываться только минимальный набор библиотек, которые необходимы для запуска сервиса.
2. Масштабирование и его виды.
Представим, что у нас есть проект, который на текущий момент уже использует 90-100% ресурсов. Код на этом проекте был оптимизирован на все 100%, а значит:
-
В базе данных не имеется зависших процессов.
-
В backend нет зависших скриптов, и отсутствуют долго выполняющие команды.
-
Frontend был оптимизирован. Ресурсы, которые используются редко, были закешированны.
Итак, оптимизировать больше нечего. Как поступить?
Необходимо масштабирование сервера. Масштабирование бывает двух типов:
-
Горизонтальное
-
Вертикальное.
Горизонтальное масштабирование.
Горизонтальное масштабирование — это когда увеличиваются ресурсы сервера, добавляем RAM, увеличиваем CPU и размер дисков.
Пример:

Когда использовать Горизонтальное масштабирование?
-
Когда заканчивается дисковое пространство. Необходимо докупить дополнительные диски.
-
Когда сервисы долго отрабатывают операции ввода и вывода. Необходимо менять медленный диск на быстрый.
-
Когда слишком часто приходит OOM Killer из-за нехватки оперативной памяти. Добавляем оперативной памяти на сервер.
Вертикальное масштабирование.
Вертикальное масштабирование — это когда когда вместо увеличения ресурсов сервера сервисы переносятся на другие машины и дублируется для отказоустойчивости. Для данных целей лучше использовать разные дата-центры.
Пример:
-
Статические файлы можно вынести на отдельный сервер, либо использовать хранилище S3.
-
Базу данных можно разделить, после чего настроить репликацию. Один сервер будет работать только на чтение, другой только на запись.
-
Поиск по статическим данным нужно отправить на отдельный сервер с быстрыми дисками.

3. Как связаны контейнеризация и масштабирование?
При поднятии контейнера пишутся параметры, которые нам необходимы в контейнере. yml-файл со всеми зависимостями, модулями.
Стоит единожды настроить и написать контейнер, и он будет работать на любом сервере одинаково, с теми самими условиями, которые были заданы при написание yml-файла. То есть, написав сервис либо сервисы всего один раз, можно будет дублировать его (их) на сколько угодно серверов, и на всех серверах сервис будет работать одинаково.
Пример: Представим, что наш проект вырос, и ресурсов уже не хватает. Было принято решение арендовать новый сервер. Для нового сервера будет достаточно дублировать yml-файл, в котором будут подняты все те же самые сервисы, которые были развернуты на старом сервере. И при этом развертывание контейнеров экономит драгоценное время, которого так часто не хватает. Ведь куда приятнее развернуть новый сервер всего за пару минут, чем развертывание сервера пару недель с нуля. Поэтому контейнеризация так необходима в вертикальном масштабировании.
Для знакомства с контейнеризацией используем сервис контейнеризации docker.
Для того, чтобы понять все тонкости работы docker, для начала необходимо понять, как именно работает docker, после чего уже писать полноценный yml-файл, который позволит запускать все сервисы одной командой.
4. Docker. БАЗА.

Все настройки будут проводится на новом сервере. Поэтому для начала рекомендуем сделать базовые настройки, о которых мы писали в предыдущих статьях (если у вас новый сервер!): Статья по базовой настройке.
Устанавливаем docker:
Подготовка системы: обновляем индексы пакетов и устанавливаем нужные пакеты для использования репозиториев через HTTPS.
apt-get update apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release
Добавьте официальный GPG-ключ Docker:
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
Устанавливаем движок Docker.
Обновляем индексы пакетов и устанавливаем последнюю версию Docker Engine и containerd:
apt-get update apt-get install docker-ce docker-ce-cli containerd.io
Вся информация об установке была взята из официального мануала docker. Для установки на другие ОС и для более углубленного изучения можете ознакомится на основном сайте по ссылке.
Начинаем работать с контейнерами.
Для начала нам нужно выбрать образ для нашего контейнера. Как это сделать? Идем на сайт со всеми образами контейнеров: hub.docker.com
Пример: Нам необходим nginx. Ищем на сайте образ nginx. Заходим на официальный сайт и скачиваем самый последний образ, после чего создаем образ нашего nginx.В данном случае это будет выглядеть так:
docker pull nginx
#:~# docker pull nginx Using default tag: latest latest: Pulling from library/nginx 5eb5b503b376: Pull complete 1ae07ab881bd: Pull complete 78091884b7be: Pull complete 091c283c6a66: Pull complete 55de5851019b: Pull complete b559bad762be: Pull complete Digest: sha256:2834dc507516af02784808c5f48b7cbe38b8ed5d0f4837f16e78d00deb7e7767 Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest
Образ скачан и собран на нашем сервере. Для проверки образов, которые уже установлены и имеются на нашем сервере, используется команда:
docker images
#:/# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest c316d5a335a5 2 weeks ago 142MB
Анализируем полученную информацию:
-
REPOSITORY — репозиторий, откуда загружен и собран наш образ. В данном случае официальный образ взятый с hub.docker.com/_/nginx.
-
TAG — версия нашего nginx. У нас самая последняя версия образа.
-
IMAGE ID — ID нашего образа.
-
CREATED — дата, когда был собран данный образ и выложен в репозиторий.
-
SIZE — размер образа.
Как видим выше, имеется образ nginx самой последней стабильной версии, выложенный разработчиками nginx 14 дней назад . Он имеет id c316d5a335a5 и занимает 142 MB нашего дискового пространства.
Теперь нам необходимо запустить наш образ. Для этого нам нужно будет команда:
docker run -d "название нашего образа"
В нашем случае получится команда:
docker run -d nginx
Запускаем:
#:/# docker run nginx d9eceddb3c2b25f6863949b776cdda280f132dc0664a4b89c4fcbe9c563436e
Для проверки запущенных контейнеров используется команда:
docker ps
Проверяем наш контейнер:
#docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8d9eceddb3c2 nginx "/docker-entrypoint.…" About a minute ago Up About a minute 80/tcp fervent_allen
Контейнер запущен и работает. Анализируем полученную информацию:
-
CONTAINER ID — ID нашего контейнера.
-
IMAGE — название нашего изображения.
-
COMMAND — это инструкция которая выполняется при запуске контейнера Docker. В данную инструкцию мы можем поместить все те команды, которые необходимы запускать каждый раз при перезагрузке контейнера. Чтоб не делать данные действия вручную.
-
CREATED — дата, когда мы собрали наш контейнер
-
STATUS — текущий статус контейнера.
-
PORTS — порты которые открыты в контейнере и на которые он принимает соединение.
-
NAMES — название нашего контейнера.
Получаем такую информацию:
Имеем контейнер с id a026e61cf29b, собранный из образа под название nginx, выполняющий команды? указанные в docker-entrypoint.sh. Собранный около минуты назад и со статусом up (поднят и работает уже около минуты). Работающий порт 80 внутри контейнера и название контейнера fervent_allen.
Мы получили контейнер (мини виртуальную машину) на нашем сервере.
Что мы можем с ним сделать?
Пример: Пустить трафик на него, и nginx этот трафик обработает. Также есть возможность зайти в наш контейнер. С помощью команды:
docker exec -it <<id контейнера или его имя>> bash
#docker exec -it 8d9eceddb3c2 bash docker@/#
Это необходимо тогда, когда нам необходимо динамически изменить какие-либо параметры без перезагрузки всего контейнера.
Пример: Мы можем перечитать конфигурацию nginx в контейнере. Без перезагрузки всего контейнера.
Давайте поднимем еще один контейнер, только прокинем 80 порт на host сервер (наш физический сервер), назовем его test_nginx и возьмем самую последнюю стабильную версию nginx.
-
Для название контейнера используем ключ —name.
-
Для проброса порта используем ключ -p.
Получаем такую команду:
docker run --name test_nginx -p 80:80 -d nginx:latest
Мы не будем использовать команду docker pull, потому что данная команда не обязательна. Все образы будут скачаны автоматически при запуске docker run.
Запускаем:
#:/# docker run --name test_nginx -p 80:80 -d nginx:latest 8d14004eb99c374f8540d3494d4c31fad794a61b878a73bb516d9e794b842164
Проверяем:
#:/# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8d14004eb99c nginx:latest "/docker-entrypoint.…" 48 seconds ago Up 47 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp test_nginxx 8d9eceddb3c2 nginx "/docker-entrypoint.…" 25 minutes ago Up 25 minutes 80/tcp fervent_allen
Как видим выше, мы имеем nginx c id номером 8d14004eb99c последней версии, работающий на 80 порту хост сервера, собранный и поднятый ~48 секунд назад с названием test_nginx. Теперь все соединения, которые будут поступать на localhost:80 на хосте, будут автоматически попадать в контейнер test_nginx.
Давайте проведем последний эксперимент:
-
Прокинем логи контейнера на хост сервер. Для этого используется ключ -v.
-
Также изменим порт с 80 на 443 и название на test_nginx1.
Получается команда:
docker run -d -p 443:80 -v/var/log/nginx:/var/log/nginx/ --name test_nginx2 nginx:latesttest
Запускаем:
#:/# docker run -d -p 443:80 -v/var/log/nginx:/var/log/nginx/ --name test_nginx2 nginx:latest 4879ed36031d2b3b7fe461ca19a2784641483cb2ec727c3ed410eddc9a79bd2f
Проверяем:
#:/# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4879ed36031d nginx:latest "/docker-entrypoint.…" 44 seconds ago Up 43 seconds 0.0.0.0:443->80/tcp, :::443->80/tcp test_nginxx2 8d14004eb99c nginx:latest "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp test_nginx 8d9eceddb3c2 nginx "/docker-entrypoint.…" 28 minutes ago Up 28 minutes 80/tcp fervent_allen
Итак, у нас имеется контейнер test_nginx1, который слушает 443 порт на хост сервере. Имеет общую директорию с хост сервером /var/log/nginx. Любой файл, который будет добавлен внутри контейнера автоматически появится в /var/log/nginx на хосте. Это работает и наоборот. Любой файл, который вы добавите в /var/log/nginx на хосте, будет и в контейнере. Директория будет общей для хоста и контейнера.
Что мы имеем в итоге? У нас есть три разных контейнера. Два из которых слушают порты на хосте и один, который работает только если поступит запрос.
Как нам сделать запрос в контейнер?
Для этого необходимо знать ip адрес контейнера. Узнать его мы можем с помощью команды inspect. При запросе команды будет выдана вся информация о контейнере, но нас интересует только ip адрес. Поэтому используем данную команду:
docker inspect <ID либо Имя контейнера> | grep IPAddress
docker inspect test_nginx | grep IPAddress "SecondaryIPAddresses": null, "IPAddress": "", "IPAddress": "172.16.2.4",
Как видим выше, ip адрес нашего контейнера 172.16.2.4. Он присваиваться автоматически при создании контейнера. Он динамический, поэтому, когда будет пересобираться контейнер, ip адрес может изменится.
А если необходим статический адрес? Можно присвоить ip адрес контейнеру. Для начала создаем нашу сеть docker. Рассмотрим команду network. Чаще всего в работе вам понадобится 3 команды:
-
create — создание сети. docker network create
-
ls — просмотреть все сети docker. docker network ls
-
rm — удалить сеть docker. docker network rm
Сначала создаем сеть. Она состоит из диапазона подсети и названия сети:
docker network create --subnet=172.16.0.0/24 test
Мы имеем подсеть docker в диапазоне 172.16.0.0/24 и с названием test.
Промеряем:
#:/# docker network ls NETWORK ID NAME DRIVER SCOPE 58fcfe449655 test bridge local
Как видим выше, у нас здесь имеется:
-
NETWORK ID — id сети.
-
NAME — название сети.
-
DRIVER — драйвер сети (по умолчанию bridge).
-
SCOPE — где работает данная сеть. В данном случае она локальная.
Итак, останавливаем второй созданный нами контейнер под кодовым названием test_nginx. Для остановки используется команда stop и название контейнера:
docker stop test_nginx test_nginx
#:/# docker stop test_nginx test_nginx test_nginx
Удаляем контейнер. Для данного действия нам поможет команда rm.
docker rm test_nginx #:/# docker rm test_nginx test_nginx
Проверяем, отсутствует ли образ:
#:/# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4879ed36031d nginx:latest "/docker-entrypoint.…" 12 minutes ago Up 12 minutes 0.0.0.0:443->80/tcp, :::443->80/tcp test_nginx2 8d9eceddb3c2 nginx "/docker-entrypoint.…" 40 minutes ago Up 40 minutes 80/tcp fervent_allen
Добавляем присваивание ip адреса.
Делается это с помощью 2 ключей.
-
Ключ —net — название сети.
-
Ключ —ip — ip адрес который мы хотим присвоить из диапазона 172.16.0.0/24 нашей сети.
Получаем команду вида:
docker run -d -p 80:80 --net test --ip 172.16.0.2 --name test_nginx nginx:latest
Внимание! Не присваивайте ip адрес с единицей в конце, т.к по умолчанию это ip адрес хоста внутри докера. В нашем примере это 172.16.0.1. То есть, если вам необходимо из контейнера обратиться к хосту, в коде необходимо будет указать 172.16.0.1 вместо localhost.
Выполняем:
## docker run -d -p 80:80 --net test --ip 172.16.0.2 --name test_nginx nginx:latest b254a1d0a969543466ff77241e8add857054266997674bd6685ff22a589a34a8
Проверяем:
#:/# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b254a1d0a969 nginx:latest "/docker-entrypoint.…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp, :::80->80/tcp test_nginx 4879ed36031d nginx:latest "/docker-entrypoint.…" 16 minutes ago Up 16 minutes 0.0.0.0:443->80/tcp, :::443->80/tcp test_nginx2 8d9eceddb3c2 nginx "/docker-entrypoint.…" 43 minutes ago Up 43 minutes 80/tcp fervent_allen
Также проверяем соединение с помощью telnet, например на 80 порт в контейнере:
#:/# telnet 172.16.0.2 80 Trying 172.16.0.2... Connected to 172.16.0.2. Escape character is '^]'.
Мы видим, что соединение проходит. Теперь мы умеем присваивать имя контейнеру, ip адрес, умеем пробрасывать директории и порты.
Настройка nginx и apache2 для работы в контейнере.
Что нам понадобится для полноценной настройки?
-
Конфигурационные файлы.
-
Название контейнера.
-
Образ контейнера.
-
Директории, которые необходимо пробросить в контейнер.
-
Директории площадок (для обработки статики nginx) и кода (apache2).
-
Директория log файлов для удобства просмотра и конфигурация.
-
Порты.
-
Сеть.
Cоздадим конфигурацию apache2 и nginx для нашего проекта DOMAIN_NAME. Конфигурацию можно сохранять куда угодно. Мы привыкли, что все конфигурации docker хранятся по пути /var/apps, поэтому создаем директорию и идем туда.
mkdir /var/apps сd /var/apps mkdir apache2 nginx
Создаем конфигурацию:
touch /var/apps/apache2/DOMAIN_NAME.conf /var/apps/nginx/DOMAIN_NAME.conf
Важное уточнение: перед настройкой у вас уже должна быть настроена директория проекта по пути /var/www/DOMAIN_NAME/, создан пользователь DOMAIN_NAME и предоставлены права на данную директорию созданному пользователю. Данные работы описаны в наших предыдущих статьях.
Запускаем apache2. Открываем /var/apps/apache2/DOMAIN_NAME.conf:
mcedit /var/apps/apache2/DOMAIN_NAME.conf
Вставляем в него:
<VirtualHost *:80> ServerAdmin webmaster@DOMAIN_NAME DocumentRoot /var/www/DOMAIN_NAME/data ServerName DOMAIN_NAME.com ServerAlias www.DOMAIN_NAME.com php_admin_value session.save_path "/var/www/DOMAIN_NAME.com/sess" php_admin_value upload_tmp_dir "/var/www/DOMAIN_NAME.com/upload" php_admin_value open_basedir "/var/www/DOMAIN_NAME.com:." CustomLog /var/www/DOMAIN_NAME/log/apache2/access.log combined ErrorLog /var/www/DOMAIN_NAME/log/apache2/error.log LogLevel error <Directory "/var/www/DOMAIN_NAME/data"> AllowOverride All Options FollowSymLinks Order allow,deny Allow from all </Directory> </VirtualHost>
-
Название контейнера — apache2.
-
Образ — php:8.0-apache.
-
Директории — прокидываем площадку по пути /var/www/DOMAIN_NAME. Прокидываем log файлы по пути /var/log/apache2. Прокидываем конфигурацию по пути /var/apps/apache2/DOMAIN_NAME.conf.
-
Порты — открывать порты для apache2 нам не нужно.
-
Сеть — т.к сеть создана, присвоим ip адрес 172.16.0.3.
Получаем команду:
docker run -d --net test --ip 172.16.0.3 --name apache2 -v/var/www/DOMAIN_NAME.com:/var/www/DOMAIN_NAME.com -v/var/log/apache2:/var/log/apache2 -v/var/apps/apache2:/etc/apache2/sites-enabled php:8.0-apache
Выполняем:
#:/# docker run -d --net test --ip 172.16.0.3 --name apache2 -v/var/www/DOMAIN_NAME.com:/var/www/DOMAIN_NAME.com -v/var/log/apache2:/var/log/apache2 -v/var/apps/apache2:/etc/apache2/sites-enabled php:8.0-apache Unable to find image 'php:8.0-apache' locally 8.0-apache: Pulling from library/php 5eb5b503b376: Already exists 8b1ad84cf101: Pull complete 38c937dadeb7: Pull complete 6a2f1dc96e59: Pull complete f8c3f82c39d4: Pull complete 90fc6462bd8e: Pull complete c670d99116c9: Pull complete 268554d6fe96: Pull complete 6c29fa0d4492: Pull complete 73e23c50a259: Pull complete 81ac13c96fc2: Pull complete b60a3e623949: Pull complete dac5dd67fd59: Pull complete Digest: sha256:2a251962959a4027456d62a2f02d716b14cd6befc2c16bfdf585e581fe1d6075 Status: Downloaded newer image for php:8.0-apache e8503234b2458320b38fef304a6040ea455bce45f24fc49a90ec46652c32b45
Проверяем:
#:/var/apps/apache2# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 51eb2aea4093 php:8.0-apache "docker-php-entrypoi…" About a minute ago Up 12 seconds 80/tcp apache2
Контейнер запущен и работает.
Запускаем nginx: Открываем конфигурационный файл по пути /var/apps/DOMAIN_NAME.com.conf:
mcedit /var/apps/DOMAIN_NAME.com.conf
Вставляем:
server { listen 80; server_name DOMAIN_NAME.com www.DOMAIN_NAME.com; access_log /var/www/DOMAIN_NAME/log/nginx/access.log; error_log /var/www/DOMAIN_NAME/log/nginx/error.log; location ~ /\.(svn|git|hg) { deny all; } location ~* ^.+\.(css|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|swf)$ { root /var/www/DOMAIN_NAME/data; expires max; access_log off; } location / { proxy_pass http://172.16.0.3; # ip адрес контейнера apache2 proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; client_max_body_size 10m; client_body_buffer_size 1280k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffer_size 4k; proxy_buffers 4 32k; proxy_busy_buffers_size 64k; proxy_temp_file_write_size 64k; } }
-
Название контейнера — nginx
-
Образ — nginx:latest
-
Директории — прокидываем площадку по пути /var/www/DOMAIN_NAME.com. Прокидываем log файлы по пути /var/log/nginx. Прокидываем конфигурацию по пути /var/apps/nginx/.
-
Порты — открываем 80 на хосте.
-
Сеть — т.к. сеть создана, присвоим ip адрес 172.16.0.4.
Получается команда:
docker run -d --net test --ip 172.16.0.4 --name nginx -p 80:80 -v/var/www/DOMAIN_NAME.com:/var/www/DOMAIN_NAME.com -v/var/log/nginx:/var/log/nginx -v/var/apps/nginx:/etc/nginx/conf.d nginx:latest
Проверяем:
#:/var/apps/nginx# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ea9a37a74237 nginx:latest "/docker-entrypoint.…" 4 seconds ago Up 3 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp nginx 51eb2aea4093 php:8.0-apache "docker-php-entrypoi…" 18 minutes ago Up 17 minutes 80/tcp apache2
Мы получили два контейнера nginx и apache2, nginx слушает все соединения на 80 порту хоста и проксирует на apache2.
Проверим. Нужно добавить в файл hosts на своем ПК. (Если не знаешь, как это сделать, в интернете полно информации по этому поводу).
127.0.0.1 DOMAIN_NAME.com
Далее добавить index.php на хосте по пути /var/www/DOMAIN_NAME.com/data.
touch /var/www/DOMAIN_NAME/data/index.php
Добавить HELLO WORLD в файл:
echo HELLO WORLD > /var/www/DOMAIN_NAME.com/data/index.php
Выполним запрос с помощью curl:
curl DOMAIN_NAME.com HELLO WORLD
curl -LI DOMAIN_NAME.com HTTP/1.1 200 OK Server: nginx/1.21.6 Date: Thu, 10 Feb 2022 20:44:46 GMT Content-Type:text/html; charset=UTF-8 Connection: keep-alive X-Powered-By: PHP/8.0.15
Все работает, поздравляю!!!
Итак, в данной статье мы познакомились с контейнеризацией, ознакомились с базовыми ключами и командами. Научились искать образы на официальном сайте. Научились присваивать контейнеру ip адрес. Научились пробрасывать директории. Это вся та база, которая необходима нам в дальнейшем. Как совет — попрактикуйтесь в развертывании контейнеров. Поиграйте с образами. Настройте их работу. Так как чем больше практики, тем лучше.
Теперь мы имеем два контейнера на хосте, которые взаимодействуют между собой и работают без ошибок. Осталось только залить файлы площадки, установить mysql на хосте и начать работать. Но данный способ больше подходит для тестов. Мы можем каждый раз писать большие команды и запускать их. А если нам необходимо управлять контейнерами? Если необходимо автоматизировать развертывание контейнеров? На помощь приходит инструмент для управления несколькими контейнерами под названием docker-compose. В следующей статье мы будем рассматривать именно его.
Спасибо за уделенное время. Надеемся, статья была для вас познавательна. Если остались вопросы можете спрашивать в комментариях, мы с радостью на них ответим.
Всем удачного администрирования, и пусть ваш PROD никогда не падает!
P.S.: больше полезного материала в нашем телеграм-канале DevOps FM.
ссылка на оригинал статьи https://habr.com/ru/company/nixys/blog/661443/
Добавить комментарий