Notes about a Windows Dev Environment with Docker
Apart from running a couple of scripts on Powershell and a bit of Python code, I haven’t gotten that deep into actual coding (creating an application, source control etc.). But little by little, I’ve started picking up developing applications using Python, PHP and Javascript.
In this post, I’ll explain the tools I use and some observations made using them.
TL;DR You can go to this top notch guide from Nick Janetakis to get yours up and running.
Terminal and IDE
- WSL Ubuntu (Windows Subsystem Linux - Ubuntu)
- Visual Studio Code
Even though work required me to use primarily Windows (and Powershell), I’ve always found the Linux terminal to be more easy (chaining commands, multiple windows/panes with tmux, vim 😁). Now, let’s not argue about which is better; I like both Linux terminal and Powershell. But when I started out, it was command-prompt vs. Linux terminal. What can you say? First impressions of Bash were that much better and it kind of carried over till now.
Enter Docker
This setup was all good for a while, until I had to start installing various versions of the runtime binaries. For example some projects needed to run on PHP 5, while newer ones need PHP 7. Python 2.7 is phasing out to Python 3, along with the pip tool and packages. This lead to juggling with various configurations for each type of project. It felt like a cluttered up box of stuff, with so many packages installed and having to deal with the occasional conflict of having multiple versions of the same package.
I needed a way to isolate each project to it’s own environment and runtime binaries etc. This is a problem which Docker has seemed to solved using containers and it’s working well for a lot of people.
Basically a container runs an isolated environment (sort of like a VM, but without the OS overhead) with your choice of OS, packages, configuration and files. To start your project dev environment, just use docker run <arguments>
. So easy, right?
Running Docker with Docker Desktop
As the Docker engine is built on Linux kernel features, it can’t run natively on Windows. There are couple of ways to run Docker on Windows but I went with the Docker Desktop route which was very straightforward.
The Docker team has done a great job to simplify the setup and get you started almost immediately.
FYI, in the new implementation, Docker uses Hyper-V virtualization and runs a small VM with the Docker engine daemon on it.
Also the use of docker-compose
is such a time saver. You can define all the services and configuration that’s needed for your application and just have it running with simple docker-compose up
. Docker Compose will start up all the necessary containers as defined in your configuration file.
WSL Tweaks
Couple of tweaks were needed to make WSL work with Docker. First is connecting to the Docker daemon running on the VM remotely from WSL. The option needs to be enabled on Docker Desktop settings and specific environment variable set in the terminal.
In WSL:
echo export DOCKER_HOST=tcp://localhost:2375 >> ~/.bashrc
# Verify that everything works with
docker info
Volume Mounts from Host to Container
Volume mount is the feature where the project folder on your local filesystem (ie: Windows) is enabled to be accessible to the container. With this we edit the code locally on Windows, while making it accessible to the container environment and see the changes we make in realtime. For example, you could have the Python environment already setup in the container and edit the code for a Flask application
We can just pass the parameter -v <host directory>:<container directory>
to the docker container run` command, and now the project files are available to the container.
Couple of things you need to be aware of is how you specify the <host directory>
in WSL. By default, local files are accessible in /mnt/<drive>/<folder>
. This needs to be changed so that your drives are referred from /
root and that would match to what the Docker daemon sees on the local filesystem. For example this would mean you can use the -v
parameter and have the <host directory>
as /c/project/src
, or more easily -v $PWD:<container directory>
. $PWD
is a environment variable that always outputs the current directory you’re in.
docker container run -d --rm --name app -v $PWD:/app -p 5000:5000 app-image
Conclusion
I’ve really enjoyed doing development work with this setup. WSL has gotten really good to the point I’m using that more, compared to Powershell. I’m also learning to improve the workflow using VSCode extensions. Maybe I’ll share my experience with those once I get enough time with it.
Docker has really changed the way I think of setting up environments. Earlier it would be either commands typed out by hand or simple bash scripts. In contrast, having the ability to define your configuration in a file and just run a few commands to get it up and running is remarkable and saves a huge amount of time.
If there are any other tools I should check out, let me know on Twitter.