- Настройка веб-сервера в Docker (NGINX + PHP + MariaDB)
- NGINX + PHP + PHP-FPM
- Создание образа
- Запуск контейнера и проверка работы
- MariaDB
- Подключение к базе из веб-сервера
- Использование docker-compose
- Возможные проблемы
- 1. Errors during downloading metadata for repository ‘AppStream’
- Nginx как обратный прокси на Docker
- О nginx
- Об обратном прокси
- Сценарий
- 1. Докеризированный nginx:
- 2. Nginx-конфиг
- 3. Docker-compose
- 4. Как запустить
Настройка веб-сервера в Docker (NGINX + PHP + MariaDB)
По данной инструкции мы настроим наш веб сервер в Docker следующим образом:
- В качестве веб-сервера будет использоваться NGINX.
- Будет поддержка приложений на PHP.
- Мы создадим 2 контейнера Docker — один для NGINX + PHP, второй для СУБД (MariaDB).
- Веб-приложение будет зашито в контейнере. Раздел для данных MariaDB будет монтироваться в качестве volume.
Данную конфигурацию можно использовать для быстрого развертывания сайтов или для локальной разработки.
Мы будем работать в системе на базе Linux. Предполагается, что Docker уже установлен.
NGINX + PHP + PHP-FPM
Рекомендуется каждый микросервис помещать в свой отдельный контейнер, но мы (для отдельного примера) веб-сервер с интерпретатором PHP поместим в один и тот же имидж, на основе которого будут создаваться контейнеры.
Создание образа
Создадим каталог, в котором будут находиться файлы для сборки образа веб-сервера:
mkdir -p /opt/docker/web-server
Переходим в созданный каталог:
- FROM centos:8
- MAINTAINER Dmitriy Mosk
- ENV TZ=Europe/Moscow
- RUN dnf update -y
- RUN dnf install -y nginx php php-fpm php-mysqli
- RUN dnf clean all
- RUN echo «daemon off;» >> /etc/nginx/nginx.conf
- RUN mkdir /run/php-fpm
- COPY ./html/ /usr/share/nginx/html/
- CMD php-fpm -D ; nginx
- EXPOSE 80
* где:
1) указываем, какой берем базовый образ. В нашем случае, CentOS 8.
3) задаем для информации того, кто создал образ. Указываем свое имя и адрес электронной почты.
5) создаем переменную окружения TZ с указанием временной зоны (в нашем примере, московское время).
7) запускаем обновление системы.
8) устанавливаем пакеты: веб-сервер nginx, интерпретатор php, сервис php-fpm для обработки скриптов, модуль php-mysqli для работы php с СУБД MySQL/MariaDB.
9) удаляем скачанные пакеты и временные файлы, образовавшиеся во время установки.
10) добавляем в конфигурационный файл nginx строку daemon off, которая запретит веб-серверу автоматически запуститься в качестве демона.
11) создаем каталог /run/php-fpm — без него не сможет запуститься php-fpm.
13) копируем содержимое каталога html, который находится в том же каталоге, что и dockerfile, в каталог /usr/share/nginx/html/ внутри контейнера. В данной папке должен быть наше веб-приложение.
15) запускаем php-fpm и nginx. Команда CMD в dockerfile может быть только одна.
17) открываем порт 80 для работы веб-сервера.
В рабочем каталоге создаем папку html:
. а в ней — файл index.php:
* мы создали скрипт, который будет выводить информацию о php в браузере для примера. По идее, в данную папку мы должны положить сайт (веб-приложение).
Создаем первый билд для нашего образа:
docker build -t dmosk/webapp:v1 .
Новый образ должен появиться в системе:
При желании, его можно отправить на Docker Hub следующими командами:
docker login —username dmosk
docker tag dmosk/webapp:v1 dmosk/web:nginx_php7
docker push dmosk/web:nginx_php7
* первой командой мы прошли аутентификацию на портале докер-хаба (в качестве id/login мы используем dmosk — это учетная запись, которую мы зарегистрировали в Docker Hub). Вторая команда создает тег для нашего образа, где dmosk — учетная запись на dockerhub; web — имя репозитория; nginx_php7 — сам тег. Последняя команда заливает образ в репозиторий.
* подробнее про загрузку образа в репозиторий докера.
Запуск контейнера и проверка работы
Запускаем веб-сервер из созданного образа:
docker run —name web_server -d -p 80:80 dmosk/webapp:v1
Открываем браузер и переходим по адресу http:// — откроется страница phpinfo:
Наш веб-сервер из Docker работает.
MariaDB
Для запуска СУБД мы будем использовать готовый образ mariadb. Так как после остановки контейнера, все данные внутри него удаляются, мы должны подключить внешний том, на котором будут храниться наши базы.
Сначала создаем том для докера:
docker volume create —name mariadb
* в данном примере мы создали том с именем mariadb. Будет создан каталог /var/lib/docker/volumes/mariadb/_data/ на хостовом сервере, куда будут размещаться наши файлы базы.
Выполним первый запуск нашего контейнера с mariadb:
docker run —rm —name maria_db -d -e MYSQL_ROOT_PASSWORD=password -v mariadb:/var/lib/mysql mariadb
- —rm — удалить контейнер после остановки. Это первый запуск для инициализации базы, после параметры запуска контейнера будут другими.
- —name maria_db — задаем имя контейнеру, по которому будем к нему обращаться.
- -e MYSQL_ROOT_PASSWORD=password — создаем системную переменную, содержащую пароль для пользователя root базы данных. Оставляем его таким, как в данной инструкции, так как следующим шагом мы его будем менять.
- -v mariadb:/var/lib/mysql — говорим, что для контейнера мы хотим использовать том mariadb, который будет примонтирован внутри контейнера по пути /var/lib/mysql.
- mariadb — в самом конце мы указываем имя образа, который нужно использовать для запуска контейнера. Это образ, который при первом запуске будет скачан с DockerHub.
В каталоге тома должны появиться файлы базы данных. В этом можно убедиться командой:
Теперь подключаемся к командной строке внутри контейнера с сервером базы данных:
docker exec -it maria_db /bin/bash
Подключаемся к mariadb:
Меняем пароль для учетной записи root:
> SET PASSWORD FOR ‘root’@’localhost’ = PASSWORD(‘New_Password’);
Выходим из командной строки СУБД:
Выходим из контейнера:
Останавливаем сам контейнер — он нам больше не нужен с данными параметрами запуска:
docker stop maria_db
И запускаем его по новой, но уже без системной переменной с паролем и необходимостью его удаления после остановки:
docker run —name maria_db -d -v mariadb:/var/lib/mysql mariadb
Сервер баз данных готов к работе.
Подключение к базе из веб-сервера
По отдельности, наши серверы готовы к работе. Теперь настроим их таким образом, чтобы из веб-сервера можно было подключиться к СУБД.
Зайдем в контейнер с базой данных:
docker exec -it maria_db /bin/bash
Подключимся к mariadb:
Создадим базу данных, если таковой еще нет:
> CREATE DATABASE docker_db DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
* в данном примере мы создаем базу docker_db.
Создаем пользователя для доступа к нашей базе данных:
> GRANT ALL PRIVILEGES ON docker_db.* TO ‘docker_db_user’@’%’ IDENTIFIED BY ‘docker_db_password’;
* и так, мы дали полные права на базу docker_db пользователю docker_db_user, который может подключаться от любого хоста (%). Пароль для данного пользователя — docker_db_password.
Отключаемся от СУБД:
Выходим из контейнера:
Теперь перезапустим наши контейнеры с новым параметром, который будет объединять наши контейнеры по внутренней сети.
Останавливаем работающие контейнеры и удаляем их:
docker stop maria_db web_server
docker rm maria_db web_server
docker network create net1
* мы создали сеть net1.
Создаем новые контейнеры из наших образов и добавляем опцию —net, которая указывает, какую сеть будет использовать контейнер:
docker run —name maria_db —net net1 -d -v mariadb:/var/lib/mysql mariadb
docker run —name web_server —net net1 -d -p 80:80 dmosk/webapp:v1
* указав опцию —net, наши контейнеры начинают видеть друг друга по своим именам, которые мы задаем опцией —name.
Готово. Для проверки соединения с базой данных в php мы можем использовать такой скрипт:
* в данном примере мы подключаемся к базе docker_db на сервере maria_db с использованием учетной записи docker_db_user и паролем docker_db_password.
После его запуска, мы увидим либо пустой вывод (если подключение выполнено успешно), либо ошибку.
Использование docker-compose
В отличие от docker, с помощью docker-compose можно разворачивать проекты, состоящие из нескольких контейнеров, одной командой.
И так, автоматизируем запуск наших контейнеров с использованием docker-compose. Необходимо, чтобы он был установлен в системе.
Сначала удалим контейнеры, которые создали на предыдущих этапах:
docker rm -f web_server maria_db
Переходим в каталог для наших сборок:
Создаем yml-файл с инструкциями сборки контейнеров через docker-compose:
web_server:
build:
context: ./web-server/
args:
buildno: 1
container_name: web_server
restart: always
ports:
— 80:80
maria_db:
image: mariadb
container_name: maria_db
restart: always
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 — при необходимости, указываем порт, который будет наш сервер пробрасывать запрос внутрь контейнера.
- volumes — позволяет внутрь контейнера прокинуть каталог сервера. Таким образом, важные данные не будут являться частью контейнера и не будут удалены после его остановки.
Запускаем сборку наших контейнеров с помощью docker-compose:
Запускаем контейнеры в режиме демона:
docker-compose up -d
Проверяем, какие контейнеры запущены:
Возможные проблемы
Рассмотрим некоторые проблемы, которые могут возникнуть в процессе настройки.
1. Errors during downloading metadata for repository ‘AppStream’
Ошибка возникает при попытке собрать имидж на Linux CentOS 8. Полный текст ошибки может быть такой:
Errors during downloading metadata for repository ‘AppStream’:
— Curl error (6): Couldn’t resolve host name for http://mirrorlist.centos.org/?release=8&arch=x86_64&repo=AppStream&infra=container [Could not resolve host: mirrorlist.centos.org]
Error: Failed to download metadata for repo ‘AppStream’: Cannot prepare internal mirrorlist: Curl error (6): Couldn’t resolve host name for http://mirrorlist.centos.org/?release=8&arch=x86_64&repo=AppStream&infra=container [Could not resolve host: mirrorlist.centos.org]
Причина: система внутри контейнера не может разрешить dns-имена в IP-адрес.
Решение: в CentOS 8 запросы DNS могут блокироваться брандмауэром, когда в качестве серверной части (backend) стоит nftables. Переключение на iptables решает проблему. Открываем файл:
Источник
Nginx как обратный прокси на Docker
О nginx
Nginx — веб-сервер с открытыми исходными кодами наподобие Apache. Несмотря на то что nginx и Apache могут использоваться в качестве веб-серверов, их функциональность и архитектура отличаются. Ниже приведены основные функции nginx.
- HTTP-сервер.
- Балансировка нагрузки.
- Обратный прокси.
В этой статье я расскажу, как использовать nginx в качестве обратного прокси. Вся конфигурация nginx выполнена через Docker.
Об обратном прокси
Обратный прокси — промежуточный сервер, который принимает запрос клиента, ретранслирует его на backend-серверы и затем передает ответ сервера обратно клиенту.
С помощью обратного прокси можно обслуживать несколько веб-приложений (с разными доменами) на одном сервере с общедоступным IP-адресом.
Обслуживание веб-приложений с помощью nginx имеет множество преимуществ.
- Уменьшение нагрузки, поскольку nginx может равномерно распределять запросы на backend-серверы.
- Обеспечение безопасности, так как обратный прокси может скрывать существование опрашиваемых им backend-серверов.
- Увеличение производительности, так как nginx может управлять статическим контентом (картинками и CSS).
- Простота аудита и логирования с использованием единой точки доступа (порт 80 и 443).
Сценарий
«У меня есть веб-приложение, написанное на языке Scala и запущенное в Docker. Я использую его с помощью обратного прокси. Я купил домен (www.bankz.com), который будет обслуживать это веб-приложение.
Все запросы сперва поступают в nginx, затем nginx перенаправляет их в приложение Scala. В этом сценарии я использую докеризированный nginx, так как все мои веб-приложения запускаются с помощью Docker.»
Ниже перечислены шаги, которые я предпринял для внедрения и конфигурации приложения:
1. Докеризированный nginx:
Так выглядит Dockerfile для nginx-сервера
Следует заметить, что я использую адаптированный конфигурационный файл nginx nginx.conf , который настраивает работу веб-приложения.
2. Nginx-конфиг
Здесь представлена самая простая конфигурация nginx-файла.
В данной конфигурации nginx слушает порт 80 , все запросы, приходящие на домен bankz.com , перенаправляются в веб-приложение, которое запущено на http://web:3000 (web – имя контейнера моего докеризированного приложения. Я использую связанные контейнеры для установления связи между ngnix и веб-приложением).
3. Docker-compose
Я запускаю веб-приложение с помощью Docker-compose. Ниже вы увидите простейший Docker-compose-файл.
Обратите внимание, что links определяется в nginx. Связывая веб-контейнер с nginx, Docker добавляет запись хоста для web в /etc/hosts nginx- контейнера.
4. Как запустить
docker-compose up -d будет поднимать и запускать эти два контейнера. Если вы перейдете на www.bankz.com , то сайт будет отдавать веб-приложение.
После этого нужно добавить домен www.bankz.com в DNS сервер с IP машины, которая запускает nginx контейнер.
Если вы хотите протестировать контейнер в вашем локальном окружении (без DNS), добавьте запись хоста в файл /etc/hosts как показано снизу:
192.168.59.103 — IP Docker хоста, так как я запускаю Docker с помощью boot2docker на OSX. Если вы запускаете Docker без boot2docker, то можете просто дать IP машине, которая запускает nginx-контейнер.
Источник