Полный цикл в digital

Установка 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

Хост для доступа к MySQLmysql, не 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 и перезапустить контейнеры.


Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг