ARM is not a new processor architecture. Virtually every smartphone today has one inside and has since the earliest days of iOS and Android. In fact, ARM goes all the way back to 1983, when transgender woman Sophie Wilson began designing the instruction set for the Acorn RISC Machine. Despite its long history, however, it’s never been considered a serious contender for workstations or desktop machines where x86 reigns supreme. Even in the data center, ARM is a comparative newcomer, with few cloud providers supporting it.

The Raspberry Pi did a lot to popularize the notion of ARM as a desktop replacement. For years, the Pi and other Single Board Computers have been slowly normalizing the ARM architecture on Linux. Now, it’s common for many popular distributions to offer both x86 and ARM versions. A key advantage of ARM is its low power consumption compared to the performance it provides. While Intel has made great strides there in the last decade, ARM still easily beats them in MHz per Watt.

That advantage was what led Microsoft (you thought I’d say Apple, didn’t you?) to release one of the first well-advertised “desktop” systems running ARM, the SurfaceRT, in 2012. Unfortunately, the launch was compromised by slow performance, lack of compatible applications and the entire Windows 8 mess. It was simply too early. It wouldn’t be until 2016, when the Pi 3 was released, that ARM on Desktop was reconsidered.

And Then the M1 Was Announced

After years of speculation and multiple iterations of their own custom ARM processor, Apple confirmed that the next MacBook would run ARM. MacOS developers and open source maintainers have been working to port their software ever since. A brief scandal erupted when it was discovered the dev kit lacked any support for hardware virtualization, meaning Docker, VMWare, Virtualbox, Parallels, and any hardware-accelerated virtualization system was non-functional. This was a potential disaster, as many developers rely on VMs or containers to run their software locally while retaining the user environment of MacOS. To Apple’s credit, they worked closely with developers and rectified the situation.

It was around this point that developers at TEN7 started asking me, “If I got an M1, would all our stuff work?” I had to break some hearts.

Not only did I live through the ugly PowerPC to Intel transition for OS X, I also lived through the nearly forgotten 68k to PowerPC transition.

“Likely not for two years,” was my reply, “and besides, none of our containers work on ARM.” Our developers rely on Flight Deck, a series of Linux containers we use both for development, and in our open source production hosting running on Kubernetes.

“So how hard would it be to get Flight Deck running on ARM?” they asked. I flatly didn’t know. I knew that Alpine Linux -- on which Flight Deck is based -- supports multiple architectures including ARM. In theory, we’d only need an ARM system on which to compile the images and push them up to Docker Hub. There was no way we’d be able to get an M1 or Apple’s Dev Kit just to compile Flight Deck.

Fortunately, Apple isn’t the only option here.

Getting Docker Installed

The most powerful ARM based system I have capable of running Docker is a Raspberry Pi 4 4GB. Presently, it’s been shoehorned into the modified case of an eMate 300, a laptop-shaped Newton intended for use in the education market. My “piMate 300” also features a mechanical keyboard and a 7” color touchscreen. A bit of a step up from the eMate.

screenshot Installing Docker

Installing Docker was a little more complicated on Raspbian than most Linux distributions. Instead of simply apt-get install docker-io, you need to add a special repository to the Raspbian package manager and then install Docker. Fortunately, Docker made this simple by providing a script which performs most of the necessary setup.

First, run updates on your system to ensure you have the newest packages installed:

sudo apt-get update

sudo apt-get upgrade

Then download and run the script:

curl -fsSL https://get.docker.com -o get-docker.sh

sudo sh get-docker.sh

When that completes, you’ll have Docker installed, but there’s a bit more set up yet to do. Docker runs as the root user. To have access to Docker commands while running as non-root, you need to add your user to the docker group.

Use the following command to get your username

whoami

Then, add yourself docker group:

sudo usermod -aG docker yourUserName

I also decided to configure Docker to start when the system starts up:

sudo systemctl enable docker

And then manually started Docker. You can choose to simply reboot the Pi at this point if you prefer:

sudo systemctl start docker

Finally, we can validate everything is working with:

docker info

Compiling Flight Deck

With Docker installed and running, the next step is to try to compile Flight Deck. Fortunately, all of Flight Deck’s code is free and open source on Github. You can choose to either use git to clone the repositories, or simply download a zip of the latest release of the source. Either works.

After getting the code, building Flight Deck is straightforward. There are no additional tools, scripts, or build systems necessary other than the docker command.

Change to the directory containing the Dockerfile. In my case, I created a flight-deck directory in my home directory, then downloaded and extracted the 7.3.x zip of flight-deck-web:

cd ~/flight-deck-7.3.x/flight-deck-web/7.3

Then, build the container:

docker build.

screenshot Compiling Flight Deck

To my astonishment, it compiled successfully the first time with no modifications. In retrospect, this made perfect sense. The base Docker image we’re using is in fact a “multi-arch” container. That is, it supports multiple processor architectures using the same name. The Docker engine is aware which CPU I’m using, so it downloaded and built the container for ARM without further prompting. Alpine Linux itself has been supporting ARM for years at this point, and Flight Deck is largely built on packages provided by Alpine. The minimalist approach in Flight Deck also helps us here.

The docker build command returns a hexadecimal image ID. We can run that using the docker run command:

docker run -it 1234567890abcdef /bin/bash

And after a short start up script, we’re greeted by “Muffy”:

screenshot Muffy

With that working, we could use Composer to download Drupal core:

composer create-project drupal/recommended-project path/to/target/dir

screenshot Composer download Drupal core

That too, worked perfectly, validating that PHP was alive and functioning on ARM.

One Down, Several to Go

The flight-deck-web container is only one of several containers necessary to run a Drupal site. We also need flight-deck-db to provide a database. For a production environment, we also need flight-deck-varnish, the official memcache image, and, optionally, flight-deck-solr. I downloaded all of these, and each one compiled and ran as expected on ARM with one exception.

Our Solr 6 image worked perfectly well, but Solr 8 failed to compile on ARM. When I dug into the build logs, I found that the problem was a missing dependency. Our Solr 6 image relies on OpenJDK 8, as per Solr’s own recommended system requirements. Solr 8, however, relies on the newer OpenJDK 11, which is not available on Alpine ARM at this time.

Getting a Site Running

With all the critical containers working, the next task was to stand up a site. Flight Deck relies on Docker Compose -- not to be confused with Composer -- which is a separate project from Docker itself. Compose relies on Python, so we can install it using the Python package manager, Pip:

sudo apt-get install libffi-dev libssl-dev

sudo apt install python3-dev

sudo apt-get install -y python3 python3-pip

sudo pip3 install docker-compose

Future versions of Flight Deck may supply a docker stack file instead of a Compose file. The format and features are similar, and it would remove the need to install Docker Compose at all.

Next, I can clone the ten7.com git repository from our internal Gitlab instance. I also needed a database dump. This last part was a bit hilarious. To get one, I needed to log in to various internal systems. To do that, I needed to log in to my password manager. To do that, I needed to use my hardware security key, which required half-tearing apart the piMate to awkwardly insert it into a free USB port. I’m sure the experience would be markedly more mundane on Apple’s consumer hardware.

Before starting up the containers, I needed to modify the docker-compose.yml to point to my local Flight Deck build files, rather than those on Docker Hub. This involved changing the image directives to build directives and supplying a local file path.

screenshot build directives

After that, two commands was all that was necessary:

docker-compose build

docker-compose up -d

That’s When the Problems Started

The first sign of trouble was that all of the containers downloaded, but some mysteriously failed to start. A quick check with docker-compose logs showed why:

screenshot docker compose logs

The “exec format error” message was Linux’s way of telling me that those containers were not multi-arch, and thus couldn’t run on ARM. The loss of the official phpMyAdmin and Mailhog images was unfortunate for local development, but not a show-stopper.

Loading the database went perfectly well. After running composer install and drush cr, the site was up!

screenshot composer install drush cr

Kinda! Like many sites, ten7.com relies on SASS to preprocess CSS. I had failed to do that step. Fortunately, npm and node-sass (should) be installed inside of flight-deck-web, so it should only be a matter of running:

npm install

npm run build

And there’s where things really went off the rails.

screenshot no official ARM support

While it may be possible to compile Node Sass to run on ARM, it isn’t officially supported. In fact, at the time of this writing, no official ARM support is available according to the 5.0.0 release.

It’s not all bad, however. There is a general tracking issue to finally, officially support ARM, due to Apple announcing the M1. Supporting only Apple’s version of ARM, unfortunately, would leave containerized development tools lacking, as the vast majority continue to run Linux. MacOS is little used for web development automated build systems or production web servers, where Linux is nearly universal. We could go back to the bad old days of committing compiled CSS code to git repositories, and bring back all the git conflicts that brings with it. I can only hope that the Node Sass team will broadly support ARM and not just Apple’s interpretation of it.

Where to Go From Here

While Flight Deck largely runs on ARM, it’s not quite ready yet for regular development. The lack of Node Sass is a major sticking point, and it would require some effort to compile all the needed utilities locally and apply whatever patches are necessary in order to support the architecture.

Furthermore, it would be best for Flight Deck to support multi-arch images itself. This can be done on an x86 based system through the use of QEMU and the docker buildx command. This would allow Flight Deck to support different architectures transparently, as does the Alpine base image and the official Memcache image.

Conclusion

ARM on desktop is, in many ways, already here. It simply wasn’t taken seriously until Cupertino gave its blessing. Fortunately, the open source community has long since been here, working to keep our tools running as technology changes. We at TEN7 hope Flight Deck will be a part of that.

screenshot Flight Deck on ARM Conclusion