Vagrant. Начало работы. Часть 2 из 2
24.11.2019
Теги: CLI • MySQL • Nginx • PHP • Ubuntu • Vagrant • Web-разработка • Windows • Виртуализация • Настройка • Установка
Установка пакетов
Для автоматической установки и настройки программного обеспечения предназначена настройка config.vm.provision
. Мы будем использовать самый простой способ — shell-скрипт, но доступны также и другие варианты — Ansible, Chef, Puppet. Рассмотрим пример:
Vagrant.configure(2) do |config| config.vm.box = "bento/ubuntu-18.04" config.vm.provision "nginx", type: "shell", inline: "echo Installing Nginx; apt-get install -y nginx" config.vm.provision "mysql", type: "shell", inline: "echo Installing MySQL; apt-get install -y mysql-server" config.vm.provision "php", type: "shell", inline: "echo Installing PHP; apt-get install -y php-fpm php-mysql" end
При установке Vagrant выдает сообщения:
$ vagrant up .......... ==> default: Running provisioner: nginx (shell)... default: Running: inline script default: Installing Nginx .......... ==> default: Running provisioner: mysql (shell)... default: Running: inline script default: Installing MySQL .......... ==> default: Running provisioner: php (shell)... default: Running: inline script default: Installing PHP ..........
Если команд много, их удобно объединить:
$script = <<~SCRIPT echo Installing Nginx apt-get install -y nginx echo Installing MySQL apt-get install -y mysql-server echo Installing PHP apt-get install -y php-fpm php-mysql SCRIPT Vagrant.configure(2) do |config| config.vm.box = "bento/ubuntu-18.04" config.vm.provision "shell", inline: $script end
$update = <<~UPDATE apt-get update apt-get -y upgrade UPDATE $install = <<~INSTALL apt-get install -y nginx apt-get install -y mysql-server apt-get install -y php-fpm php-mysql INSTALL Vagrant.configure(2) do |config| config.vm.box = "bento/ubuntu-18.04" config.vm.provision "update", type: "shell", inline: $update config.vm.provision "install", type: "shell", inline: $install end
Или вообще вынести в отдельный shell-файл:
Vagrant.configure(2) do |config| config.vm.box = "bento/ubuntu-18.04" config.vm.provision "shell", path: "provision.sh" end
echo 'Installing Nginx'
apt-get install -y nginx
echo 'Installing MySQL'
apt-get install -y mysql-server
echo 'Installing PHP'
apt-get install -y php-fpm php-mysql
Поставщики (provisioners) выполняются в трех случаях:
- при начальном
vagrant up
- по команде
vagrant provision
- по команде
vagrant reload --provision
vagrant up|reload
могут быть запущены с ключом --no-provision
, чтобы пропустить инструкции provision
.
Если у каждого поставщика есть имя, то можно выполнить только его:
Vagrant.configure(2) do |config| config.vm.box = "bento/ubuntu-18.04" config.vm.provision "update", type: "shell", path: "update.sh" config.vm.provision "install", type: "shell", path: "install.sh" end
$ vagrant provision --provision-with update
Несколько виртуальных машин
Допускается создание нескольких виртуальных машин в одном Vagrantfile
:
Vagrant.configure(2) do |config| # образ системы Ubuntu 18/04 LTS (Bionic Beaver) config.vm.box = "bento/ubuntu-18.04" # не проверять репозиторий на наличие обновлений config.vm.box_check_update = false # отменить создание ssh-ключа config.ssh.insert_key = false # ПЕРВАЯ ВИРТУАЛЬНАЯ МАШИНА config.vm.define "web-server" do |subconfig| # имя виртуальной машины subconfig.vm.provider "virtualbox" do |vb| vb.name = "apache-server" end # hostname виртуальной машины subconfig.vm.hostname = "apache-server" # настройки сети subconfig.vm.network "private_network", ip: "192.168.53.3" # установка пакетов subconfig.vm.provision "apache", type: "shell", inline: "apt-get install -y apache2" end # ВТОРАЯ ВИРТУАЛЬНАЯ МАШИНА config.vm.define "sql-server" do |subconfig| # имя виртуальной машины subconfig.vm.provider "virtualbox" do |vb| vb.name = "mysql-server" end # hostname виртуальной машины subconfig.vm.hostname = "mysql-server" # настройки сети subconfig.vm.network "private_network", ip: "192.168.53.4" # установка пакетов subconfig.vm.provision "mysql", type: "shell", inline: "apt-get install -y mysql-server" end # обновление системы (для первой и второй) config.vm.provision "update", type: "shell", inline: "apt-get update && apt-get upgrade -y" end
Запускаем виртуальные машины:
$ vagrant up Bringing machine 'web-server' up with 'virtualbox' provider... Bringing machine 'sql-server' up with 'virtualbox' provider...
Ход установки первой виртуальной машины:
==> web-server: Importing base box 'bento/ubuntu-18.04'... ==> web-server: Matching MAC address for NAT networking... ==> web-server: Setting the name of the VM: apache-server ==> web-server: Clearing any previously set network interfaces... ==> web-server: Preparing network interfaces based on configuration... web-server: Adapter 1: nat web-server: Adapter 2: hostonly ==> web-server: Forwarding ports... web-server: 22 (guest) => 2222 (host) (adapter 1) ==> web-server: Booting VM... ==> web-server: Waiting for machine to boot. This may take a few minutes... web-server: SSH address: 127.0.0.1:2222 web-server: SSH username: vagrant web-server: SSH auth method: private key ==> web-server: Machine booted and ready! ==> web-server: Checking for guest additions in VM... ==> web-server: Setting hostname... ==> web-server: Configuring and enabling network interfaces... ==> web-server: Mounting shared folders... web-server: /vagrant => D:/vagrant/www ==> web-server: Running provisioner: update (shell)... web-server: Running: inline script ********** обновление системы ********** ==> web-server: Running provisioner: apache (shell)... web-server: Running: inline script ********** установка Apache **********
Ход установки второй виртуальной машины:
==> sql-server: Importing base box 'bento/ubuntu-18.04'... ==> sql-server: Matching MAC address for NAT networking... ==> sql-server: Setting the name of the VM: mysql-server ==> sql-server: Fixed port collision for 22 => 2222. Now on port 2200. ==> sql-server: Clearing any previously set network interfaces... ==> sql-server: Preparing network interfaces based on configuration... sql-server: Adapter 1: nat sql-server: Adapter 2: hostonly ==> sql-server: Forwarding ports... sql-server: 22 (guest) => 2200 (host) (adapter 1) ==> sql-server: Booting VM... ==> sql-server: Waiting for machine to boot. This may take a few minutes... sql-server: SSH address: 127.0.0.1:2200 sql-server: SSH username: vagrant sql-server: SSH auth method: private key ==> sql-server: Machine booted and ready! ==> sql-server: Checking for guest additions in VM... ==> sql-server: Setting hostname... ==> sql-server: Configuring and enabling network interfaces... ==> sql-server: Mounting shared folders... sql-server: /vagrant => D:/vagrant/www ==> sql-server: Running provisioner: update (shell)... sql-server: Running: inline script ********** обновление системы ********** ==> sql-server: Running provisioner: mysql (shell)... sql-server: Running: inline script ********** установка MySQL **********
Остановить обе виртуальные машины:
$ vagrant halt ==> sql-server: Attempting graceful shutdown of VM... ==> web-server: Attempting graceful shutdown of VM...
Запустить обе виртуальные машины:
$ vagrant up
Подключение по ssh к первой машине:
$ vagrant ssh web-server
Остановить вторую виртуальную машину:
$ vagrant halt sql-server
Установка Nginx, MySQL и PHP
Во время создания виртуальной машины Vagrant запустит скрипт provision.sh
, который установит Nginx, MySQL, PHP + создаст два виртуальных хоста.
Vagrant.configure(2) do |config| # образ системы Ubuntu 18/04 LTS (Bionic Beaver) config.vm.box = "bento/ubuntu-18.04" # не проверять репозиторий на наличие обновлений config.vm.box_check_update = false # отменить создание ssh-ключа config.ssh.insert_key = false config.vm.provider "virtualbox" do |vb| # имя виртуальной машины vb.name = "ubuntu-1804-test" # объем оперативной памяти vb.memory = 2048 # количество ядер процессора vb.cpus = 1 end # hostname виртуальной машины config.vm.hostname = "ubuntu-1804-test" # настройки сети config.vm.network "public_network" # синхронизация директорий config.vm.synced_folder ".", "/var/www" # установка пакетов config.vm.provision "shell", path: "provision.sh" end
apt-get update
apt-get -y upgrade
apt-get install -y nginx
apt-get install -y mysql-server
apt-get install -y php-fpm php-mysql
# создаем две директории для двух виртуальных хостов
mkdir /var/www/site1.loc
mkdir /var/www/site2.loc
# создаем в каждой из этих директорий php-файл
echo '<?php phpinfo(); ?>' > /var/www/site1.loc/index.php
echo '<?php phpinfo(); ?>' > /var/www/site2.loc/index.php
# создаем два виртуальных хоста
cat > /etc/nginx/sites-available/site1.loc <<EOF
server {
# слушать порт 80
listen 80;
# директория сайта
root /var/www/site1.loc;
# индексные файлы
index index.php index.html;
# домен сайта
server_name site1.loc www.site1.loc;
location / {
try_files \$uri \$uri/ =404;
}
# PHP скрипты передаются на выполнение FastCGI серверу
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# With php-fpm (or other unix sockets):
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
}
EOF
cat > /etc/nginx/sites-available/site2.loc <<EOF
server {
# слушать порт 80
listen 80;
# директория сайта
root /var/www/site2.loc;
# индексные файлы
index index.php index.html;
# домен сайта
server_name site2.loc www.site2.loc;
location / {
try_files \$uri \$uri/ =404;
}
# PHP скрипты передаются на выполнение FastCGI серверу
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# With php-fpm (or other unix sockets):
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
}
EOF
ln -s /etc/nginx/sites-available/site1.loc /etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/site2.loc /etc/nginx/sites-enabled/
echo '' >> '/etc/hosts'
echo '127.0.0.1 site1.loc www.site1.loc' >> '/etc/hosts'
echo '127.0.0.1 site2.loc www.site2.loc' >> '/etc/hosts'
systemctl reload nginx
Синхронизация директорий
По умолчанию синхронизируется директория, где расположен Vagrantfile
на хост-системе с директорией /vagrant
виртуальной машины. Это можно изменить с помощью настройки config.vm.synced_folder
: указывается абсолютный или относительный путь для хост-системы и абсолютный — для виртуальной машины.
В нашем случае синхронизируется директория d:/vagrant/www
с директорией /var/www
. Таким образом, будут синхронизированы и вложенные директории виртуальных хостов:
d:/vagrant/www/site1.loc <=> /var/www/site1.loc # первый виртуальный хост d:/vagrant/www/site2.loc <=> /var/www/site2.loc # второй виртуальный хост
У меня в настройках для второго адаптера используется сетевой мост, так что виртуальная машина является частью той же сети, что и хост-система. Через web-интерфейс роутера, который выдает ip-адреса всем устройствам локальной сети, можно закрепить за виртуальной машиной выданный ip-адрес — у меня это 192.168.110.12. А чтобы получить доступ к сайтам на виртуальной машине — добавить пару записей в host
-файл основной системы.
192.168.110.12 site1.loc www.site1.loc 192.168.110.12 site2.loc www.site2.loc
Скрипт безопасности MySQL
У нас есть небольшая проблема с сервером MySQL — не задан пароль для root
. Кроме того, пользователь root
не может может подключаться по паролю, а только с помощью плагина auth_socket
.
Чтобы это исправить, нужно выполнить скрипт безопасности. После запуска скрипт задает вопросы и нам надо на них ответить:
# mysql_secure_installation
- Would you like to setup VALIDATE PASSWORD plugin?
- Please set the password for root here.
- Re-enter new password.
- Remove anonymous users?
- Disallow root login remotely?
- Remove test database and access to it?
- Reload privilege tables now?
В этом нам поможет expect
— инструмент, который позволяет создать скрипт, который ответит на вопросы от скрипта безопасности MySQL. Подключимся к виртуальной машине по ssh и установим expect
:
# apt install expect
Вместе с expect
будет установлен и autoexpect
. Он позволяет запускать скрипты, которые надо автоматизировать, после чего записывает то, что они выводят, и то, что пользователь вводит, отвечая на их вопросы. Так что запускаем и отвечаем на вопросы:
# cd /var/www # результат работы autoexpect будет в директрии d:/vagrant/www хост-машины # autoexpect mysql_secure_installation
После завершения работы autoexpect
сообщит о том, что собранные данные записаны в файл script.exp
.
#!/usr/bin/expect -f
#
# This Expect script was generated by autoexpect on Sun Nov 24 09:32:55 2019
# Expect and autoexpect were both written by Don Libes, NIST.
#
# Note that autoexpect does not guarantee a working script. It
# necessarily has to guess about certain things. Two reasons a script
# might fail are:
#
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts. If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character. This
# pacifies every program I know of. The -c flag makes the script do
# this in the first place. The -C flag allows you to define a
# character to toggle this mode off and on.
set force_conservative 0; # set to 1 to force conservative mode even if
; # script was not run conservatively originally
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}
#
# 2) differing output - Some programs produce different output each time
# they run. The "date" command is an obvious example. Another is
# ftp, if it produces throughput statistics at the end of a file
# transfer. If this causes a problem, delete these patterns or replace
# them with wildcards. An alternative is to use the -p flag (for
# "prompt") which makes Expect only look for the last line of output
# (i.e., the prompt). The -P flag allows you to define a character to
# toggle this mode off and on.
#
# Read the man page for more info.
#
# -Don
set timeout -1
spawn mysql_secure_installation
match_max 100000
expect -exact "\r
Securing the MySQL server deployment.\r
\r
Connecting to MySQL using a blank password.\r
\r
VALIDATE PASSWORD PLUGIN can be used to test passwords\r
and improve security. It checks the strength of password\r
and allows the users to set only those passwords which are\r
secure enough. Would you like to setup VALIDATE PASSWORD plugin?\r
\r
Press y|Y for Yes, any other key for No: "
send -- "N\r"
expect -exact "N\r
Please set the password for root here.\r
\r
New password: "
send -- "qwerty\r"
expect -exact "\r
\r
Re-enter new password: "
send -- "qwerty\r"
expect -exact "\r
By default, a MySQL installation has an anonymous user,\r
allowing anyone to log into MySQL without having to have\r
a user account created for them. This is intended only for\r
testing, and to make the installation go a bit smoother.\r
You should remove them before moving into a production\r
environment.\r
\r
Remove anonymous users? (Press y|Y for Yes, any other key for No) : "
send -- "Y\r"
expect -exact "Y\r
Success.\r
\r
\r
Normally, root should only be allowed to connect from\r
'localhost'. This ensures that someone cannot guess at\r
the root password from the network.\r
\r
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : "
send -- "Y\r"
expect -exact "Y\r
Success.\r
\r
By default, MySQL comes with a database named 'test' that\r
anyone can access. This is also intended only for testing,\r
and should be removed before moving into a production\r
environment.\r
\r
\r
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : "
send -- "Y\r"
expect -exact "Y\r
- Dropping test database...\r
Success.\r
\r
- Removing privileges on test database...\r
Success.\r
\r
Reloading the privilege tables will ensure that all changes\r
made so far will take effect immediately.\r
\r
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : "
send -- "Y\r"
expect eof
Изменим имя скрипта (это можно сделать и в директриии d:/vagrant/www
):
# mv script.exp mysql_sec.sh
Запросы, которые нужно выполнить, чтобы root
мог подключаться по паролю:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'qwerty'; FLUSH PRIVILEGES;
После этого удаляем виртуальную машину и создаем заново. Но предварительно изменяем кофигурационный файл:
Vagrant.configure(2) do |config| # образ системы Ubuntu 18/04 LTS (Bionic Beaver) config.vm.box = "bento/ubuntu-18.04" # не проверять репозиторий на наличие обновлений config.vm.box_check_update = false # отменить создание ssh-ключа config.ssh.insert_key = false config.vm.provider "virtualbox" do |vb| # имя виртуальной машины vb.name = "ubuntu-1804-test" # объем оперативной памяти vb.memory = 2048 # количество ядер процессора vb.cpus = 1 end # hostname виртуальной машины config.vm.hostname = "ubuntu-1804-test" # настройки сети config.vm.network "public_network" # синхронизация директорий config.vm.synced_folder ".", "/var/www" # установка пакетов config.vm.provision "shell", path: "provision.sh" config.vm.provision "shell", inline: "apt-get install -y expect" config.vm.provision "shell", path: "mysql_sec.sh" config.vm.provision "shell", inline: <<-QUERY mysql -uroot -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'qwerty'; FLUSH PRIVILEGES;" QUERY end
Основные команды
Проверить файл конфигурации Vagrantfile
:
$ vagrant validate
Запустить или создать виртуальную машину:
$ vagrant up
Приостанавить работу виртуальной машины
$ vagrant suspend
Возобновить работу виртуальной машины:
$ vagrant resume
Перезагрузить виртуальную машину:
$ vagrant reload
$ vagrant reload --provision
Подключиться к виртуальной машине по ssh:
$ vagrant ssh
Посмотреть настройки подключения по ssh:
$ vagrant ssh-config
Остановить виртуальную машину:
$ vagrant halt
Удалить виртуальную машину:
$ vagrant destroy
Проверить состояние виртуальной машины:
$ vagrant status
Проверить состояние всех виртуальных машин:
$ vagrant global-status
Посмотреть все доступные команды:
$ vagrant --help
Поиск: MySQL • Nginx • PHP • Ubuntu • Web-разработка • Виртуальная машина • Установка • Настройка • Vagrant • CLI