Установка LEMP в Docker
Создадим какую нибудь папку, где будет лежать наш проект, в ней нам нужно будет создать вот такие папки и файлы:
hosts
здесь будут храниться файлы конфигурации nginx для наших проектовimages
папка с нашими образамиlogs
здесь будет собрирать логи из разных образовmysql
в этой папке будут храниться файлы наших баз данныхwww
в этой папке будут лежать файлы наших проектов, по директории на каждый проектdocker-compose.yml
файл конфига, который соберет все в кучу
hosts/
hello-test.conf
images/
php/
php.ini
Dockerfile
logs/
mysql/
www/
hello.test/
index.php
docker-compose.yml
index.php
В папке www
создадим папку с нашим проектом, например hello.test
. В ней создадим файл index.php
со следующим содержанием:
<?
/*
* Дириктория www/hello.test/index.php
*/
phpinfo();
PHP
Давайте создадим в папке с нашими образами images
папку php
, в ней файлы php.ini
для своих определений значений конфига и Dockerfile
для настройки нашего образа.
Официальный образ PHP
не включает в себя никаких модулей, для того чтобы их включить, мы соберем собственный образ на основе официального. В файл images/php/Dockerfile
пропишем следующее:
#
# Дириктория images/php/Dockerfile
#
# Для начала указываем исходный образ, он будет использован как основа
FROM php:7.4-fpm
# RUN выполняет идущую за ней команду в контексте нашего образа. В данном случае мы установим некоторые зависимости и модули PHP. Для установки модулей используем команду docker-php-ext-install. На каждый RUN создается новый слой в образе, поэтому рекомендуется объединять команды используя &&.
RUN apt-get update && apt-get install -y \
curl \
wget \
git \
libfreetype6-dev \
libonig-dev \
libpq-dev \
libjpeg62-turbo-dev \
libmcrypt-dev \
libpng-dev \
libzip-dev \
&& pecl install mcrypt-1.0.3 \
&& docker-php-ext-install -j$(nproc) iconv mbstring mysqli pdo_mysql zip \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd \
&& docker-php-ext-enable mcrypt
# Куда же без composer'а.
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Добавим свой php.ini, можем в нем определять свои значения конфига
ADD php.ini /usr/local/etc/php/conf.d/40-custom.ini
# Указываем рабочую директорию для PHP
WORKDIR /var/www
# Запускаем контейнер
CMD ["php-fpm"]
docker-compose.yml
Docker Compose упрощает жизнь если у вас больше одного контейнера. С помощью одного, а иногда нескольких файлов, мы описываем какие контейнеры запускать, их настройки и связи между контейнерами. Начиная со второй версии docker compose поддерживает наследование и можно с его помощью описывать разные конфигурации для разных окружений. Мы сейчас не будем заострять на этом внимание, у нас одно окружение и один файл. В файл docker-compose.yml пропишем следующее:
#
# Дириктория docker-compose.yml
#
version: '2'
services:
nginx:
# используем последний стабильный образ nginx
image: nginx:latest
# слева указан порт который займет nginx в локальной ОС, справа указан дефолтный порт на котором nginx работает в контейнере
ports:
- "8000:80"
# монтируем директории, слева директории на основной машине, справа - куда они монтируются в контейнере
volumes:
- ./hosts:/etc/nginx/conf.d
- ./www:/var/www
- ./logs:/var/log/nginx
# образ nginx будет общаться с php
links:
- php
php:
# у нас свой образ для PHP, указываем путь к нему и говорим что его надо собрать
build: ./images/php
# образ PHP будет общаться с mysql
links:
- mysql
# монтируем директории, слева директории на основной машине, справа - куда они монтируются в контейнере
volumes:
- ./www:/var/www
mysql:
# образ mysql из dockerhub-хранилища
image: mysql
# слева указан порт который займет mysql в локальной ОС, справа указан дефолтный порт на котором mysql работает в контейнере
ports:
- "3306:3306"
# монтируем директории, слева директории на основной машине, справа - куда они монтируются в контейнере
volumes:
- ./mysql:/var/lib/mysql
# задаем пароль для root пользователя
environment:
MYSQL_ROOT_PASSWORD: secret
pma:
# используем последний стабильный образ phpmyadmin
image: phpmyadmin/phpmyadmin
# сообщаем контейнеру о перезапуске, если система перезагружается
restart: always
# образ phpmyadmin будет общаться с mysql
links:
- mysql:mysql
# слева указан порт который займет pma в локальной ОС, справа указан дефолтный порт на котором pma работает в контейнере
ports:
- 8183:80
# прописываем название нашего MySQL хоста, логин и пароль
environment:
PMA_HOST: mysql
MYSQL_USERNAME: root
MYSQL_ROOT_PASSWORD: secret
Nginx
Конфиг nginx для докер контейнеров ничем не отличается от обычного конфига для сайта. Стоит лишь обратить внимание на директиву fastcgi_pass
, где мы используем не путь к unix-сокету
, а адрес php:9000
. Здесь присутствует немного магии docker: php
- это хост по которому доступен наш php
контейнер внутри контейнера nginx
, ну а 9000
- порт, по которому можно достучаться до fpm-сокета
.
Мы уже сосдали тестовый проект hello.test
, создадим для этого проекта nginx
конфиг. В папке hosts
cоздадим файлик hello-test.conf
:
#
# Дириктория hosts/hello-test.conf
#
server {
index index.php;
server_name hello.test;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/hello.test;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
Hosts
Чтобы наш пробный сайт hello.test заработал в браузере, нужно не забыть добавить его в файл hosts
. Открываем C:\Windows\System32\drivers\etc
и добавляем в него:
127.0.0.1 hello.test
Mysql
Хост для доступа к MySQL
— mysql
, не localhost
, а именно mysql
. Почему нужно прописывать в настройках подключения базы именно mysql - ответ простой, это название контейнера в docker-compose
Дириктория ./mysql
- это папка в нашем проекте, куда будем складывать файлы базы, а /var/lib/mysql
- это папка, где лежит база по дефолту. По идее, можно держать базу внутри контейнера, но удобнее вытащить в свою ОС. Например, так можно будет делать бэкапы и использовать одну и ту же базу в разных проектах.
Зависимости
Обратите внимание, как мы проставляли зависимости контейнеров друг от друга:
nginx:
links:
- php
php:
links:
- mysql
mysql:
...
pma:
links:
- mysql:mysql
nginx
зависит от php
, php
, зависит от mysql
, mysql
не зависимое приложение работающие само по себе, phpmyadmin
тоже зависит от mysql
. Когда мы запустим docker-compose, увидим в консоли такой порядок, это как раз демонстрирует порядок запуска контейнеров:
- Network docker_default Created
- Container docker-mysql-1 Started
- Container docker-pma-1 Started
- Container docker-php-1 Started
- Container docker-nginx-1 Started
Запуск
Минимальная конфигурация для нашей локальной разработки готова. Осталось только запустить и проверить, работоспособность. Переходим в корень нашего проекта, где лежит файл docker-compose.yml
. Выполняем в консоли команду docker-compose up -d
и ждем. Первый запуск он самый долгий, потому что Docker должен скачать образы и собрать все в одно целое. В самом конце мы увидим заветные строки:
Starting source_mysql_1 ...
Starting source_mysql_1 ... done
Starting source_php_1 ...
Starting source_php_1 ... done
Starting source_nginx_1 ...
Starting source_nginx_1 ... done
Starting source_pma_1 ...
Starting source_pma_1 ... done
Сообщения говорят что все 4 контейнера поднялись и работают. Проверим все ли так, открываем браузер и переходим по адресу http://hello.test:8000/
, обновляем страницу и видим:
PhpMyAdmin
Открываем http://hello.test:8183
, видим привычную форму входа в PhpMyAdmin, вбиваем логин: root
и пароль: secret
, входим в интерфейс PhpMyAdmin. Но здесь нас ждет сюрприз.
Успешно зайти в PhpMyAdmin можно только один раз, при попытке входа второй раз зайти не получится. Для решения проблемы нужно сначала зайти в контейнер mysql, а потом в саму базу mysql.
Чтобы попасть в контейнер, нужно узнать его id
. Пишем в консоле команду docker ps
и видим список контейнеров, в моем случае Id
контейнера mysql
- 3825c5051ee9
.
Запускаем дополнительный процесс в контейнере, попадаем в консоль контейнера:
docker exec -it 3825c5051ee9 bash
Подключаемся к базе под root
:
mysql -uroot -proot
Выполняем запрос:
ALTER USER root IDENTIFIED WITH mysql_native_password BY 'root';
Выходим из базы данных:
exit
выходим из контейнера mysql
:
exit
Создание дополнительного хоста
Для создания дополнительного хоста нам нужно в папке www
создать папку проекта, в папке hosts
создать для него конфиг nginx
и перезапустить контейнеры.