Running Composer on guest VM with Vagrant and rsync only keeps - vagrant

I searched about this topic and could not find anything so here I go with my question: I have Linux running in Vagrant as guest, Windows as host; I shared folders with rsync to speed up development with Rails (using NFS or SMB is extremely slow); some of my PHP dependencies get installed with Composer within my project, so when I run Composer via SSH from the guest it downloads and installs them, however, when I restart my VM I lost the dependencies downloaded and need to start over.
So is there anything I could do to run Composer remote or locally, and not loose my changes? so far I've tried changing the sync type to SMB, run Composer, and then go back to rsync, however, I need to switch on and off and I'd like something more automated...
Thank you for your help!
Carlos.

From the docs:
The rsync synced folder does a one-time one-way sync from the machine running to the machine being started by Vagrant.
So this is intentional: If you don't get the result of ANY changes (not just Composer) out of the vagrant machine onto your copy on Windows, it will always get lost inside the VM.
Use SMB or shared folders and bear the performance penalty. Or try and get a NFS server for Windows and install the files inside the VM via NFS.

Related

Forgetting a VM in Vagrant

I've started a VM on Google Compute Engine using Vagrant with the vagrant-google provider. I no longer wish to control the VM using Vagrant, but I would like it to keep running without me interrupting it.
What's the proper way to have Vagrant "forget" about this machine?
so the instance has been installed on GCE and you can control directly from there.
Locally you can delete the .vagrant folder that vagrant created in the folder when you launch it
After this to remove references you can run vagrant global-status --prune which will remove invalid entries and clean vagrant conf file from this machine

Running vagrant on two macs

I have Vagrant installed on my iMac but I would also like to install and run it on my MacBook. Is it possible to run the same Vagrant box across two Macs?
I have done a Vagrant up command within a shared Dropbox folder - so i'm guessing that all I need to do is install vagrant on the second mac and then navigate to the Dropbox shared folder and do vagrant up.
Would this work?
Known solution:
ssh to the host machine
user#MacBook: ssh user#imac
then vagrant up; vagrant ssh.
user#imac: vagrant up; vagrant ssh
vagrant#vagrantvm:
This would be the most straight forward way I can think of.
Another option:
RDP to imac and run vagrant up;vagrant ssh as normal
Yet another option:
If your vagrant file is complete enough you should be able to vagrant up on any host to give you the same vagrant env. This relies on your use case but is how I use vagrant.
Vagrant stores the state of the machine and machine id inside the .vagrant folder. The running machine (vm) itself is handled by virtualbox/vmware or any provider your using. Lets say the virtualbox box is stored somewhere else on your system and referenced by Vagrant.
If you access the folder from two systems your basically remote controlling two different machine on two different systems. Not a good solution. Furthermore, you will run into problems if the states are different, e.g. its "up" on system one but "destroyed" on system two.
Additionally to the above solutions I propose the following:
Vagrant Share! Enable Vagrant http-/ssh-Share between your systems.
Vagrant machines should be repeatable and destroyable. Therefore, put your Vagrantfile under version control and checkout on the two systems.
Configure your provider to store the box itself on the dropbox.

Hot deploying app builds to Vagrant

Please note: although I mention Gradle/Groovy in this question, this is strictly about Vagrant usage, and could just as easily apply to any other language/build system.
I am new to Vagrant and am trying to figure out how Vagrantfiles, when pushed to source control, interact with that repo's build.
Say I have the following repo, built by Gradle:
src/
main/
groovy/
<lots of groovy source>
test/
groovy/
<lots of groovy test source>
build.gradle
settings.gradle
Now let's say that, without Vagrant, I would normally clone this repo and run gradle clean build to run unit tests on the code, and ultimately, package it into a running program (executable JAR). Then a gradle run starts the app.
Well, in a lot of GitHub repos I see Vagrantfiles committed. So obviously this is to make it easy to spin up a VM and run the respective app inside of. I'm trying to figure out the typical "flow" of incorporating a Vagrantfile into my repo above such that developers can:
Clone the repo
Build with Gradle
Somehow, deploy to the Vagrant box
Test the running app instance (running inside the box)
Tweak the code } #4, #5 and #6 quick/rapid dev-test-tweak cycles utilizing hot re-deploys
Re-test
Take a look at this Vagrantfile for a CAS server (chosen at random). I think this is where the magic happens, in terms of deploying and restarting the server on the box, but I checked the Vagrant docs for shell.inline and nothing concrete came up.
So I ask: How do I "integrate" my Vagrantfile with my build, such that the build produces a deployed, running app? Further, what do my run/deploy-test-code-redeploy cycles look like with Vagrant boxes (what I call "hot deploying")?
I'm going to explain how I would achieve what you are looking to do, this might not be the official way to do it, so anyone with more Vagrant experience should please provide pointers on where it can be improved. I've been working with Vagrant for about 6 months now. You say you are new to Vagrant, so I'll be as complete as I can, even though some parts you have probably already mastered, but might be useful to other users.
tl;dr; Skip to Creating the Vagrantfile section if you are already familiar with how the Vagrantfile works
Let's start with what the example Vagrantfile is doing.
config.vm.box = "puppetlabs/centos-6.5-64-puppet"
This is telling Vagrant to pull the box on which everything else is built. You can find a lot of official and community contributed boxes on the Vagrant Cloud. This one being from puppetlabs, based on CentOS 6.5 64-bit with Puppet already installed.
config.vm.network "forwarded_port", guest: 8080, host: 8088
This is telling Vagrant to forward port 8088 on your host to 8080 on the Vagrant box. So accessing http://127.0.0.1:8088 on your host will access port 8080 on the guest.
config.vm.provision :shell do |shell|
Provisioning is the process of setting up the Vagrant box when it is ran for the first time. Provisioning will only run once for a new VM, unless forced. See the provisioning section of the Basic Usage Vagrant Docs. This one specifically is executing a bunch of shell commands when it is being provisioned.
shell.inline = "command;
command;"
Shell inline is sending these commands, seperated by the semicolon, to the box. This is to automate the commands as if you were typing them in an SSH session yourself. The Vagrant Docs on Shell Provisioning has some more advanced uses where you can define an actual file to be executed.
Note: Your shell script should not try to execute tools that have not yet been installed. (ex. Running a Python script where Python is not available yet).
config.vm.provision "puppet" do |puppet|
I can't comment much on the Puppet section since I'm not a Puppet user (yet, probably). This is setting some Puppet values.
shell.inline = "cd /vagrant && mvn clean package;
sudo cp target/cas.war /srv/tomcat/cas/webapps/;
sudo /sbin/service tomcat-cas restart"
This is also executing shell commands. Basically changing directory, cleaning, copying cas.war to the webapps directory and then restarting the service. More on the /vagrant shared folder later. Now we have enough to start building our own Vagrant file on. I'm going to keep the sample simple to make it generic.
Creating the Vagrantfile
You will most likely want to build on a Vagrant box that already matches your requirements, but for now, let's not do that. You can however find a lot of already created boxes on the Vagrant Cloud. I'm going to show you how to get a (very) simple Python app running using Flask.
Pick your favourite distribution from the available Vagrant boxes. I'm going to use ubuntu/trusty64 since I use it on a daily basis. All command should be easily translated to other distributions.
Create a new directory for your project and open a shell / console window in it.
Using the console, initialize your Vagrant box vagrant init ubuntu/trusty64. This will create a base Vagrantfile for you to work from.
Open your Vagrantfile and uncomment config.vm.network "forwarded_port", guest: 5000, host: 8080. We want port 8080 to take us to port 5000 on the guest machine. Tip: For your project, it will be wise to choose a port that is most likely not already in use to avoid clashing with other apps. 8080 might be bad choice, 8089 will be better.
Let's add some scripts to execute on provisioning. Since Python is shipped with Ubuntu (and most other I know) we don't need to install Python, but we do need pip (a Python Package manager) and Flask.
config.vm.provision :shell do |shell|
shell.inline = "cd /vagrant;
sudo apt-get -y install python-pip;
sudo pip install Flask;"
end
This will change the directory to the Vagrant share. Install pip using Ubuntu's package manager, then install Flask using pip. The -y flag is to automatically have apt-get install without prompting for a yes/no question. You might need to run Vagrant up --provision a couple of times to get all your commands 100% correct.
Note on the Vagrant share: The Vagrant share is a directory that is synced between the host and guest machine and will be available under /vagrant. It includes all the files and directories in your project directory (where your Vagrantfile resides).
We now have all the tools we need to run our app. I've created an incredibly simple Flask app as a sample. Download it to your project directory from this Gist and name it app.py
Now we'll be able to run the Python app located in your project directory. I like to keep the install sections and running sections seperate. So add another section that starts the app.
Note: The & makes the app fork to the background so the vagrant up can complete. You'll probably want to do something more fancy than this with your app.
config.vm.provision :shell do |shell|
shell.inline = "/vagrant/app.py &"
end
Finally we can start everything and have Vagrant do its magic. In your console, in your project directory (where your Vagrant file is located). Run vagrant up.
Moment of truth. Open your browser (on the host) and browse to http://127.0.0.1:8080/. You should see Hello Vagrant Provisioned World!.
That takes care of the provisioning of your app. Automatically, from a Vagrantfile, that you can commit with your project code.
Now to get to your initial steps, and how this fits in.
Integrating into your development workflow
I'm listing your steps, integrated with Vagrant.
Clone the repo
This step stays the same, with the exception of a Vagrantfile included in your repo with provisioning for any required libraries and tools required for your project.
Run vagrant up in the project directory. This will automatically create and provision the box and share your project with the box.
You can build the project in the Vagrant provisioning steps, but if you are actively developing the application, you might not want to do that.
Test the running app instance (running inside the box) - Simply SSH into the box, enter the `/vagrant' directory and run your app.
Tweak the code } #4, #5 and #6 quick/rapid dev-test-tweak cycles utilizing hot re-deploys
Since your project is shared live between the host and the guest. you can simply stop the app (if running) and run the app again on the guest. No copying needed.
Re-test
This will give you quick developent cycles while keeping the environment the same. A new developer can simply clone and vagrant up to get going on the project without worrying about the environment and whatnot.
Continuous Integration is a vast topic. You can still apply the practises to your repo, etc. But I'd skip the CI deployment process while developing. I make use of Jenkins and Capistrano for my CI deployments, but it is too heavy weight for development. In production I won't use Vagrant since it will double-virtualize your VM already (unless you run bare metal). For production I'll make use of Docker and Fig.
I hope this explains how to integrate Vagrant into your flow for your project, please do comment if anything needs clarification. I believe the sample should word perfectly, since that is the goal of using Vagrant.

Where is Vagrant saving changes to the VM?

I am just starting with Vagrant and I am having a little trouble understanding a few details. I have read through the docs but still am missing a basic concept. When I want to start a Vagrant box I run:
vagrant up
This will "build the VM based on the box" I understand that the boxes are stored at ~/.vagrant.d and in fact I have packaged up my own box from a base Ubuntu box. However, when I run vagrant up and start to add files to the vm, where is the virtual hard drive for the vm stored? For example, when I run apt-get install apache2 and the root system is modified, where is this modified?
When I do a du on my current directory I do not see any changes. I also do not see any changes in the ~/.vagrant.d directory. However, I can do vagrant halt, restart my local machine and then run vagrant up again and the changes are persisted somewhere.
vagrant up also reports
[default] VM already created. Booting if its not already running...
Can someone tell me where the VM is created and where the changes are made?
Vagrant imports the base box which is located at ~/.vagrant.d/boxes/, like you said.
This is where the base boxes are kept. It uses it to start a VM from the clean state. When importing a VM, the responsibility of where to store data files and VM state is up to VirtualBox itself. This is a configurable location but typically defaults to ~/VirtualBox\ VMS for Mac OS X and Linux. In Windows the boxes are kept in %userprofile%\.vagrant.d\boxes
It is easy to find the place where they are getting created, regardless of what platform you happen to be using.
1. Start VirtualBox.
2. Go to the VM that shows as running instance.
3. Check out the Settings ->Storage.
4. You can find the path to location where VMs are created and stored in your file system.
I always change the directory that Virtualbox uses by default for VMs. Normally it is in your profile folder in Windows.
I change it to something like "D:\VHDs\VBox\" and there I found my vagrant test vm: "test01_1347456065". It was called test01, so I guess vagrant adds the numbers to keep things unique.

Developing on Windows -> Deploying on a Virtual Machine?

Is there an easy way to integrate with VirtualBox such that I could develop under the host, Windows, and deploy and run scripts via a mounted folder in a guest linux system?
I'm looking to develop for Linux under Windows, kind of.
You can use VirtualBox's Shared Folders feature to enable your Ubuntu virtual machine to mount a directory of your Windows host. However, you're likey to be deal with some impedance mismatches like different line endings. I hope that is the least of your worries.
You might want to check out vagrant http://vagrantup.com/
It provides a nice and easy system to create a VM from a template in Virtual Box, and will automatically mount the project folder in the guest VM. The config can also easily be included in your project so others can use it.
I develop in PHP. And I use Debian as guest OS, and Win7 as host OS.
You can done automaticly mount share folder by:
new a file in /etc/init.d/ named mnt_win_sf, than you edit it:
It must has the same info head with /etc/init.d/apache2. And you need just one line of command:
mount -t vboxsf share_folder_name mount_point
We also need to excute this script before apache2, so we edit /etc/init.d/apache2. In the Require Start line, add mnt_win_sf
update them by:
sudo update-rc.d mnt_win_sf defaults
sudo update-rc.d apache2 defaults

Resources