I can't figure out a good way to set up a development environment on OS X using Docker and Boot2Docker. The problem I'm hitting is how to manage the source code so that:
In theory, this should be easy to do by mounting my source code as a volume:
docker run -it -v /path/to/my/source/code:/src some-docker-image
Unfortunately, this has two major issues that make it completely unusable on OS X:
For example, here is how long it takes Jekyll to compile my homepage if the source code is part of the Docker image:
> docker run -it brikis98/yevgeniy-brikman-homepage:v1 bash
root@7aaea30d98a1:/src# time bundle exec jekyll build
[...]
real 0m7.879s
user 0m7.360s
sys 0m0.600s
Here is the exact same Docker image, except this time, I mount the source code from OS X:
> docker run -it -v $(pwd):/src brikis98/yevgeniy-brikman-homepage:v1 bash
root@1521b0b4ce6a:/src# time bundle exec jekyll build
[...]
real 1m14.701s
user 0m9.450s
sys 0m3.410s
The default watch mechanisms in SBT, Jekyll, and grunt use technologies such as inotify, which do not work if they are running in a Docker container and the changes are made in OS X to a mounted folder.
I searched for solutions (including all the ones on SO) and tried out a few of them, but have not found a successful one:
Has anyone found a solution that actually works and allows you to productively develop code with Docker and OS X?
I have finally found a solution that seems productive using Boot2Docker + rsync. I've captured the details on how to set this up in my own answer as well as an open-source project called docker-osx-dev.
Docker may speed up your development process significantly, but not necessarily your app itself. Although it helps with making your application scalable, so more users will be able to use it, the single instance of your app will usually be just a hint slower than without Docker.
Developing inside a Docker container generally means starting a container and leaving it running, while you edit your source code. As you make changes, you see the changes appear in the container. To get your source code inside a container, you can use something called a bind mount.
I've decided to add my own answer with the best solution I've found so far. I'll update this if I find better options.
The best solution I've found for setting up a productive development environment with Docker on OS X is: Boot2Docker + Rsync. With rsync, build times in a Docker container are on par with running the build directly on OSX! Moreover, the file watcher code does not need polling (inotify
works since rsync uses normal folders), so hot reload is almost as fast.
There are two ways to set it up: an automated install and a manual install.
I've packaged all the steps for setting up Boot2Docker with Rsync into an open source project called docker-osx-dev. The code is a bit rough, but I've been successfully using it for several weeks to easily switch between 3 projects with 3 different tech stacks. Try it out, report bugs, and submit some PRs! Also, see my blog post, A productive development environment with Docker on OS X for more info.
brew install boot2docker
.boot2docker init && boot2docker start --vbox-share=disable
.boot2docker shellinit
and copy the environment variables it prints out into your ~/.bash_profile
file.boot2docker ssh "tce-load -wi rsync"
./foo/bar
folder from OS X, you need to create /foo/bar
on the Boot2Docker VM: boot2docker ssh "mkdir -p /foo/bar && chown -R docker /foo/bar"
.rsync --archive --rsh="ssh -i $HOME/.ssh/id_boot2docker -o StrictHostKeyChecking=no" /foo/bar docker@dockerhost:/foo
. Check the rsync docs for various settings you may want to enable, such as using --exclude .git
to exclude the .git
folder when syncing.brew install fswatch
) piped into rsync.docker run
to fire up your Docker container and use the -v
flag to mount the folder you're syncing: docker run -v /foo/bar:/src some-docker-image
.inotify
), and the build should run fast because all the files are "local" to the container.boot2docker ip
command to find out what IP it's on.Update: Now that docker for mac is in beta with non-hack functionality, going that route may be a lot more reasonable for local development without a essay's worth of hacks and workarounds.
Don't. I know that's not the answer you are probably hoping for, but take an honest evaluation of the cost/benefit of trying to get local source code + dockerized execution vs just doing local development on OSX.
At some point all the issues, setup effort, and operational pain points MAY be resolved well enough, but as of right now my take on this is it's a net loss.
Issue #1: Mounted volumes on Virtual Box (which use vboxfs) are extremely slow
Wait a while and this will almost certainly improve.
Issue #2: File watching is broken
I'm not sure a fix for this is in the near future. If this type of functionality is key to your development workflow, I would consider this a dealbreaker. It's not worth a major R&D effort when compared to just using rbenv/bundler to manage your jekyll/ruby installs and running them locally on OSX like folks have been doing successfully for the past decade+.
Just like "the cloud" has zero involvement in my local development setup, at the moment, docker is a win for testing/staging/deployment and for running databases and other third party components, but the applications I'm actually coding get run straight on OSX.
Docker for Mac and Windows shall be the definitive way of developing with Docker on OS X (and Windows). A Docker product, the software is an “integrated, easy-to-deploy environment for building, assembling, and shipping applications from Mac or Windows.” It purports to be able to solve the issues presented by the OP. From its March 24, 2016 announcement:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With