This setup is not perfect. It’s not for everyone either. There are many different ways to setup your development environment depending on what you need and what you know.
This setup suits the needs of me and my team. YMMV.
That being said, this was not without its fair share of pain and confusion, so here are a few gotchas worth noting…
DNS and network alias… oh my!
The biggest pain point was without doubt setting up the DNS and Nginx element of this setup. By default, Docker does not make it easy for a container to gain access services on the host. This is by design and makes total sense.
However, sometimes you WANT to do this. I wanted Nginx in my container to proxy requests to a port on my host, in this case our Rails app. You cannot use
127.0.0.1 inside a container to reference the host, because that localhost address will always be the container itself, NOT the host i.e. think of
To circumvent this we create a network alias to our
lo0 network interface on the
192.168.0.99 IP address. This is then injected into our Nginx container thus enabling the proxying of requests to our host via the alias.
For further reading, this forum post proved to be very useful.
This is not a Docker tutorial
This series aims to show a working example of ONE way to use Docker in a development environment. A lot of Docker knowledge is assumed, although the various scripts and configuration files hide a lot of this away from you.
When learning Docker you will be faced with a steep learning curve. It took me a while to get my head around some of the concepts. Persevere!
It’s all time well-spent and once you have a solid understanding of Docker you can start to see – and use! – it’s power. This series is testament to that.
Why is the Rails app not in a container?
This is the burning question. I did initially try to go down this route, having everything in containers, including the Rails application.
However, having my Rails apps inside containers didn’t work for me, and here’s why…
- Ease of use. Having my Rails apps running on my host allows me to cherry-pick which apps I want running at any time. I can run one app, two apps, or all apps without changing any configuration files i.e. my Rails apps are decoupled (almost!) from my stack and Docker configuration.
- I don’t lose any of my shell setup loveliness. Running a Rails app in a container means every Rails command has to be executed within the container.
- Disk space. All my apps use the same Ruby and Rails versions, as well as a whole host of other common gems. Installing gems on my host saves me a ton of space.
- Having all gems installed on the host also makes jumping into the source code of a gem trivial and natural. I do this regularly.
- Performance. Having my Rails apps (and gems) mounted into a container seemed to adversely affect performance. Reloading seemed sluggish.
- Safety. Having my gems installed on my host makes it far less likely I will uninstall or delete them by mistake. Installing your gems in a data volume makes this easy to do. Sure, you can rebuild easily, but it takes ages to do this and it’s a waste of time. Additionally, Docker doesn’t clean up after itself very well, at least not automatically. I have some helper scripts to keep my system in good shape, which includes removing volumes. I don’t have to worry about deleting a volume in error.
I mentioned before that this demo is a simplified version of what I’m already using on my work machine. My team are also using this setup. It’s made my life much easier and I’ve learned more about Docker.
Extending docker-demo-stack should be trivial, and you could easily have multiple versions of this demo, each in a subdirectory, to handle the various stacks you may have to work with.
Feel free to hit me up with any questions you may have.