Proof of concept to explore various Vagrant/Docker setups
In the past, we have used Vagrant for our VM but ran into file system performance issues with Node.js based projects. The key grievance was syncing the local folder .
caused significant delay in picking up file system changes on the remote machine. This slowed down developer workflows and caused frustration.
We want to see if other non-default setups will work as well as how to use Docker. For this exercise, we have bloated our node_modules
folder (see package.json
for details).
As a baseline, we ran the watch script locally on the host machine.
Steps:
# Install our Node.js dependencies
npm install
# Start our script
npm start
Results:
- File system change events:
nodemon
restarted immediately - File system read/write:
index.js
takes 300ms to load heavy dependencies
https://www.vagrantup.com/docs/synced-folders/basic_usage.html
This setup uses VirtualBox and the default shared folders to sync a lot of node_modules
between the local and remote machine.
For this experiment, run the following:
# Start our Vagrant machine
export ENV="default"
vagrant up
# SSH into the machine
vagrant ssh
# Start up a simple watch + reboot script
cd /vagrant
npm start
Results:
- File system change events:
nodemon
restarted immediately - File system read/write:
index.js
took 2000ms to 3500ms to load heavy dependencies
As a second baseline, we have a setup with no sync at all. For this, run the following:
# Start a default Vagrant machine
export ENV="default"
vagrant up
# SSH into the machine
vagrant ssh
# Copy the contents of `/vagrant` to a temporary folder
# DEV: This may take a while...
cd "$(mktemp -d)"
cp /vagrant/* . -r
# Start up a simple watch + reboot script
npm start
Results:
- File system change events:
nodemon
restarted immediately - File system read/write:
index.js
takes 300ms to load heavy dependencies
"Disabling" on https://www.vagrantup.com/docs/synced-folders/basic_usage.html
Add a disabled sync for node_modules
to see if we can prevent Vagrant from syncing this folder
Steps are the same as "Vagrant with VirtualBox + default sync" but export ENV="ignore"
Unfortunately, we were unable to get this implementation working.
Additionally, we attempted to sync folders via Dir::glob
+ reject!
but Vagrant isn't setup for syncing individual files.
Moved to NFS based sync for node_modules
Steps:
# Install NFS dependencies on host machine
# https://help.ubuntu.com/community/SettingUpNFSHowTo
sudo apt-get install -y nfs-kernel-server
# Start our Vagrant machine
export ENV="nfs"
vagrant up
# SSH into the machine
vagrant ssh
# Start up a simple watch + reboot script
cd /vagrant
npm start
Results:
- File system change events:
nodemon
starts within 300ms of save - File system read/write:
index.js
takes 600ms to 1400ms to load a heavy dependency
We have skipped this due to lack of integration; we would need to run a separate vagrant rsync-auto
process at all times.
We explored using vanilla Docker (i.e. no Vagrant wrapper). To get our example running, perform the following:
# Install Docker
# See https://docs.docker.com/linux/step_one/
# Build our container
docker build -t docker-explore .
# Run our container with the local directory mounted to /vagrant
docker run -i -t -v $PWD:/vagrant docker-explore /bin/bash
# Run our script
cd /vagrant
npm start
Results:
- File system change events:
nodemon
restarted immediately (local performance) - File system read/write:
index.js
takes 300ms to load a heavy dependency (local performance)
Notes:
- We should be able to use a
bootstrap.sh
strategy viaADD bootstrap.sh
inside ofDockerfile
- We can connect to a running container via
docker-exec
- For example
docker exec -it 3f0f94a39ae2 /bin/bash
will connect to the container with id3f0f94a39ae2
- For example
- To expose a port on an existing container, we must
stop + commit (with change) + start
- http://stackoverflow.com/a/26622041
- It seems that
docker-commit
supports adding inEXPOSE
instructions via change as well
- To persist data across container rebuilds, we can use a data-only container
Conclusions:
I'm on the fence about using Docker at the moment. It seems like it should work with some paradigm changes but there are definitely going to be unforeseen issues that we have previously solved with Vagrant.
We might be best off with sticking to Vagrant but keeping Node.js local for now.
We started getting this set up but decided to focus on Docker instead of learning both how it works + how it integrates into Vagrant.
I think the main benefit here is docker run {{container-id}}
becomes vagrant docker-run
(i.e. no id/name necessary).
We are trying another container based solution for Vagrant. This one isn't as portable as Docker but it has the same syntax as Vagrant VirtualBox 👍
Steps:
# Install LXC dependencies
sudo apt-get install lxc redir
# Install vagrant-lxc plugin
vagrant plugin install lxc
# Start our Vagrant machine
export ENV="lxc"
vagrant up
# SSH into the machine
vagrant ssh
# Start up a simple watch + reboot script
cd /vagrant
npm start
Results:
- File system change events:
nodemon
restarted immediately (local performance) - File system read/write:
index.js
takes 300ms to load a heavy dependency (local performance)
Notes:
- We are using a secondary user on our machine so the UIDs don't align. As a result, we need an additionl script during provisioning
- We need to use a special image for LXC support. However, it's well documented:
- https://www.wildcardcorp.com/blog/making-vagrant-virtualbox-nfs-less-painful-with-sparse-disk-images
- Seems to be OS X specific and other options listed are network based as well
- https://github.com/mrdavidlaing/vagrant-unison
- VM + another sync program
- TODO: Try it out but not confident in it (also need to do same separate command as
rsync-auto
)