Creating Python Docker Image For Windows Nano Server

Jung-Hyun Nam
Mar 11 · 6 min read
Image Credit: https://unsplash.com/photos/9-ohfp-Dicg

My company, DEVSISTERS, is an early adopter of Windows container and Windows Kubernetes in Korea and its gaming industries. Recently, our team operated a Windows stack-based game software closed beta for a limited time. (Related Link, Korean)

During the closed beta period, we often collected application dump files to debug and improve server applications. Initially, we wrote a script with PowerShell and FileSystemWatcher.

But as you know, FileSystemWatcher and PowerShell do not work correctly sometimes. Also, in the Windows environment, PowerShell would be the right choice, but most of our team members are not familiar.

Initially, a simple automation script wrote in Python. Currently, Python official images only packaged with Windows Server Core image, not the Nano Server image. This option makes containerized Python applications consume more memory and resources, which makes a quite overhead.

In most cases, people accept this limitation willingly because the Nano server has too limited features than traditional Windows Server SKU. If you try to run a Python application in Nano Server, you will soon face a very tough problem. These differences can make overwork and can waste your time.

But I decided to make a hard work because I want to optimize the Python workload in Windows container environment. So I used about two business days and worked done charmingly. :-)

The Dockerfile — Build Stage

I used a multi-staged build for minimizing output image size. I defined some environment variables and changed the default shell to PowerShell.

Then, download an embedded version of Python Windows release and extract the ZIP file. Also, I download the get_pip.py script file too. Before doing that, I modified SecurityProtocol property to allow communication with the GitHub URL.

I used an embedded version of Python because the official Win32 installer will not work in Nano Server. And this is the hard part.

Some complicated configurations applied in this stage. I’ll explain what’s going on here.

  • I create PIPVER.CMD file to pass the PYTHON_PIP_VERSION environment variable to Nano Server.
  • For reducing the hard-coded part, I looked up the Win32 resource table in the python executable file and made a postfix string. This postfix string continuously used to extract the compiled Python library archive file and removing the _PTH file.
  • Embedded Python does not honor the system path variable (PYTHONPATH) due to the _PTH file after version 3.7.x. Removing this file makes embedded Python works like traditional Python.
  • I extracted the archived pre-compiled Python library to Libs directory.
  • Finally, for latter use, I created the DLLs directory separately. This directory used by pip and virtualenv.

Phew! The hard part is over. Until now, in this build stage, I created a temporary directory and composed a Python installation directory manually.

The Dockerfile — Nano Server

Let’s dive into the Nano Server.

By default, Windows Container uses the ContainserUser account. For security reasons, even in a container, the user does not have all permissions. If you want to modify the registry and system settings in the Windows container, you should change your user account to ContainerAdministrator.

I defined the PYTHONPATH environment variable locally. Then I configured the PATH, PYTHONPATH environment variable to system-wide. Also, I set the PIP_CACHE_DIR environment variable for hiding the PIP cache directory from the container root path.

The last line configures the long-path support for Windows operating system.

In the case of the AWS CLI, it requires “.PY” file extension should be associated with a Python interpreter directly. These commands make mappings between major Python file extensions and Python interpreter, respectively.

The remaining parts are relatively simple. Simply call the get-pip script with — disable-pip-version-check, — no-cache-dir, and specify the PIP version. After the PIP installation completed, remove temporary files and verifying Python and PIP works correctly.

In the official Python Windows Server Core image, it adds the virtualenv package for convenience. So I simply added it to provide virtualenv tool in the Nano Server container.

Then, changing the user to ContainerUser again. This configuration makes the container more secure.

Finally, I specify the default command of this image as a Python interpreter.

Test Flight — AWS CLI & Virtual Environment

First, I tested the installation of AWS CLI.

Then, I tested the installation of Django in a virtual environment.

It looks like work correctly.

Test Flight — Django Web Application

Lastly, I created a simple Django sample web site with the Nano Server. I wrote a simple Dockerfile to achieve this.

First, I create a new Django project.

Then, I modified the settings.py file to allow all hosts. In this case, I’m not using any reverse proxy server, so I need to adjust the security setting that would enable incoming connection to Windows container.

Lastly, I create a Dockerfile to build a docker image.

Let’s start the Nano server-based Django application!

Voila! After launching the container, I can browse the Django app.

From now on, you can run your ordinary Python application in the Nano Server container. It makes your Windows-based Python application much slimmer and works fast.

Do you want to use the image?

I published a public Git repository and Docker Hub repository. You can clone the code or pull the image immediately.

And as always, All kinds of contributions are welcome!

Beyond the Windows

DevOps Engineer’s Blog

Jung-Hyun Nam

Written by

DevOps Engineer @ DEVSISTERS, Corp., Microsoft MVP since 2009, Living in S.Korea.

Beyond the Windows

DevOps Engineer’s Blog

More From Medium

More on Docker from Beyond the Windows

More on DevOps from Beyond the Windows

More on DevOps from Beyond the Windows

Choosing Your Base Image in Windows Container

More on Python from Beyond the Windows

More on Python from Beyond the Windows

Running Django Applications in iPad

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade