I'm playing around with docker and vagrant to isolate my dev environment on os x. So far so good, i've found a couple of good tutorials and introductions but some of the posts seems to be outdated as vagrant envolved...
My main issue the mounting of a shared folder from my host machine to the docker container – it kind of works, but i have no idea if i'm running into a vagrant/docker issue or just doing something wrong.
Let me explain my current state:
I'm using the following Vagrantfile.boot2docker
for my virtual machine and mount the current directory to /app
in the vm. I can see the folder inside the vm and it's content changes, whenever I update the files on the host machine.
VAGRANTFILE_API_VERSION = "2"
Vagrant.require_version ">= 1.6.3"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "yungsang/boot2docker"
config.vm.network "private_network", ip: "192.168.33.10"
config.vm.synced_folder ".", "/app", type: "rsync"
# Uncomment below to use more than one instance at once
# config.vm.network :forwarded_port, guest: 2375, host: 2375, auto_correct: true
# Fix busybox/udhcpc issue
config.vm.provision :shell do |s|
s.inline = <<-EOT
if ! grep -qs ^nameserver /etc/resolv.conf; then
sudo /sbin/udhcpc
fi
cat /etc/resolv.conf
EOT
end
# Adjust datetime after suspend and resume
config.vm.provision :shell do |s|
s.inline = <<-EOT
sudo /usr/local/bin/ntpclient -s -h pool.ntp.org
date
EOT
end
config.vm.network :forwarded_port, guest: 5000, host: 5000
end
In my Vagrantfile
i'm creating two seperate docker containers, a isolated redis instance and my node app which mounts the app directory from the vm to the container d.volumes=["/app:/foo"]
VAGRANTFILE_API_VERSION = "2"
ENV['VAGRANT_DEFAULT_PROVIDER'] = 'docker'
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.define "redis" do |redis|
redis.vm.provider 'docker' do |d|
d.image = 'redis:latest'
#Comment the line below if you are running on a linux host
d.vagrant_vagrantfile = "./Vagrantfile.boot2docker"
d.name = 'redis'
end
end
config.vm.define "node_app" do |node_app|
node_app.vm.provider "docker" do |d|
d.name = 'node_app'
d.build_dir = "."
#Comment the line below if you are running on a linux host
d.vagrant_vagrantfile = "./Vagrantfile.boot2docker"
d.ports = ["5000:5000"]
d.volumes = ["/app:/foo"]
d.link('redis:redis')
end
end
end
My Dockerfile
loads the latest nodejs container and copies the package.json
and app.js
from the host to the app
directory before installing dependencies and running the app. The static copy of the folder from the current directory works well, my app connects to redis and works i can reach it as expected at http://192.168.33.10:5000 ! (Note: i've commented out the VOLUME command here, so files are just copied at container the beginning of the lifecylce)
FROM node:latest
#use vagrant shared folder
ADD . /app
WORKDIR /app
# install your application's dependencies
RUN npm install
# exposes our app port
EXPOSE 5000
# replace this with your main "server" script file
CMD ["node", "app.js"]
After my first success i've tried to use my shared volume and changed the Dockerfile
as follows:
FROM node:latest
#use vagrant shared folder
ADD . /foo
# mount volume
VOLUME ['/foo']
WORKDIR /foo
# install your application's dependencies
RUN npm install
# exposes our app port
EXPOSE 5000
# replace this with your main "server" script file
CMD ["node", "app.js"]
I've reloaded the vm and got a bunch of errors: mostly no package.json found
or npm module missing (express)
. I've figured out – by using the first Dockerfile and the following node.js app https://gist.github.com/joernroeder/e86a3882360497c828f9 (which simply lists the files in /foo
and there content) – that the volume needs some time to mount, replaces the content of foo
with it's own initial content and removes the generated files (including the node_modules
directory).
The files inside /foo
therefore reflects the changes from the host, and syncing works well.
Do you have any tips and tricks for me how i can mount the volume in time, or are i'm doing something completly stupid here?
Thanks
The defined volume for the node_app container
d.volumes = ["/app:/foo"]
will be available only after the dockerfile is executed and the container is started.A workaround is to first use
Add /app /foo
in the dockerfile and after container creation the static added data will be overriden by the volume mount.An example implementaion with docker and compose can be found here: https://github.com/b00giZm/docker-compose-nodejs-examples/tree/master/02-express-redis-nodemon. Note that this is also possible without compose just using vagrant and docker providers.