./ahmedhashim

Develop Where You Deploy

I once spent a day debugging why a python import wasn’t working in production. The code ran without issues on Ubuntu during development but crashed consistently when deployed to Alpine Linux servers.

It came down to libc. I was developing on a glibc system but deploying with musl-based Docker images.

When you install a python package on Ubuntu, you get wheels compiled against glibc. Those same wheels fail on Alpine Linux because musl handles dynamic linking differently.

The differences go beyond binary compatibility. DNS resolution behaves differently between the two. Applications that resolved hostnames fine during development can start timing out in production because musl’s resolver has different fallback behavior.

Memory management and threading also differ, along with subtler things like character encoding. The bugs that come out of these differences can result in a few gray hairs.

The fix is to use the same OS and runtime versions from development through production. If you’re deploying to Alpine Linux, develop on Alpine Linux. If production runs Python 3.9.2, don’t develop on 3.9.7 because it’s slightly newer.

I don’t expect developers to abandon their Mac workflows, but Docker makes testing against a production image trivial. A quick docker run before deployment can save hours of production debugging.