Coding is fun, debugging issues on other team members machines isn't. It works on my machine doesn't cut it anymore!
This post outlines how to run your code in a container rather than directly on your machine including how to debug and run tests, why you should do it and what the trade offs are.
It works on my machine
It's a bit of a joke between old school developers from the days where sharing code involved passing physical media between each other. But even today with all the fancy CI/CD it costs serious money and causes massive frustration. If you have ever worked on a team where you rely on code created by a team member, there is at least one time during the project that you just can't get it to work. You call the person who developed it across, try everything you can think of, delete everything, reinstall, do it again, then you both sit with blank expressions staring at the screen slowly loosing the will to live.
How do containers solve this problem?
Like most software solutions this problem was modeled against one that was solved decades ago in the 1950's. Before the 50's most cargo ships were transporting entire lorries including the trailer and the cab. Then Malcolm McLean came along. He owned a lorry company and saw what a massive waste of space this system of transporting the whole vehicle, so he made detachable containers that fit both on the trailers of the lorries and in a specially designed cargo ship and container ships as we know it were born.
If we translate this back to software, containers are self contained processes on your machine that share some of your underlying OS and add some additional functionality. All the isolation of a VM without the duplication of an operating system. This isn't a new concept and can be traced back to Unix V6 but it took until 2013 for containers to become easy for the likes of us mortals to use.
So, back to using the things.
Why you would want to do this.
- Versions of any runtimes (e.g. node) are synchronized across the team.
- All dependencies managed by a dependency manager (e.g. npm) will be the same version and compiled on the same OS
- Code can use built-in optimized OS specific functionality like
grepwithout having to build in a shim for different operating systems.
- It is easier to deploy to production later either using a container orchestration systems or use the image definition to build up the bare metal.
- Have the ability to share these pre-built images between developers
- Easier to create a releasable production product without any more configuration, testing
- All local settings are now in code, environment variables, arguments, port numbers etc.
The trade offs
- Some complexity to begin with
- Adding additional maintenance
- Requires staff to have additional skills / knowledge of linux / chosen OS (could be also a benefit to upskill?).
- Probably overkill if you are on a team of one or prototyping and not relevant to single page apps
Now the fun bit.
To achieve this nirvana we will be using docker. You can download this for Mac, Windows or Linux. Just have a look at the site.
Setting up your development environment
The best way to learn this stuff is just to get stuck in and try an break things. I've created a repo with a simple static page that is returned. You can expand to whatever the new hotness is.
I'll be going through an example code base that I prepared earlier with all of this set up, for the first bit all you need to install is:
Get the code
Open a terminal and clone the code locally
git clone [email protected]:peterjgrainger/development-with-docker.git
Start the container
Open a new terminal, this will display the logs of the running node process.
cd development-with-docker docker-compose up
This might take a while ☕️
Navigate to http://localhost:3000 to see your new beautiful site.
Debugging and editing
For debugging you need to install an vscode, you could also use the node debugger in chrome. Installing node if you don't already have it also quiets the vscode intellisense
Open a new terminal and navigate to the code we downloaded in the previous steps
cd development-with-docker npm install
Open vscode with the command line tools.
Go to the debug tab
Go to the Debug tab (shortcut on mac: ⇧⌘D)
Attach to the running docker
attach to Docker from the dropdown and press F5 or the ▶️ button beside the dropdown
Go back to the code view
Navigate to the
src/index.js file (file finder shortcut: ⌘p</kbd)
Click in the left margin to add a breakpoint on the line 15
You should be automatically focused on that line in vscode. You are now debugging!
Change the code and refresh http://localhost:3000 to see your changes.
What about testing.
You can do that too! Open a new terminal and run the tests inside the container.
docker exec site npm test
You should get the output
> ava tests/*.js ✔ foo ✔ bar 2 tests passed
Developing with docker
I hope this gives you an idea of the pros and cons of using Docker for your development environment. It's a bit of pain upfront but is worth it in the end.
If you have any issues with the instructions or need any help with a more complicated setup use the comments or get in touch on twitter @peterjgrainger