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 udostępnianie katalogów

Vagrant udostępnianie katalogów

Wirtualne maszyny takie jak VirtualBox mają możliwość udostępniania katalogów z komputera gospodarza (host) na maszynę gościa (guest). Umożliwia to w bardzo łatwy sposób dostęp do danych bowiem wystarczy wejść do określonego katalogu i mamy dostęp.

Udostępnianie katalogów – zasada działania

Spróbuję zobrazować zasadę działania udostępniania katalogów pomiędzy maszyną na której jest uruchamiana wirtualna maszyna, a systemem uruchamianym na wirtualnej maszynie.

Na powyższym schemacie mamy host-a, jest to maszyna na której będzie uruchamiana wirtualna maszyna. Kolejny element to wirtualna maszyna, w tym przypadku VirtualBox. Teraz pomiędzy nimi chcielibyśmy wymieniać dane, najwygodniejszą metodą jest właśnie udostępnienie katalogu. Rozwiązanie to jest o tyle wygodne, że katalog udostępniony z poziomu host-a jest synchronizowany w obu kierunkach. Oznacza to tyle, że jeśli dodamy nowy plik z poziomu wirtualnej maszyny pojawi się on na maszynie host-a i odwrotnie.

Domyślne ustawienia

Bazując na najprostszej konfiguracji, którą omawiałem we wpisie Instalacja i konfiguracja środowiska zobaczymy jak działa udostępnianie katalogów. Dla niewtajemniczonych poniżej konfiguracja z której będę korzystał.

Vagrant.configure("2") do |config|
 
  config.vm.box = "ubuntu/xenial64"
  config.vm.network "private_network", ip: "192.168.33.10"
 
  config.vm.provider "virtualbox" do |vb|
    vb.name = "WebServer"
    vb.cpus = 1
    vb.memory = 1024
    vb.gui = false
  end
 
end

Nigdzie tutaj nie ma żadnej wzmianki o udostępnieniu katalogu. Jednak Vagrant jest na tyle uprzejmy, że sam montuje katalog w którym znajduje się plik Vagrantfile do katalogu o nazwie vagrant. Możemy to zobaczyć na etapie uruchamiania/budowania wirtualnej maszyny.

Oczywiście ścieżki będą się różniły od tych zaprezentowanych na powyższym screenie. Montowanie katalogu w którym znajduje się możemy odtworzyć i zmodyfikować dodając do pliku Vagrantfile poniższy wpis.

config.vm.synced_folder ".", "/vagrant"

lub wyłączyć dodając wpis

config.vm.synced_folder ".", "/vagrant", disabled: true

Posiadając wiedzę o domyślnym montowaniu katalogu zawierającego plik Vagrantfile możemy dodać go do naszego projektu. Zaś po uruchomieniu maszyny będzie on dostępny w systemie gościa. Przy odpowiedniej konfiguracji systemu gościa, mamy możliwość bezpośredniej pracy nad projektem, który będzie uruchamiany przez wirtualną maszynę.

Udostępnianie katalogów

Do udostępniania katalogów Vagrant ma dodatkową opcję, którą dodajemy w pliku Vagrantfile. W najprostszej postaci wygląda ona następująco:

config.vm.synced_folder "katalog_zrodlowy", "katalog_docelowy"
  • katalog_zrodlowy – ścieżka do katalogu który ma zostać udostępniony,
  • katalog_docelowy – ścieżka pod którą będzie dostępny udostępniany katalog w systemie gościa,

Dodajmy montowanie katalogu src znajdującego się w katalogu projektu do katalogu /var/www/czterytygodnie

config.vm.synced_folder "./src", "/var/www/czterytygodnie"

Przy próbie uruchomienia takiej definicji możemy otrzymać błąd, jeśli katalog src nie istnieje.

W takim przypadku możemy utworzyć katalog lub dodać opcję create w konfiguracji.

config.vm.synced_folder "./src", "/var/www/czterytygodnie", 
  create: true

Po przeładowaniu wirtualnej maszyny poleceniem vagrant reload powinniśmy otrzymać poniższą listę montowanych katalogów.

Na liście znajdziemy domyślnie montowany katalog oraz naszą nową definicję, która utworzyła katalog src w katalogu projektu. Mimo tego, że mamy możliwość tworzenia katalogu w momencie montowania, to nie polecał bym używania tej opcji. W większości wypadków chcemy mieć dostęp do katalogu istniejącego już na dysku nie zaś ma on być tworzony.

Opcje udostępniania katalogów

Poznaliśmy już opcję create oraz disabled, jednak nie tylko je zostają nam udostępnione przez Vagranta. Zobaczmy jakie mamy możliwości konfiguracji udostępniania katalogów:

  • create (boolean) – jeśli ustawimy wartość na true to ścieżka na komputerze host-a zostanie utworzona jeśli nie istnieje (domyślnie: false)
  • disabled (boolean) – wyłącza montowanie katalogu, przydatne gdy chcemy wyłączyć domyślne montowanie lub wyłączać montowanie jakiegoś katalogu warunkowo (domyślnie: false)
  • group (string) – nazwa grupy, która ma być wykorzystywana do montowania katalogu (domyślnie: grupa użytkownika SSH)
  • mount_options (array) – list dodatkowych opcji udostępniania dla polecenia mount
  • owner (string) – nazwa użytkownika, który powinien być właścicielem udostępnianego katalogu (domyślnie: użytkownik SSH)
  • type (string) – typ udostępnienia katalogu (domyślnie: vagrant automatycznie dobiera najlepszy typ w zależności od środowiska)
  • id (string) – nazwa udostępnienia pod którą będzie ono widoczne na maszynie gościa

Typy udostępnień katalogu

Do tej pory nie określaliśmy typu udostępniania katalogu przez co był stosowany zapewne domyślny typ VirtualBox.

VirtualBox

Domyślny typ stosowany z reguły, gdy nie zdefiniujemy innego typu przy udostępnieniu. Typ ten synchronizuje katalog znajdujący się na maszynie host-a z tym na maszynie gościa w obu kierunkach.

NFS

Domyślny sposób synchronizacji oferowany przez VirtualBox-a nie jest idealny, gdyż przy większych katalogach z dużą ilością plików pojawiają się problemy wydajnościowe. Rozwiązaniem tych problemów może być zmiana sposobu synchronizacji na NFS.

Użytkownicy systemu Windows niestety są pozbawieni tej metody synchronizacji. W przypadku jej ustawienia Vagrant zignoruje tę opcję.

Do działania tej metody synchronizacji konieczne jest zainstalowanie nfsd na maszynie gospodarza (host-a). W przypadku linux-a (Ubuntu) operacja sprowadza się do wydania polecenia:

sudo apt-get install nfs-kernel-server

Zaś w przypadku Mac OS X takowy serwer powinien być już zainstalowany.

W przypadku gdy używasz VirtualBox-a konieczne jest dodatkowe zdefiniowanie sieci prywatnej. Jest to związane z ograniczeniami VirtualBox-a.

Zobaczmy jak zmieni się nasza konfiguracja, jeśli będziemy chcieli zastosować synchronizację typu NFS.

config.vm.synced_folder "./src", "/var/www/czterytygodnie", 
  type: "nfs"

Zmiana niemal kosmetyczna, jednak przy przeładowaniu konfiguracji poleceniem vagrant reload otrzymamy prośbę o podanie hasła do naszego komputera.

Jest to związane z faktem, że Vagrant potrzebuje zmodyfikować plik /etc/exports oraz zrestartować serwer NFS. Operacja ta jest wykonywana za każdym razem, gdy będziemy uruchamiali wirtualną maszynę poleceniem vagrant up lub vagrant reload.

Jeśli nie chcesz za każdym razem wpisywać hasła to należy dokonać edycji pliku /etc/sudoers wprowadzając poniższe modyfikacje:

Mac OS X

mnd_Alias VAGRANT_EXPORTS_ADD = /usr/bin/tee -a /etc/exports
Cmnd_Alias VAGRANT_NFSD = /sbin/nfsd restart
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /usr/bin/sed -E -e /*/ d -ibak /etc/exports
%admin ALL=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD, VAGRANT_EXPORTS_REMOVE

Ubuntu

Cmnd_Alias VAGRANT_EXPORTS_CHOWN = /bin/chown 0\:0 /tmp/*
Cmnd_Alias VAGRANT_EXPORTS_MV = /bin/mv -f /tmp/* /etc/exports
Cmnd_Alias VAGRANT_NFSD_CHECK = /etc/init.d/nfs-kernel-server status
Cmnd_Alias VAGRANT_NFSD_START = /etc/init.d/nfs-kernel-server start
Cmnd_Alias VAGRANT_NFSD_APPLY = /usr/sbin/exportfs -ar
%sudo ALL=(root) NOPASSWD: VAGRANT_EXPORTS_CHOWN, VAGRANT_EXPORTS_MV, VAGRANT_NFSD_CHECK, VAGRANT_NFSD_START, VAGRANT_NFSD_APPLY

Fedora

Cmnd_Alias VAGRANT_EXPORTS_CHOWN = /bin/chown 0\:0 /tmp/*
Cmnd_Alias VAGRANT_EXPORTS_MV = /bin/mv -f /tmp/* /etc/exports
Cmnd_Alias VAGRANT_NFSD_CHECK = /usr/bin/systemctl status --no-pager nfs-server.service
Cmnd_Alias VAGRANT_NFSD_START = /usr/bin/systemctl start nfs-server.service
Cmnd_Alias VAGRANT_NFSD_APPLY = /usr/sbin/exportfs -ar
%vagrant ALL=(root) NOPASSWD: VAGRANT_EXPORTS_CHOWN, VAGRANT_EXPORTS_MV, VAGRANT_NFSD_CHECK, VAGRANT_NFSD_START, VAGRANT_NFSD_APPLY

RSync

Kolejna metoda synchronizacji to rsync stosowana głównie w przypadkach braku możliwości użycia innych metod. Synchronizacja w tym przypadku odbywa się tylko w jednym kierunku z maszyny gospodarza (host) na maszynę gościa (guest). Nie jest to także synchronizacja ciągła bowiem automatycznie uruchamia się tylko w momencie uruchamiania maszyny poleceniem vagrant up lub vagrant reload.

W systemach unix-owych rsync powinien być zainstalowany i nie powinniśmy mieć problemów z jego użyciem. W systemach z rodziny Windows zapewne będzie konieczność instalacji dodatkowego oprogramowania. Możemy zainstalować środowisko Cygwin lub co jest według mnie lepszym rozwiązaniem instalujemy GIT-a zawierającego środowisko MinGW.

Nasza konfiguracja po zmianie sposobu synchronizacji może wyglądać następująco:

config.vm.synced_folder "./src", "/var/www/czterytygodnie", 
  type: "rsync"

Podczas uruchamiania wirtualnej maszyny zobaczymy informację o synchronizacji wskazanego katalogu.

Niestety synchronizacja jest jednorazowa co praktycznie uniemożliwia komfortową pracę z tak skonfigurowaną maszyną wirtualną. Jednak możliwe jest wymuszenie synchronizacji danych poprzez wywołanie polecenia vagrant rsync to dalej nie jest idealne, ale już jest lepiej. Vagrant daje nam jeszcze jedną możliwość jest nią monitorowanie udostępnionego katalogu poprzez vagrant rsync-auto. Po uruchomieniu polecenia udostępnione katalogi z włączoną opcją rsync-auto będą monitorowane i synchronizowane.

Po wywołaniu polecenia następuje inicjalizacja rsync i pierwsza synchronizacja po której rsync przechodzi w stan obserwacji. Gdy tylko nastąpi jakaś modyfikacja w katalogu, rsync powinien dokonać ponownej synchronizacji i tak aż do momentu wyłączenia mechanizmu.

RSync poza opcją rsync-auto posiada kilka innych opcji konfiguracji. O wszystkich możecie poczytać w dokumentacji, ja zaś chciałem wam powiedzieć jednak o jednaj bardzo przydatnej rsync__exclude. Ustawienie to pozwala na eliminację z synchronizacji pewnych katalogów, które nie muszą znajdować się na maszynie docelowej np. katalog git-a, IDE itp.

config.vm.synced_folder "./src", "/var/www/czterytygodnie", 
  type: "rsync", 
  rsync__exclude: ".git/"

W tym przypadku został wyeliminowany katalog z repozytorium GIT-a, które będzie zbędne na maszynie docelowej.

SMB

Ostatni sposób synchronizacji dedykowany systemowi Windows. Jest on dla Windows-a tym czym jest NFS dla Linux-a / OS X, czyli wydajnym mechanizmem synchronizacji dwukierunkowej. Jednak nawet system Windows musi w tym przypadku spełnić pewne wymagania. Mianowicie wymagany jest PowerShell w wersji 3 lub wyższej oraz wszelkie polecenia będą wykonywane z uprawnieniami administratora.

Typ ten posiada jedynie trzy opcje w konfiguracji:

  • smb_host – adres ip,
  • smb_password – hasło użytkownika Windows,
  • smb_username – login użytkownika Windows

Opcje te nie są wymagane i jeśli nie zostaną zdefiniowane to przy uruchamianiu zostaniemy poproszeni o ich podanie.

Nasza konfiguracja po zmianie sposobu synchronizacji może wyglądać następująco:

config.vm.synced_folder "./src", "/var/www/czterytygodnie", 
  type: "smb"

Podsumowanie

Udostępnianie katalogów wykorzystując Vagrant-a jest bardzo proste i przy niezbyt złożonych operacjach nie powinno powodować żadnych problemów. Jednak jeśli projekt jest duży, zawiera frameworki pokroju Symfony / Laravel / Zend Framework, to praca w takim środowisku może być mało optymalna. Nie zawsze bowiem wystarczy zmiana rodzaju synchronizacji na NFS czy SMB. Czasem trzeba będzie posiłkować się utrzymywaniem części projektu bezpośrednio w maszynie wirtualnej i synchronizacją rsync. Jednak niech was to nie odstrasza od tego rozwiązania bowiem potrafi ono bardzo usprawnić proces budowania środowiska.

Jeśli zaś chcecie wdrażać rozwiązania oparte o Vagrant-a na produkcję, to możecie śmiało cały projekt załadować do wirtualnej maszyny i zapomnieć o udostępnianiu katalogów.