NGINX / PHP-FPM / Percona (MySQL) DB на виртуальной машине Ubuntu

Опубликовано Опубликовано в рубрике Моим ученикам, Софт

Всем привет! Сегодняшняя статья будет посвящена подготовке рабочего места разработчика. А именно — установке и настройке LNMP-окружения на виртуальной машине в windows-среде. Всех заинтересовавшихся приглашаю под кат!

Сразу же возникает пара вопросов:

  1. Почему не взять готовый Denwer, XAMPP, Open Server?
  2. Зачем всё делать руками? Есть же Vagrant

Прежде, чем начать описание процесса, отвечу на эти вопросы по порядку.
1. В сети есть много готовых сборок веб-серверов, предназначенных для локальной разработки в windows-средах. Для начинающих разработчиков полезно использовать такие сборки, чтобы овладеть языком программирования и не заморачиваться с системным администрированием. Но очень скоро начинаются первые трудности:

  • Большинство хостингов сейчас предлагают linux-среды для размещения сайтов. Соответственно, тут же начинаются проблемы с кодировкой, адресацией и прочим.
  • Если первые проблемы устранены, то со временем возникает необходимость установки модулей PHP/Apache/NGINX для решения прикладных задач. При портировании с windows на *nix могут возникнуть проблемы с настройкой и поведением приложения.
  • PHP 5.5 и выше не умеет работать с Windows XP и ниже

2. Автоматическая сборка сервера — это здорово, удобно, круто и даёт профит при указании в резюме 😉 Но проблема в том, что любая автоматизация без понимания всех стадий технического процесса очень быстро разваливается. Поэтому сегодня с расскажу и пошаговой сборке сервера руками, чтобы в следующих статьях поговорить об автоматизации.

Итак, начнём.

Шаг №0. Скачиваем дистрибутивы.

  • VirtualBox для Windows [ скачать ] — выбирайте соответствующую разрядность для вашей операционной системы. Если Вы используете х64 систему и хотите установить x64 виртуальную машину, то необходимо проверить, что Ваш процессор имеет аппаратную поддержку виртуализации. Если это так, то в BIOS необходимо перейти к секции Processor и включить Intel Virtualization Technology (в некоторых системах может называться Virtualization Extensions) или AMD-V. После этого VirtualBox сможет работать с 64-разрядными виртуалками
  • Дистрибутив Linux [ скачать ] — начнём с наиболее простого для изучения дистрибутива : Ubuntu Server 14.04 LTS. Вообще, я предпочитаю CentOS для работы, но его преимущества безопасности и строгости становятся его же минусами для изучения с нуля.
  • Клиент для подключения через SSH — PuTTY

Шаг №1. Создаём виртуальную машину и устанавливаем ОС
После запуска программа VirtualBox встретит нас примерно таким окном:
Главное окно
В нём Вам нужно выбрать кнопку «Создать», по нажатию которой система выдаст диалоговое окно мастера создания виртуальных машин
Мастер создания виртуальной машины
Здесь нужно указать:

  • Имя виртуалки (какое больше нравится)
  • Выбрать тип ОС (нам нужна Linux)
  • Выбрать тип серверного linux-дистрибутива (у наc Ubuntu Server)
  • Указать объём доступной оперативной памяти. Тут нужно отталкиваться от требований проектов. Для скриптов при обучении с лихвой хватит 2 ГБ. Если на стадии обучения скрипты будут вылезать за лимит памяти, то что-то точно идёт не так. Можно указать и меньше, но для нашего проекта будет использоваться база данных MySQL, а она довольно прожорливая в плане RAM.
  • Дать инструкцию на создание виртуального жёсткого диска. Нам вполне хватит 10 гигабайт для стартовых проектов.

По нажатию на кнопку «Создать», система выдаст ещё одно диалоговое окно — создания виртуального жёсткого диска

Мастер создания виртуального жёсткого диска

Указываем расположение, размер, тип (VDI) по умолчанию. Формату хранения я бы уделил больше внимания.

  • Динамический жёсткий диск изначально занимает мало места на физическом носителе, но растёт по мере добавления файлов на виртуальную машину. Растёт он ровно до указанного при создании лимита.
  • Фиксированный жёсткий диск на физическом носителе сразу занимает примерно тот же объём памяти, который выделяется ему при установке.

В чём же разница? В целях обеспечения стабильности работы системы лучше использовать виртуальные жёсткие диски фиксированного размера, т.к.

  • Быстродействие ввода-вывода будет максимальным для виртуальных жестких дисков фиксированного размера, поскольку для файла не используется динамическое расширение.
  • При расширении динамического жёсткого диска на физическом носителе может закончится пространство для хранения данных, что приведёт к сбою записи.
  • Данные в файле не будут повреждены вследствие нехватки пространства на диске или прекращения подачи питания.

Итак, мы создали наш жёсткий диск и вернулись в первое диалоговое окно. Наша виртуальная машина готова к запуску. Но не торопитесь стартовать!
Нужно внести ещё несколько настроек. Выбираем нашу виртуальную машину и переходим в меню её настроек.
Настройка виртуальной машины
Нам нужно настроить подключение виртуалки к сети, а также указать ей доступ к скачанному образу операционной системы.

  1. Переходим в меню «Сеть» и выбираем тип подключения «Сетевой мост». При необходимости нужно указать сетевую карту, если у Вас их несколько.
    В данном варианте соединения адаптер выступает в роли моста между виртуальной и физической сетями. Со стороны внешней сети имеется возможность напрямую соединяться с гостевой операционной системой — это очень удобная опция.
  2. Переходим в меню «Носители -> Атрибуты -> Оптический привод» и кликаем на иконку компакт диска, чтобы выбрать наш скачанный образ на 0-вом шаге.
    Выбор образа

Вот теперь можно нажимать «ОК» и запускать виртуальную машину. При первом запуске начнётся установка ОС Ubuntu. Выбираем язык English, а на следующем шаге — Install Ubuntu Server.
На заметку: для того, чтобы вывести курсор из консоли виртуальной машины используйте комбинацию клавиш "Ctrl" + "Alt" справа.
Далее Вам будет предложено

  • Выбрать язык ОС и временную зону.
    199329c56f
    Россия находится в Other -> Europe -> Russian Federation.
    На шаге configure locales выбираем United States — en_US.UTF-8.
    Раскладку клавиатуры (Keyboard layout) можно определить автоматически.
  • Указать сетевое имя (Hostname) — поставим UbuntuDev.
  • Создать вторичного (после root — администратора) пользователя. Создадим пользователя developer с удобным паролем.
  • Зашифровать пользовательский раздел — мы пока этого делать не будем
  • Подтвердить временную зону сервера
  • Разбить диск на разделы. О том, как Linux работает с диском можно прочитать здесь. А мы подробнее рассмотрим процесс разбиения на диски.

Сначала нам нужно выбрать ручное разбиение дисков — Manual
Ручное разбиение дисков

На скриншоте ниже система предлагает выбрать диск, на котором будет создана таблица разделов. Выбираем SCSI3 и на следующем шаге подтверждаем создание новой таблицы разделов.

Создание таблицы разделов

В следующем диалоге выбираем пункт FREE SPACE
FREE SPACE
и создаём загрузочный раздел:

  1. Выбираем Create a new partition
    Create a new partition
  2. Указываем new partition size 512 MB
    Partition size
  3. Задаём type Primary
    Primary
  4. Задаём location Beginning
    Beginning
  5. Выбираем опцию Mount point и нажимаем Enter -> Указываем mount point /boot
    Mount point
    ce215845b4
  6. Устанавливаем bootable flag в on
  7. Выбираем Done setting up the partition

Теперь создадим логические разделы для данных и файл подкачки (swap). Я рекомендую создать следующие логические разделы:

  • /data — здесь у нас будут лежать скрипты и база данных. В больших системах стоит разделять эти вещи.
  • /tmp — здесь будут накапливаться временные файлы
  • /var/log — для больших систем стоит отделить раздел логов, чтобы он не мешал основной системе, но для нас это некритично.

Выбираем снова FREE SPACE -> Create a new partition. Укажем для раздела данных размер в 5 GB

Тип указываем Logical, location — beginning, Mount point -> Enter manually -> /data . В остальном всё по умолчанию. Заканчиваем создание, выбрав Done setting up the partition.
Точно также создаём раздел /tmp на 512 MB, указав в конце mount point /tmp.
Ещё 4 гигабайта выделим под корневой раздел ( «/» ) — там у нас будут храниться файлы БД.

У нас осталось около 0.7 GB места. Выделим его под раздел подкачки. Для того, чтобы сделать это, на последнем шаге в пункте Use as выбираем значение swap area
swap area

В итоге должна получиться примерно следующая картинка
Disk parts

Разметка завершена, выбираем Finish partitioning and write changes to disk

Далее установщик предложит Вам указать настройки прокси-соединения. Если Вы не используете прокси, то просто пропустите этот шаг (Continue). Если же прокси есть, то заполните поля согласно настройкам Вашего прокси-соединения.

На следующем шаге Вам предложат выбрать автоматическую установку обновлений безопасности. Рекомендую оставить этот пункт в значении «No automatic updates», если Вы не уверены, что обновления не будут мешать Вам жить. Ведь каждое обновление потенциально приносит несовместимость с текущей системой.
No updates, please!

Теперь установщик попросит указать пакеты, которые потребуется установить. Выбираем только OpenSSH Server (с помощью пробела). Остальное установим сами в нужных версиях.
Перед завершением установки Ubuntu попросит добавить системный загрузчик GRUB в главную загрузочную запись. Выбираем Yes и продолжаем.

На этом установка закончена. Система предупредит о том, что нужно вынуть (для нас — размонтировать) установочный диск. Это можно сделать из меню VitrualBox -> Настройки -> Носители -> Атрибуты -> Оптический привод.
Нажимаем Continue.
После перезагрузки в том самом окне GRUB выбираем Ubuntu для загрузки.
GRUB

Система запросит логин и пароль. Входим под пользователем developer, которого мы создали в процессе установки. Мы внутри! 🙂
Ubuntu

Шаг №2. Оптимизируем взаимодействие с ОС и устанавливаем пакеты.
Посмотрим, какой IP нам был присвоен с помощью команды
ifconfig
В моём случае это 172.20.4.14
IP адрес

Запустим ssh (если он не запускался) и добавим его к автозапуску

service ssh start
update-rc.d ssh defaults

Теперь можно запустить скачанную на шаге №0 утилиту PuTTy и использовать её для соединения с сервером. Её интерфейс гораздо удобнее работы через VirtualBox.
PuTTy выглядит следующим образом:
PuTTy

Вводим полученный IP в поле Host Name (or IP address). Используем порт 22 — это порт для соединений SSH по умолчанию. Нажимаем Open.
Логинимся под пользователем developer. Теперь можно заниматься установкой нужных нам пакетов.

Нам потребуются:

  1. NGINX — веб-сервер для обработки пользовательских запросов
  2. PHP-FPM. Для установленной мной версии Ubuntu 14.04 LTS актуальной версией PHP является 5.5.9
  3. Percona DB — форк движка MySQL. Более стабильный и производительный

На заметку: более "классической" является сборка Apache + NGINX + PHP, где все запросы принимаются с помощью NGINX как реверс-прокси (он либо отдаёт статические файлы, либо направляет запрос к Apache, который взаимодействует с PHP). Связка более ресурсоёмкая, но и менее уязвима за счёт добавления слоя Apache. NGINX менее требователен к ресурсам.

Устанавливаем NGINX
В Ubuntu 14.04 LTS по умолчанию доступен NGINX версии 1.4 (на момент написания статьи). Это устаревшая версия, мы поставим максимально совместимую — 1.8.
Для этого нужно выполнить команду
sudo su
чтобы включить root-привилегии. Система запросит пароль пользователя developer. Теперь root активен.

Сначала скачаем ключ, которым подписан пакет NGINX, с официального сайта по ссылке.
Откроем ключ в блокноте, скопируем его и перейдём обратно в консоль. Запустим текстовый редактор vi:
vi nginx.key
NGINX key
Дальше нажимаем комбинацию клавиш Shift + Insert — она произведёт вставку из буфера обмена. Теперь нажимаем Ctrl + C, курсор переключится на нижнюю строку экрана. В нижней строке набираем
:wq
Это команда на сохранение и выход. Всё, ключ на виртуалке.
Теперь добавим его к установщику, а также подключим официальные репозитории nginx.

apt-key add nginx.key
echo "deb http://nginx.org/packages/ubuntu/ trusty nginx" >> /etc/apt/sources.list
echo "deb-src http://nginx.org/packages/ubuntu/ trusty nginx" >> /etc/apt/sources.list
apt-get update

Можно ставить NGINX
apt-get install nginx

После установки можем проверить версию
nginx -v

Должно получиться что-то вроде
nginx version: nginx/1.8.1

Устанавливаем Percona DB
Мы будем устанавливать Percona версии 5.6, где InnoDB, как известно, уже умеет делать FullText индексы, а MyISAM уже и не нужен.
Скачиваем пакет репозиториев Percona
wget https://repo.percona.com/apt/percona-release_0.1-3.$(lsb_release -sc)_all.deb

И устанавливаем его
dpkg -i percona-release_0.1-3.$(lsb_release -sc)_all.deb

Обновляем список репозиториев. Не забываем, что находимся под root-ом!
apt-get update

Теперь можно поставить пакет БД
apt-get install percona-server-server-5.6

В процессе установки система запросит пароль root-пользователя для БД

Устанавливаем PHP-FPM
Тут всё достаточно просто
apt-get install php5-fpm php5-cli php5-mysql php5-gd

Проверяем установку
php -v

Должно получиться
PHP 5.5.9-1ubuntu4.14 (cli) (built: Oct 28 2015 01:34:46)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies

Заодно добавил PHP-FPM в автозагрузку командой

update-rc.d php5-fpm defaults

Шаг №3. Настраиваем пакеты и их взаимодействие
Теперь мы можем приступить непосредственно к настройке установленных пакетов для того, чтобы начать работу.
Настраиваем NGINX
Веб-сервер NGINX многопоточен. Согласно документации NGINX количество дочерних процессов веб-сервера должно быть равно количеству ядер процессора в системе.
Давайте узнаем, сколько ядер процессоров есть у нас
cat /proc/cpuinfo | grep processor | wc -l
На моей виртуальной машине доступно 1 ядро. Я отредактирую файл nginx.conf
nano nginx.conf
И выставлю значение

worker_processes 1;

В конец файла добавим ссылку на подключение директории виртуальных хостов

include /etc/nginx/sites-enabled/*;

Сохраняем файл через Ctrl + O.

Если проект должен быть доступен через браузер, то нужно создать виртуальный хост, который будет обслуживать наш проект.
Создадим директорию проекта в разделе /data

mkdir /data/myproject.com
mkdir /data/myproject.com/docs
mkdir /data/myproject.com/logs
chown -R nginx:nginx /data/myproject.com
chmod -R 0775 /data/myproject.com

Теперь создаём настройку для нашего виртуального хоста
nano /etc/nginx/sites-available/myproject.com

Ниже я привожу код конфигурации виртуального хоста.
server {
# слушаем стандартный порт HTTP
listen 80;
# здесь нужно указать наш домен
server_name myproject.com www.myproject.com;
# кодировка по умолчанию
charset utf-8;
# для разработки потребуются логи
access_log /data/myproject.com/logs/access.log combined;
error_log /data/myproject.com/logs/error.log;
# корневая директория логики
root /data/myproject.com/docs;
# установим сжатие данных
gzip on;
gzip_disable "msie6";
gzip_comp_level 6;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_proxied any;
gzip_types text/plain application/xml
application/javascript
text/css
text/js
text/xml
application/x-javascript
text/javascript
application/json
application/xml+rss;
# настройки размеров и таймаутов
client_max_body_size 100m;
client_body_buffer_size 128k;
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;
client_header_buffer_size 1k;
large_client_header_buffers 4 16k;
# правила обработки запросов к домену
location / {
# корневая директория
root /data/myproject.com/docs;
# стартовый скрипт
index index.php;
# правило автозагрузки в порядке следования: файл, папка, скрипт
try_files $uri $uri/ @fallback;
}
# правило для того, чтобы отдавать статические файлы
location ~* \.(jpeg|ico|jpg|gif|png|css|js|pdf|txt|tar|gz|wof|csv|zip|xml|yml) {
access_log off;
try_files $uri @statics;
expires 14d;
add_header Access-Control-Allow-Origin *;
add_header Cache-Control public;
root /data/myproject.com/docs;
}
location @statics {
rewrite ^/(\w+)/(.*)$ /$2 break;
access_log off;
rewrite_log off;
expires 14d;
add_header Cache-Control public;
add_header Access-Control-Allow-Origin *;
root /data/myproject.com/docs;
}
# правила обработки PHP-скриптов
location ~ \.php$ {
root /data/myproject.com/docs;
proxy_read_timeout 120;
fastcgi_read_timeout 120;
try_files $uri $uri/ =404;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

Активируем виртуальный хост
ln -s ../sites-available/myproject.com

Добавим пользователя nginx в группу www-data, чтобы NGINX мог получить доступ к сокету PHP
usermod -a -G www-data nginx

Перезапустим NGINX
service nginx restart

Настраиваем Percona
Любой MySQL движок использует файл /etc/my.cnf , но у Percona его по умолчанию нет.
Создадим его

touch /etc/my.cnf

Внесём настройки

[client]
# порт и сокет для клиента
port = 3306
socket = /var/run/mysqld/mysqld.sock
[mysqld]
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
datadir = /var/lib/mysql
# Отдадим под innodb четверть памяти. Настройка эта зависит от объёма данных в формате innodb
# Но в идеале нужно всегда устанавливать значение больше, чем полный объём данных в innodb
innodb_buffer_pool_size = 512M
# У нас один процессор, поэтому будет только 1 поток кэша
innodb_buffer_pool_instances = 1
# Чтобы innodb работал быстрее, отключаем запись резервных данных на жёсткий диск
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = 'O_DIRECT'

Сохраним файл. Для того, чтобы применить более тонкие настройки, можно воспользоваться утилитой mysqltuner.

Зайдём на сервер MySQL. Пароль рута был задан при установке.
mysql -uroot -p

Посмотрим, что за пользователи созданы по умолчанию

use mysql;
select * from user;

Как видим, полно всего ненужного.
MySQL users

Удаляем пользователей, оставляя только root@localhost

drop user 'root'@'ubuntudev';
drop user 'root'@'127.0.0.1';
drop user 'root'@'::1';
drop user ''@'localhost';
drop user ''@'ubuntudev';
flush privileges;

Теперь создадим базу данных и пользователя для нашего PHP-приложения. Разумеется, пароль задаём свой.

create database application_db;
create user 'connect'@'localhost' identified by 'password';
grant SELECT, INSERT, UPDATE, DELETE on application_db.* to 'connect'@'localhost';
flush privileges;

Пользователь создан, права обновлены. Теперь можно будет спокойно соединяться с базой и работать с данными.

Настраиваем PHP
Зачастую нужно использовать PHP не только для генерации страниц, но и для выполнения команд из консоли.
При этом используются разные модули PHP и, как следствие, разные конфигурационные файлы. Для удобства сделаем один файл конфигурации и ссылки на него из модулей. Выполним поочерёдно команды

mv /etc/php5/fpm/php.ini ../
rm /etc/php5/fpm/php.ini
rm /etc/php5/cgi/php.ini
cd /etc/php5/fpm
ln -s /etc/php5/php.ini
cd /etc/php5/cgi
ln -s /etc/php5/php.ini

В файле /etc/php5/fpm/php.ini находим параметры и вносим изменения

short_open_tag = On
cgi.fix_pathinfo = 0
date.timezone = Europe/Moscow

Перезагружаем PHP-FPM
service php5-fpm restart

Шаг №4. Взлетит?
Теперь попробуем написать что-нибудь на PHP и проверить работоспособность результата нашей долгой работы.
Перейдём в директорию проекта

cd /data/myproject.com/docs

Создадим там простенький файл index.php с содержимым


Теперь пропишем привязку хоста к доменному имени. Если Вы работаете под Windows, то с правами администратора откройте файл
C:\Windows\System32\drivers\etc\hosts
и добавьте туда строчку
172.20.4.14 myproject.com

Разумеется, нужно заменить 172.20.4.14 на IP, выданный Вам сетью.
Сохраняем файл, открываем браузер и набираем myproject.com.

Если всё сделано правильно, то результатом будет вот такая картинка
Результат

Шаг №5. Работа с файлами
А какой прок от виртуалки, если нет возможности удобно работать с файлами на ней?
Можно подключить общий диск или смонтировать USB устройство. Но гораздо удобнее использовать Samba для коннекта между win и *nix.

Установим пакет
apt-get install samba

Теперь нужно произвести настройки в файле /etc/samba/smb.conf . Добавляем в конец файла строки

[my-projects]
comment = My projects
path = /data/
valid users = developer
create mask = 0775
force create mode = 0775
directory mask = 0775
writable = yes
force group = www-data

Теперь нужно создать пользователя samba командой
smbpasswd -a developer
указав при этом отдельный пароль для него.

Перезагружаем процессы samba

service smbd restart
service nmbd restart

Теперь уже в windows в адресной строке проводника можно вбить наш IP
Адресная строка

В результате мы увидим вот такую сетевую директорию
Сетевая папка

Кликнув по ней правой клавишей, мы сможем подключить её как сетевой диск и работать напрямую через любимый редактор файлов или IDE.

За сим всё!

С радостью отвечу на возникшие вопросы в комментариях!

NGINX / PHP-FPM / Percona (MySQL) DB на виртуальной машине Ubuntu: 4 комментария

    1. Приветствую! Было бы здорово увидеть конфиги, логи.
      Судя по ответу, у Вас запрос доходит до NGINX, но не смотрит на директорию с PHP-файлами.

  1. Спасибо за статью. Возник вопрос.
    В конфиге nginx прописано user www-data;
    В php-fpm
    /etc/php5/fpm/pool.d/my_user.conf

    прописал:

    [my_user]
    pm = dynamic
    pm.start_servers = 1
    pm.min_spare_servers = 1
    pm.max_children = 5
    pm.max_spare_servers = 5
    php_admin_value[display_errors] = stderr
    php_admin_value[log_errors] = On
    listen = /var/www/php-fpm/my_user.sock
    listen.mode = 0660
    listen.owner = www-data
    listen.group = www-data
    user = www-data
    group = www-data
    chdir = /
    php_admin_value[upload_tmp_dir] = /var/www/my_user/data/mod-tmp
    php_admin_value[session.save_path] = /var/www/my_user/data/mod-tmp
    php_value[date.timezone] = Europe/Moscow
    php_value[max_execution_time] = 300
    php_value[post_max_size] = 100M
    php_value[memory_limit] = 128M
    php_value[upload_max_filesize] = 100M
    php_value[error_reporting] = E_ALL & ~E_STRICT & ~E_DEPRECATED

    Вопрос, как разрешить, запись, выполнение и чтение файлов владельцем которых является my_user для www-data и наоборот. PHP создает файлы с владельцем и группой www-data:www-data

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *