I recently worked on a team that created web app with a React front-end. It connects to an API running Flask and Python. The data is stored in SQL Server. Our micro-services architecture application is two docker containers running on Azure App Services with SQL in an Azure VM.
Initially, the application was configured to connect to the database with PYMSSQL. New functionality required a database connection using PYODBC. I suspected this might help with performance too. But the application randomly wouldn’t connect with PYODBC.
After much testing, we thought it was a specific instance of SQL Server. Further testing by the team determined it was machine/container dependent. That allowed us to test lots of options and found that it would only work with specific version of Alpine, Python and PYODBC.
We generated and ran 114 different Docker files containing alpine and python versions ranging from 3.7 to 3.10. We tested many patch version numbers for two things: 1.) Can the container build? 2.) Can the container connect to the database and pull data?
The results were surprising:
- Anything using pymssql==2.2.7 failed.
- Later patch versions tend to fail (so 3.9.2 will work but 3.9.13 does not).
- if it failed to build, it’s because it couldn’t find libraries.
In the end, we discovered that if we don’t request a very specific version of Alpine (ie 3.9.13) it will default to the latest; often this is 15 or more. When building the libraries, to get right version, the PYLIST uses the hex representation of Python versions. The hex value 030B000A2, only goes to version 12. Anything over 12, fails.
The point of this article is that we must be very careful with packages and versions. This can seriously affect performance, reliability, or compatibility. This is especially true with open-source systems that are dependent on multiple developers. Be careful about your versions and manage them throughout the application lifecycle.