Creating ageless Windows CLIs with Docker and Wine

A while ago I spent some hours writing a mockup for a legacy Windows CLI. This CLI was part of the overall system to be overhauled and we wanted a dead simple Docker-based test setup. On the other hand, we wanted a test setup as close to the production system as possible. The other day a friend of mine asked: Shouldn’t it be possible to run the CLI inside a Docker container with Wine?

Wine (originally an acronym for "Wine Is Not an Emulator") is a compatibility layer capable of running Windows applications on several POSIX-compliant operating systems, such as Linux, macOS, & BSD.

Apparently, we were not the first to try this approach:

We ran a few promising experiments with several ready-made Dockerfiles available on the web.

The Dockerfile

Back at the drawing table we more or less followed How to Install Wine on Ubuntu 18.04 LTS and came up with a rather simple Dockerfile one-liner of our own:

FROM ubuntu:18.10

ENV WINEDEBUG -all

RUN apt-get update && apt-get install -y --no-install-recommends wine wine64

Tip: To suppress the Wine debug messages consider setting the environment variable WINEDEBUG=-all

This valuable flag is discussed in Cannot disable fixme message or How to permanently disable WINE debugger

A first Wine Experiment

With the Dockerfile prepared let’s build the wine-experiment image…

$ docker build --rm -t wine-experiment .
…
Processing triggers for wine (3.0.3-2) ...
Removing intermediate container d808ffb68959
 ---> 76343a265984
Successfully built 76343a265984
Successfully tagged wine-experiment:latest

and do a test-run:

$ docker run --rm -it  wine-experiment wine64-stable ipconfig                                                                                                   
wine: created the configuration directory '/root/.wine'
Could not load wine-gecko. HTML rendering will be disabled.
Could not load wine-gecko. HTML rendering will be disabled.
wine: configuration in '/root/.wine' has been updated.
Ethernet adapter lo

    Connection-specific DNS suffix. . :
    IPv4 address. . . . . . . . . . . : 127.0.0.1
    Default gateway . . . . . . . . . :
…

Ethernet adapter eth0

    Connection-specific DNS suffix. . : home
    IPv4 address. . . . . . . . . . . : 172.17.0.3
    Default gateway . . . . . . . . . : 172.17.0.1    

Nice.

Running the Windows CLI inside Docker

We mount our Windows tool demo-app.exe and all its dependencies into the container with -v $PWD:/demo. Since the executable isn’t on the path we also change the working directory via the option -w /demo/bin.

$ docker run -v $PWD/wine:/root/.wine -v $PWD:/demo -w /demo/bin wine-experiment demo-app
      /`·.¸
     /¸...¸` ¸.·´  ¸   `·.¸.·´)
: © );      ¸  {
 `·.¸ `·  ¸.·´\`·¸)
     `\\´´.·´

Tip: To avoid the generation of the wine metadata in .wine we additionally mount the configuration directory via -v $PWD/wine:/root/.wine into the container.

Seems Wine can extend the life of Windows CLIs…


Thanks for the Fish goes to ASCII Art Archive


Photo by Nicole De Khors from Burst