Marcin Lewandowski
Marcin Lewandowski
Programista PHP ( Symfony ), blogger, trener oraz miłośnik kawy. Na co dzień pracuję z Symfony, RabbitMQ, ElasticSearch, Node.js, Redis, Docker, MySQL.

Vagrant instalacja i konfiguracja środowiska

Vagrant instalacja i konfiguracja środowiska

Jako że podstawy teoretyczne odnośnie Vagrnt-a już mamy z poprzedniego wpisu. To czas przystąpić do działania, zainstalujemy Vagrant-a i przygotujemy swój pierwszy Vagrantfile.

Instalacja Vagrant-a i VirtualBox-a

Do działania Vagrant-a potrzebujemy tzw. hipernadzorcę jakim jest np. VirtualBox. Do dyspozycji mamy także Hyper-V, Docker, VMware oraz AWS. Jeśli pobierzecie instalator ze strony Vagrant-a to powinniście mieć VirtualBox-a zawartego w instalatorze.

Dodatkowo warto w przypadku użytkowników Windows-a zainstalować dodatkowe oprogramowanie umożliwiające łączenie się poprzez protokół ssh. Jest to potrzebne do zalogowania się do wirtualnej maszyny, którą będzie tworzył Vagrant. Osobiście polecam putty, które jest spoko, ale genialnym rozwiązaniem jest zainstalowanie sobie GIT-a. Wraz z GIT-em zostanie zainstalowane MinGW (Minimalist GNU for Windows), dzięki któremu zyskujemy dostęp do poleceń typowo linuks-owych w tym ssh.

Konfiguracja maszyny wirtualnej – Vagrantfile

Do konfiguracji maszyny wirtualnej wykorzystywany jest plik Vagrantfile, który opisuje konfigurację maszyny. Plik ten jest plikiem tekstowym, którego składnia została oparta o język Ruby (znajomość języka Ruby nie jest wymagana).

Tworzymy plik Vagrantfile

Plik Vagrantfile możemy stworzyć od zera lub wygenerować za pomocą Vagranta. Jako że jesteśmy leniwi i nie mamy pojęcia jak napisać go od zera to zdamy się na Vagranta. Uruchamiamy konsolę przechodzimy do katalogu w którym ma znajdować się plik Vagrantfile i wpisujemy polecenie:

vagrant init

Powinno spowodować to stworzenie w bieżącym katalogu pliku Vagrantfile. W przypadku, gdy taki plik istnieje zostaniemy o tym poinformowani i Vagrant wstrzyma generowanie nowego pliku.

Rzućmy okiem teraz na wygenerowany plik:

# -*- mode: ruby -*-
# vi: set ft=ruby :
 
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
  # The most common configuration options are documented and commented below.
  # For a complete reference, please see the online documentation at
  # https://docs.vagrantup.com.
 
  # Every Vagrant development environment requires a box. You can search for
  # boxes at https://atlas.hashicorp.com/search.
  config.vm.box = "base"
 
  # Disable automatic box update checking. If you disable this, then
  # boxes will only be checked for updates when the user runs
  # `vagrant box outdated`. This is not recommended.
  # config.vm.box_check_update = false
 
  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  # NOTE: This will enable public access to the opened port
  # config.vm.network "forwarded_port", guest: 80, host: 8080
 
  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine and only allow access
  # via 127.0.0.1 to disable public access
  # config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
 
  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  # config.vm.network "private_network", ip: "192.168.33.10"
 
  # Create a public network, which generally matched to bridged network.
  # Bridged networks make the machine appear as another physical device on
  # your network.
  # config.vm.network "public_network"
 
  # Share an additional folder to the guest VM. The first argument is
  # the path on the host to the actual folder. The second argument is
  # the path on the guest to mount the folder. And the optional third
  # argument is a set of non-required options.
  # config.vm.synced_folder "../data", "/vagrant_data"
 
  # Provider-specific configuration so you can fine-tune various
  # backing providers for Vagrant. These expose provider-specific options.
  # Example for VirtualBox:
  #
  # config.vm.provider "virtualbox" do |vb|
  #   # Display the VirtualBox GUI when booting the machine
  #   vb.gui = true
  #
  #   # Customize the amount of memory on the VM:
  #   vb.memory = "1024"
  # end
  #
  # View the documentation for the provider you are using for more
  # information on available options.
 
  # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies
  # such as FTP and Heroku are also available. See the documentation at
  # https://docs.vagrantup.com/v2/push/atlas.html for more information.
  # config.push.define "atlas" do |push|
  #   push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME"
  # end
 
  # Enable provisioning with a shell script. Additional provisioners such as
  # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
  # documentation for more information about their specific syntax and use.
  # config.vm.provision "shell", inline: <<-SHELL
  #   apt-get update
  #   apt-get install -y apache2
  # SHELL
end

Wygląda nieco przerażająco, ale nie ma czego się obawiać jakieś 99% to komentarze, które mają nam pomóc w świadomym włączaniu poszczególnych opcji konfiguracyjnych. Po usunięciu komentarzy pozostanie plik w takiej wersji:

Vagrant.configure("2") do |config|
 
  config.vm.box = "base"
 
end

Czyż teraz nie wygląda to lepiej 😉 Pierwsza linia Vagrant.configure("2") do |config| to rozpoczęcie pliku wraz z informacją o wersji API jaką używamy. W przypadku tego pliku API jest w wersji 2. Linia ostatnia end mówi o zakończeniu konfiguracji maszyny, wszystko pomiędzy jest właściwą konfiguracją.

Wygenerowany plik posiada tylko jeden parametr konfigurujący config.vm.box, do którego jest przypisana nazwa obrazu systemu jaki ma zostać użyty przy starcie maszyny wirtualnej. W przypadku domyślnej konfiguracji jest to jakiś obraz bazowy, listę dostępnych obrazów możemy przeglądać pod adresem https://atlas.hashicorp.com/boxes/search.

Ja na swoje potrzeby zmienię ten obraz na ubuntu/xenial64, czyli oficjalny obraz Ubuntu 16.04 LTS. Zamiast modyfikować plik, możemy już na etapie generowania Vagrantfile podać jakiego obrazu chcemy użyć. Wystarczy do polecenia inicjalizacji dodać nazwę obrazu:

vagrant init ubuntu/xenial64

Mając tak podstawową konfigurację już możemy uruchomić wirtualną maszynę wykorzystując plik Vagrantfile. Wystarczy w katalogu z plikiem wydać polecenie:

vagrant up

Jeśli pierwszy raz wykorzystujemy dany obraz to musimy się liczyć z faktem, że musi zostać on ściągnięty do nas na komputer, co może zająć nieco czasu. W przypadku, gdy będziemy chcieli wykorzystać ten sam obraz w innym pliku Vagrantfile to także nie będzie on pobierany z sieci. Zostanie on załadowany z lokalnego repozytorium do którego możemy dodawać / usuwać / aktualizować obrazy, ale o tym następnym razem.

Połączenie ssh

Kiedy mamy uruchomioną wirtualną maszynę to możemy się do niej zalogować wykorzystując ssh:

vagrant ssh

Pozwala to na wprowadzanie dowolnych modyfikacji w systemie, jednak naszym celem jest stworzenie juz skonfigurowanej maszyny więc rozszerzmy nieco podstawową konfigurację którą mamy.

Konfiguracja sieci

Zaczniemy od skonfigurowania sieci, w tym celu dodajemy linijkę:

config.vm.network "private_network", ip: "192.168.33.10"

Oczywiście adres IP podajemy taki jaki chcemy, aby został ustawiony dla naszej maszyny. Ustawienie to dodaje dodatkowy interfejs sieciowy i ustawia na nim określony adres IP.

Konfiguracja sprzętowa maszyny

W zależności od możliwości sprzętowych maszyny na której uruchamiamy naszą wirtualną maszynę powinnismy odpowiednio przyznać zasoby. Poniżej prosta konfiguracja, którą sobie krok po kroku wyjaśnimy:

config.vm.provider "virtualbox" do |vb|
    vb.name = "Test"
    vb.cpus = 2
    vb.memory = 1024
    vb.customize ["modifyvm", :id, "--vram", "128"]
    vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"]  
    vb.gui = true
end

Zaczynając od samego początku mówimy jaki provider będzie uruchamiał naszą maszynę wirtualną. W tym przypadku będzie to virtualbox, który ma zostać skonfigurowany następująco:

  • vb.name – nazwa maszyny,
  • vb.cpus – przyznana liczba rdzeni procesora,
  • vb.memory – przyznana liczba megabajtów pamięci RAM dla maszyny,
  • vb.customize [ --vram ] – przyznana liczba megabajtów pamięci RAM dla karty graficznej,
  • vb.customize [ --clipboard ] – dwukierunkowy schowek, pozwalający kopiować wykorzystując skróty klawiszowe Ctrl+C, Ctrl+V,
  • vb.gui – parametr określa czy VirtualBox ma uruchamiać maszynę w trybie graficznym,

Kopiowanie plików

Jeśli chcemy skopiować jakieś pliki z systemu użytkownika do tworzonego obrazu, możemy to wykonać wykorzystując config.vm.provision typu file.

config.vm.provision "file",
  source: "nazwa_pliku.txt",
  destination: "/home/vagrant/nazwa_pliku.txt"

Jak widać ustawienie jest banalna, polega na określenia skąd (source) ma zostać skopiowany plik. Oraz miejsce docelowe (destination) kopiowanego pliku. Przydatne przy kopiowaniu plików konfiguracyjnych.

Uruchamianie poleceń powłoki

Ustawienie config.vm.provision poza typem file, posiada także typ shell. Można go używać na dwa sposoby, pierwszy podajemy wszystkie polecenia w zdefiniowanym bloku kodu, jak pokazano to poniżej:

config.vm.provision "shell", inline: <<-SHELL
    apt-get update
    apt-get install -y apache2
SHELL

Jest to dobre rozwiązanie, gdy mamy tylko kilka prostych poleceń. Bardziej praktycznym rozwiązaniem jest stworzenie pliku i podanie do niego ścieżki.

config.vm.provision "shell", path: "init.sh"

Konfiguracja systemu operacyjnego i narzędzi

Wiemy już jak zainstalować Vagrant-a oraz jak stworzyć prosty plik Vagrantfile. Czas wykorzystać tę wiedzę do konfiguracji systemu oraz instalacji dodatkowych narzędzi. W tym celu wykorzystamy możliwość uruchamiania poleceń powłoki config.vm.provision "shell", path: "init.sh".

Plik init.sh będzie zawierał polecenia instalujące dodatkowe oprogramowanie oraz konfigurujące system. Zacznijmy od czegoś prostego, czyli instalacja dodatkowych narzędzi.

apt-get install -y nginx
apt-get install -y php7.0
apt-get install -y php7.0-mysql
apt-get install -y mariadb-server 
apt-get install -y expect 
apt-get install -y git

Powyższe polecenia instalują pakiety nginx + php + MariaDB czyli w skrócie typowy serwer wwww. Instalacja ta odbywa się bez interakcji użytkownika dzięki zastosowaniu flagi -y.

Jest jednak pewien problem w przypadku serwera bazodanowego MariaDB. Mianowicie po instalacji konieczne jest uruchomienie narzędzia mysql_secure_installation. Nie można tego zrobić bez interakcji z użytkownikiem bowiem narzędzie to wymaga odpowiedzi na kilka pytań. Jenak możne to obejść stosując narzędzie expect, które odpowie za nas 😉

export ROOT_NEW_MYSQL_PASSWORD="haslo_do_bazy_danych"
 
SECURE_MYSQL=$(expect -c "
set timeout 3
spawn mysql_secure_installation
expect \"Enter current password for root (enter for none):\"
send \"\r\"
expect \"root password?\"
send \"y\r\"
expect \"New password:\"
send \"$ROOT_NEW_MYSQL_PASSWORD\r\"
expect \"Re-enter new password:\"
send \"$ROOT_NEW_MYSQL_PASSWORD\r\"
expect \"Remove anonymous users?\"
send \"y\r\"
expect \"Disallow root login remotely?\"
send \"y\r\"
expect \"Remove test database and access to it?\"
send \"y\r\"
expect \"Reload privilege tables now?\"
send \"y\r\"
expect eof
")
 
sudo echo "${SECURE_MYSQL}"

Po wszystkim powinniśmy mieć działający serwer www. Możemy to sprawdzić wchodząc na adres IP naszej wirtualnej maszyny ustawionej w pliku konfiguracyjnym Vagrantfile.

Jednak nie mamy obsługi php w naszym serwerze, konieczne jest zmodyfikowanie serwera Nginx. Przygotowujemy nowy plik konfiguracyjny Nginx-a, który skopiujemy do naszej wirtualnej maszyny podczas jej konfiguracji.

server {
    listen 80 default_server;
    listen [::]:80 default_server;
 
    root /var/www/html;
 
    index index.php index.html index.htm index.nginx-debian.html;
 
    server_name _;
 
    location / {
        try_files $uri $uri/ =404;
    }
 
    location ~ \.php$ {
 
        fastcgi_index index.php;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;

        include fastcgi_params;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    location ~ /\.ht {
        deny all;
    }
}

Dodajemy kopiowanie pliku z nową konfiguracją do pliku install.sh

sudo cp /vagrant/vagrant_files/nginx-php /etc/nginx/sites-available/default

Należy wyjaśnić, że podczas tworzenia wirtualnej maszyny, tworzy ona domyślnie powiązanie pomiędzy naszym katalogiem, a katalogiem /vagrant w wirtualnej maszynie. Pozwala nam to an dostęp do plików znajdujących się w katalogu.

Dodajemy jeszcze testowy plik php oraz restart serwera Nginx.

sudo cp /vagrant/vagrant_files/index.php /var/www/html/
 
sudo /etc/init.d/nginx restart

Przykładowy plik php wygląda następująco:

<h1 style="text-align: center">Vagrant WebSerwer !!!</h1>
<?php
 
phpinfo();

Po tych wszystkich modyfikacjach serwer www powinien wyświetlić nam poniższą stronę.

Jeśli nie chce wam się kopiować powyższych zawartości plików to wszystko znajdziecie na GitHub-ie.