I’m starting to move myself off of Apple products. The reasons why deserve an entirely different blog post, so I won’t go into it here, but that meant trying to move my development environment off of macOS. And while most languages and frameworks play nice on Windows, web development is a completely different animal.

For context, one of the systems that our team uses at Team Bliss is developed mostly by me. The project handles build artifact distribution and access control and is written with Django, wrapped up in a nice little Docker image to deploy.

So this blog post will go into Docker on Windows, WSL2, and my overall experience with web development on Windows!

Mistakes were made - Docker

When I first tried to use Docker on Windows, everything went to hell because I didn’t realize the ramifications of using Linux-based images directly on Windows.

Most of the images that worked on macOS and Linux machines immediately crashed on Windows. Trying to debug the problem was a nightmare - there were a lot of syscalls and low-level stuff that I didn’t understand - and also very time-consuming. I still don’t know exactly what went wrong, but if I had to guess, Windows and Linux treat permissions and files differently and the container was crashing because the entrypoint scripts were mangled by Windows before ingestion.

So for a while I returned to the environment set up on macOS, until I could take another shot at it.

Attempt 2 - WSL with Docker

My second attempt was a bit better, but not entirely.

This time, I changed tack and decided to try and run Docker with WSL integration. The plan was to get the project cloned to a WSL distro, and then use the Docker integration to “launch” the container inside the WSL container - which would make the Docker executable on Windows spin up another container to house the Docker program. (It’s containers all the way down!)

And it worked! I was able to launch the image inside WSL and navigate to it by pointing my browser at localhost. Everything worked out of the box.

I happily fired up PyCharm to make some small tweaks and pointed it at the remote share of WSL - and that’s where things started to fall apart. PyCharm threw up its hands and called it a day. It seems like PyCharm doesn’t support WSL, or at least didn’t support WSL when I tested it. Even though I could make changes, PyCharm warned me about permission problems and what not.

And when I tried to commit my changes using GitKraken, it too complained about permissions problems. I gave up on trying to modify the state of my project from Windows and returned to WSL, but the Windows programs had completely broken the project git state, as git refused to commit my changes and threw up an error about permissions as well.

And that’s how attempt 2 went down the toilet. Back to virtual machines and macOS I go!

WSL2, Docker, and VS Code

After a while, I decided it was time for a last attempt. This had to work, or else my next laptop was going to be from an Apple Store.

I first enabled the WSL feature, installed the WSL2 kernel extension, installed a WSL2 distro (Debian), and then installed Docker for Windows, making sure to enable the WSL2 integration during installation. (You don’t really have to - if you forget, it’s a simple settings toggle away.) Then, inside the Debian container, I cloned the project, and ran docker-compose up -d to start up a container.

It worked beautifully. Just like attempt 2, the container spun up in Docker for Windows and I was able to access it with zero problems.

To edit the code, I decided to use Visual Studio Code instead. After I installed VS Code, I installed the “Remote - WSL” plugin, and then inside the Debian container, ran code . inside the project directory to launch the VS Code integration.

And that’s what I’ve been using for the last couple of days to develop the project. Any changes I make in VS Code are reflected instantaneously on the local server running on Docker for Windows, without any permissions problems that I encountered in the past. The only bummer is that I can’t use the excellent GitKraken tool, but a simple workaround is to use git add -p <file> and just stage chunks of my code, which works just as well.

I’m really impressed by the integration work done by Microsoft, the VS Code team, and Docker. Transitioning from the WSL2 container to VS Code and Docker is really seamless with a quick code . or docker-compose command. And the performance isn’t too shabby. If I had to nitpick, I guess the network stack is a bit slower, because communication between my browser and the server running inside Docker is slower than my setup back on macOS, but it’s still really snappy and performant regardless.

Of course, most of my troubles came from Docker, since that’s what the project is packaged with. Had I used a traditional direct-installation approach, I would’ve been able to develop directly on Windows with Python. But I still think using Docker is worth it because it makes deployments really easier.

Conclusion

WSL2 really makes it easy to develop on tools that were originally meant for UNIX systems. While it can still use some polish here and there, I think it bridges the gap and plugs most of the potholes that developers might run into. Most importantly, it’s enough that I’m ready to fully transition to Windows machines for developing software.

So if you’re like me and you want to get off of macOS for development, Windows with WSL2 is not a bad choice! Give it a try and see if it works for you.