40 KiB
[!seealso] Все части
Мы продолжаем цикл обучающих статей для начинающих системных администраторов. В серии "Настройка #LEMP сервера с помощью #docker для простых проектов" мы разберем docker и #docker-compose, рассмотрим, как поднять стек #LAMP+ #nginx с помощью docker, а также расскажем вам, в чем преимущество контейнеризации и виртуализации.
Несмотря на то, что тема уже достаточно подробно отражена в сети, мы решили подробно описать общие стандарты администрирования с нуля, поскольку регулярно получаем большое количество базовых вопросов от людей, так или иначе связанных с нашей сферой. Цель серии статей - не показать, как развернуть идеальное окружение, а лишь указать на нюансы в работе и защитить начинающих специалистов от базовых ошибок при настройке.
Серия статей будет полезна начинающим системным администраторам и инженерам, поэтому если вы опытный админ, то можете смело пропускать данный материал.
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 '^]'.
P.S.: telnet держит соединение открытым. Для того чтоб закрыть соединение с вашей стороны. Используйте комбинацию ctrl
+c
либо напишете в консоли quit
.
#:/# telnet 172.16.0.2 80
Trying 172.16.0.2...
Connected to 172.16.0.2.
Escape character is '^]'.
quit
#:/# telnet 172.16.0.2 80
Trying 172.16.0.2...
Connected to 172.16.0.2.
Escape character is '^]'.
^C
Мы видим, что соединение проходит. Теперь мы умеем присваивать имя контейнеру, 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.