Understanding vagrant with a docker provisioner - vagrant

So my goal here is to have Vagrant spin me up a VM that I can use as a rails web application development environment. I am very, very new to Vagrant, Docker, etc. and wanted to check if this even makes sense:
Should I be creating one Docker image, or two? My thought was that one image would be for rvm, ruby, and rails, and the other image would be for Apache.
The goal would be something that could be distributed to a few people, who would then get the exact same environment set up easily.
Here is my current Vagrantfile:
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "phusion/ubuntu-12.04-amd64"
config.vm.network "forwarded_port", :guest => 80, :host => 5000
# Share the docker configs
config.vm.synced_folder "./docker", "/docker"
config.vm.provision "docker" do |d|
d.build_image "-t me/rvm-dev /docker/rvm-dev"
d.run "me/rvm-dev"
end
config.vm.host_name = "coursera-rail.dev"
config.vm.network :forwarded_port, guest:80, host:8080
end
And here is my current (probably wrong) Dockerfile
(as an aside, I am trying to find some good guidance on creating a "docker" user account so I don't run everything as root)
## Dockerfile
FROM ubuntu:latest
RUN apt-get update
RUN apt-get upgrade -y
RUN apt-get install -y curl
RUN mkdir -p /tmp/downloads
## Install RVM, Ruby, Rails
RUN cd /tmp/downloads
RUN \curl -L https://get.rvm.io | bash -s stable --ruby --rails
Lastly, the above works, and if I use vagrant ssh I can head in to my VM, but obviously I am unable to use RVM without doing docker run -i -t me/rvm-dev and getting a shell with docker. Is this supposed to be the workflow?

In my humble opinion, the best flow would be to
1) separate your app and db stack into vagrant boxes
or
2) run docker on the host (the physical machine) and your DB instance (mysql, etc..) inside a vagrant box.
Option one is best because you are "sandboxing" both layers of the stack (DB and APP) inside Vagrant thus leaving the OS on your local machine (windows, Linux, Mac OSX) instact. Of course, you could install/run your IDE on the physical machine.

Related

The safety of running vagrant images

I have external vagrant running scripts - is it safe to run something like that locally (without risking doing anything externally in production)? I've been using vagrant a long time ago, but it's supposed to be used locally in a dev environment, right?
I have the following Vagrantfile:
config.vm.define "vmmachine" do |vmmachine|
vmmachine.vm.hostname = "machine-dev"
vmmachine.vm.network :private_network, ip: "192.168.10.12"
vmmachine.vm.provision :shell, :path => "vagrant/machine/init.sh"
end
vagrant/machine/init.sh is:
#!/usr/bin/env bash
export DEBIAN_FRONTEND=noninteractive
# Add repo
echo "deb http://www.somewebsite.com testing main" > /etc/apt/sources.list.d/machine.list
# Add key
wget --quiet -O - https://www.somewebsite.com.key.asc | apt-key add -
apt-get update
apt-get install -q -y screen htop vim curl wget
apt-get install -q -y machine-server
service machine start
apt-get clean
Also, why is it 192.168.x.x instead of 127.0.0.x? What is the benefit of that?
Yes Vagrant can definitely be used in local development. I'm not entirely sure what scripts you're trying to run but it looks to me like running it locally would definitely be an option. I used Vagrant as my local dev server for awhile and know of quite a few other devs who do so currently.
The reason Vagrant doesn't use 127.0.0.x is because your site is running in a VM on your computer and not locally on the computer itself. You basically connect to the VM through a local IP address Vagrant gives a small explanation about the IP address in their docs:
While you can choose any IP you would like, you should use an IP from the reserved private address space. These IPs are guaranteed to never be publicly routable, and most routers actually block traffic from going to them from the outside world.
So I would say they "officially" recommend using 192.168.x.x though they say you can use pretty much any IP you want.

vagrant box copy not working well

I cannot boot a vagrant box copy without problem.
I use "hashicorp/precise32" (I cannot install "ubuntu/trusty64" or 32 on my machine, I've tried everything. I guess it's because my pc is too old, 2009).
I can vagrant up using the default added box "hashicorp/precise32".
All works fine.
Then, I vagrant halt and do a copy of the vagrant box like that :
vagrant package --base myprojectvm_default_1437507203066_25705 --output mybox.box
vagrant box add mybox.box --name mybox
Then I vagrant destroy.
Then I change Vagrantfile : config.vm.box = "hashicorp/precise32"
to config.vm.box = "mybox"
THen I run vagrant up and I see this in my guest after minutes :
"Waiting for network configuration...
Waiting up to 60 more seconds for network configuration....
Booting system without full network configuration..."
Then some "Starting..." lines among other lines... and finally, machine booted.
Why "without full network configuration" ?
From the vagrant book
It is very common for Linux-based boxes to fail to boot initially.
This is often a very confusing experience because it is unclear why it
is happening. The most common case is because there are persistent
network device udev rules in place that need to be reset for the new
virtual machine. To avoid this issue, remove all the persistent-net
rules. On Ubuntu, these are the steps necessary to do this:
$ rm /etc/udev/rules.d/70-persistent-net.rules
$ mkdir /etc/udev/rules.d/70-persistent-net.rules
$ rm -rf /dev/.udev/
$ rm /lib/udev/rules.d/75-persistent-net-generator.rules>
on centos box, this is the command I am running
cd /etc/sysconfig/network-scripts/
sudo rm -f ifcfg-eth1
cd /etc/udev/rules.d/
sudo rm -f 70-persistent-net.rules
It then has always been working fine for me

Using Vagrant on cloud CI services

Are there any cloud CI services that allow Vagrant VMs to run using VirtualBox as a provider?
Early investigation shows this seems not to be possible with Travis CI or Circle CI, although the vagrant-aws plugin allows for the use of AWS servers as a Vagrant provider. Is this correct?
Update January 2021: GitHub Actions also supports Vagrant - and Vagrant/VirtualBox are both installed out-of-the-box in the MacOS environment (not on Linux or Windows currently!). See the possible environments here. Therefore I created a fully comprehensible example project at: https://github.com/jonashackt/vagrant-github-actions
1.: Create a Vagrantfile (and you're not limited to libvirt as with Travis, you have a full VirtualBox environment with nested virtualization working on GitHub Actions!) like this:
Vagrant.configure("2") do |config|
config.vm.box = "generic/ubuntu1804"
config.vm.define 'ubuntu'
# Prevent SharedFoldersEnableSymlinksCreate errors
config.vm.synced_folder ".", "/vagrant", disabled: true
end
2.: Create a GitHub Actions workflow like this vagrant-up.yml inside the .github/workflows directory in your repository:
name: vagrant-up
on: [push]
jobs:
vagrant-up:
runs-on: macos-10.15
steps:
- uses: actions/checkout#v2
- name: Run vagrant up
run: vagrant up
- name: ssh into box after boot
run: vagrant ssh -c "echo 'hello world!'"
You can even add caching for the Vagran boxes, this will safe you some seconds :)
Early 2020:
TravisCI is now able to run Vagrant finally! Thanks to this GitHub issue I learned about libvirt and KVM, which could be used together with the vagrant-libvirt Plugin to run Vagrant boxes on TravisCI.
An example TravisCI .travis.yml should look somehow like that:
---
dist: bionic
language: python
install:
# Install libvrt & KVM
- sudo apt-get update && sudo apt-get install -y bridge-utils dnsmasq-base ebtables libvirt-bin libvirt-dev qemu-kvm qemu-utils ruby-dev
# Download Vagrant & Install Vagrant package
- sudo wget -nv https://releases.hashicorp.com/vagrant/2.2.7/vagrant_2.2.7_x86_64.deb
- sudo dpkg -i vagrant_2.2.7_x86_64.deb
# Vagrant correctly installed?
- vagrant --version
# Install vagrant-libvirt Vagrant plugin
- sudo vagrant plugin install vagrant-libvirt
script:
- sudo vagrant up --provider=libvirt
- sudo vagrant ssh -c "echo 'hello world!'"
With the help of the generic Vagrant Box images from Vagrant Cloud you can also establish a workflow of using Vagrant + libvirt + KVM on Travis and Vagrant + VirtualBox on your local machine, if you like:
I created a fully working and 100% comprehensible example project here: https://github.com/jonashackt/vagrant-travisci-libvrt
Many CI services are not allowing to run Vagrant via LXC or Virtualbox as it will require nested virtualization (running VM in VM) or a pure bare metal server provisioned for you.
Current 2021 (updated) situation:
Github Actions can do it.
Travis was able to run Vagrant with some workarounds.
AppVeyor allows running VirtualBox (non-free plans).
You can't under CodeShip
You can't under CircleCI
Don't know about other CI services, will investigate further.
I hope during the time we'll see CI services allowing to run Vagrant with Virtualbox or LXC, but for now Docker (with its limitations) is the only option.
Personally, I would be happy to use it for integration tests against different platforms/linux distros via Test-Kitchen CI or similar.
AppVeyor runs Vagrant using VirtualBox as a provider. Furthermore, you can use other providers like libvirt or Hyper-v.
Updated:
Github Actions is another option. Only Mac OS environment has nested virtualization enabled. An example is here and here.

vagrant ash: sudo: not found

When starting my vagrant box with a small 15MB Busybox image, the first time I get an error during the phase
Mounting shared folders...
It seems vagrant is trying something with sudo, which isn't istalled. I get this error:
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!
mkdir -p /vagrant
Stdout from the command:
Stderr from the command:
ash: sudo: not found
It works so far, I can login as root with the password vagrant, but I guess this is not perfect?
This is my setup: https://github.com/rubo77/ffnord-example/blob/pyddhcpd/Vagrantfile
config.ssh.username = 'root'
config.ssh.password = 'vagrant'
config.ssh.insert_key = 'true'
config.ssh.shell = 'ash'
(0..9).each do |i|
config.vm.define "gc-node0#{i}" do |node|
end
end
By default vagrant share/sync the directory /vagrant (guest) with the current project directory, the one containing the Vagrantfile (host), more directories can be shared using config.vm.synced_folder, I don't know if the default /vagrant can be disabled.
If you aren't using the shared directories feature then the missing sudo isn't a problem.
If your filesystem is writeable you can create the /vagrant directory once, so on next up vagrant shouldn't try to sudo mkdir again;
but assuming you're using VirtualBox (I don't know about others emulator behavior/architecture) you'll face another problem, shared directories require the kernel modules vboxsf and vboxguest (from VirtualBox Guest Additions) to be built (against the running kernel sources) and loaded (insmod), and the command mount.vboxsf to be built and installed in /sbin, plus your busybox require the option mount helpers enabled because vagrant use mount -t vboxsf and not mount.vboxsf directly, when vagrant try to mount the shared directories and those requirements aren't matched there is a long timeout before failing with error (a minute/two or more).
Notice that busybox (current stable) support sudo, is just disabled by default.
If you're building the buildroot yourself from sources I can tell that the shared feature works (I managed to get an image with busybox to work as vagrant expect), if you're using some pre-built kernel/busybox... may be a problem, you have to find matching binaries for vboxsf, vboxguest, mount.vboxsf and if the mount helpers option is disabled in your busybox you need to find a workaround (perhaps modifying vagrant to use mount.vboxsf).

Vagrant Puppet guest cli output on host

I have been using Vagrant with Puppet for a few days; this is a cool tool in the context of automation.
I have a question. Sometimes apt operations (or git clone) take a few minutes to download all the packages. Vagrant logs all operations on the host's cli, but only those that have already been performed. There is no information about the currently executing task, so I am not sure if the machine hanged or if an operation is still running.
Is there a possibility to output all the guest's cli output on the host's cli in Vagrant?
I am running Vagrant 1.4.3 on Windows 8 via Git Bash and this solution didn't work for me:
Vagrant provision live output
You can pass extra options to the puppet command in the Vagrantfile, among which --verbose and/or --debug. This is the example reported in Vagrant documentation (link):
Vagrant.configure("2") do |config|
config.vm.provision "puppet" do |puppet|
puppet.options = "--verbose --debug"
end
end
By passing these options the output in the host console should be much more verbose.

Resources