Use Docker container to build windows installers for electron apps on macOS

The Purpose

The purpose of this article is to fix System.Exception at Squirrel.Utility.CreateZipFromDirectory and outline the benefits of using Docker when building Windows installers for Electron-powered applications. It is specifically for those who use any of the macOS versions above Majove.

I recommend this approach for production builds as well, for Windows and Linux platforms. Why for production? Because with Docker, it will be straightforward to set up, build/test/ship job on CI/CD tools like Jenkins, GoCD, AWS Code Build, etc…

The Reason

I was using my MacBook for building windows installers for almost 2 years now. It was running os version Majove, but recently I upgraded to Big Sur. Mac OS is great. I love it, but sometimes you can’t do much with it, especially when it comes to heavy workloads, such as electron app builds.

Mojave was the last version of macOS to run 32-bit apps. Starting with Catalina, 32-bit apps are no longer compatible with macOS. This is a problem for legacy applications, but Apple announced this change in 2018, giving developers time to refactor their applications.

In my case, the problem occurred when I tried to build a windows installer for the electron application on macOS BigSur.

The Problem

As you may probably know, to build windows installers on macOS, you will need the following packages installed globally:

  1. Wine - compatibility layer capable of running Windows applications
  2. Mono - Cross-platform, open-source .NET framework

Besides this, you’ll also need some NPM packages for building windows installers.

There is a large variety in Github:

  1. electron-builder — https://github.com/electron-userland/electron-builder
  2. windows-installer — https://github.com/electron/windows-installer
  3. electron-installer-windows — https://www.npmjs.com/package/electron-installer-windows
  4. electron-packager https://github.com/electron/electron-packager

I was using an electron-packager with electron-installer-windows to package and build the windows app.

Here are my npm scripts:

This will go ahead and run 2 more scripts:

The first command will configure some stuff and run an electron-packager to generate a package in the build folder, which electron-installer-windows will later use to build the actual .exe file.

The second command uses an electron-installer-windows to build the installer.

This second command failed on my MacBook running macOS Big Sur with the following exception.

After many research hours, I found out that 7zip in electron-windows-installer is shipped in 64-bit, and obviously, my macOS can not run that. There is a workaround to download 7Zip 32-bit, install it and replace .exe and dll in the vendor folder and run again, but this makes the build process hard to maintain, so I thought of a workaround process less expensive to maintain.

The Solution

This is definitely not a solution but a workaround for 7zip and all other 32-bit apps used by electron packages. A Docker image will have all dependencies preinstalled to spin up a container every time I want to build a windows version. Let’s describe the environment at a high level.

Here are the high-level steps:

  1. Take the latest image of Ubuntu as a base image.
  2. Install required packages like wget, gnupg2 software-properties-common, etc...
  3. Install node and npm (preferable using as others may need to use different node versions)
  4. Install wine and mono

Here is the complete Dockerfile

Usage

Pull the docker image from the docker hub. It is available publically.

In your terminal, navigate to the project root directory, remove node_modules and package-lock.json, to avoid node version conflicts inside the container.

This will spin up a container and map the current folder with the /project path in the container. Once in, type npm install to install the package and your build command. In my case, it will be

This will go ahead and build the package and the installer. You’ll then need to type exit to exit and destroy the container. Note that I left nvm inside in case you need a different node version. I am using 11 currently. That’s why it will be the default version of the node when you enter the container.

Conclusion

Nonetheless, I would never recommend building installers locally. I would rather use build tools like AWS code build, Jenkins, or any other CI/CD to build for production.

This is a quick workaround that will help to speed up local tests. I hope this will be helpful for someone.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store