I’ve had a love hate relationship with Docker over the years, I’ve really struggled to make it fit in to my development flow. Now I know it’s just me because I see plenty of folks using Docker for development but it just never clicked for me. There’s always been a disconnect.
Until I found DevContainers in VS Code. First up, let’s caveat this. What I’m going to talk about in this entire article is possible without going near VS Code, VS Code is the final piece in my jigsaw and hopefully by the end you’re going to understand why.
I’ve experimented my fair share with Docker using a Dockerfile in my projects and Docker Compose - I’ve just assumed I should be able to type
docker-compose up in my terminal and in a few minutes I’d have a working local version of my app complete with all it’s dependencies, seed data presented to me.
What if, instead of trying to setup the entire application with one command, what if you didn’t do any of that and just booted an environment where you can write and execute your code locally? Enter Dev Containers. Simply put, a development container is just for the project you are working on - whether it be Ruby, Node, Go etc etc - no more installing of whatever you need locally, have it all in the container and safely stored in source control. What’s even better is that VS Code detects your app has a devcontainer config and boots it up and then closes it down when your done for that particular project. This is SUPER handy when coming onto a project for the first time - I mean, seriously, who actually reads READMEs?
When your project is opened in the container the magic happens (I’m not intending to go through the ins and outs of it here). But, what you end up with is your local VS Code running with your application code, opening terminal inside VSCode opens a terminal to the container. Running your application inside the container, eg with
rails server runs your application within the container that is then accessible by your local browser. It’s almost entirely invisible that you’re running in a container - assuming Docker run’s fine on your computer of course!
Well there’s a few requirements as you’d expect:
- VS Code installed (obviously)
- Docker installed
- Remote Developer Extension installed in VS Code
Once you’ve got these satisfied, open up the app in VS Code and from the bottom left corner of the VS Code interface click the green >< icon and choose
Remote-Containers: Add Developement Container Configuration files, VS Code will then offer you a bunch of premade environments to pick what your project needs. For example, picking Ruby a further prompt lets you pick the version and if you need Node.js available. A
.devcontainer folder will be added to your project containing a
devcontainer.json and a
Dockerfile as well as VS Code now prompting you to open the app in the container.
And that’s it. If it all went well you’ll be sitting in VS Code and it will look just like it always does. Opening a terminal within VS Code dumps you into the container a prompt that looks just like it would locally and git commands in the terminal just work.
If it’s a Ruby app your next task is to run
bundle, remember this is a clean environment. Ah, but it’s not found. Nevermind, open up the
Dockerfile and you’ll see a commented out block for installing gems, add in the
gem install bundler. Save the file, from the >< icon, Rebuild container, wait, return to terminal - run
bundle and you’re done.
I said at the beginning I’d explain why it’s the last piece of the puzzle. Sure, this is entirely possible with
docker exec -it <container name> /bin/bash - but then I’d have to remember that command each and every time (or use an alias). I can’t simply just open a new terminal window and be in my app, I have to run the docker command. The implementation of DevContainers abstracts it all away from me. Not convinved? Ok - come back next time and I’ll try and persuede you some more - there’s plenty more goodness with Dev Containers!
In my next article I’ll explore adding dependencies and customizing the VS Code workspace.