Developing the Eventuate Common library on an M1/Arm MacBook
multi-architecture docker images dockerAfter enhancing the microservicesio/plantuml project to publish a multi-architecture Docker image for Intel and Arm, I moved on to the eventuate-common project. It’s a Gradle project that publishes some foundational Java libraries and some Eventuate-flavored Docker images for Zookeeper, MySQL, Postgres and SQL server. These libraries and images are used by the Eventuate examples including the Tram Customers and Orders example application I described in my first post on this topic.
This post describes my experiences developing Eventuate Common on my M1/Arm MacBook. Specifically, I describe how I was able to build a MySQL image and run the related tests. Later posts describe how I changed this project to build and publish multi-architecture images.
The other articles in this series are:
- Part 1 - My Apple M1 MacBook: lots of cores, memory and crashing containers
- Part 2 - Building multi-architecture Docker images for Intel and ARM
- Part 3 - Configuring a CircleCI-based pipeline to build multi-architecture Docker images
- Part 4 - Testing an Intel and Arm multi-architecture Docker image on CircleCI
- Part 5 - Configuring CircleCI to publish a multi-architecture Docker image
- Part 7 - Configuring CircleCI to build, test and publish multi-architecture images for Eventuate Common
- Part 8 - Building a multi-architecture Docker image for Apache Kafka
- Part 9 - Publishing multi-architecture base images for services
- Part 10 - Publishing a multi-architecture Docker image for the Eventuate CDC service
- Part 11 - The Eventuate Tram Customers and Orders example now runs on Arm/M1 MacBook!!
Gradle behaves differently!
After running git clone
on my M1 MacBook, I ran ./gradlew testClasses
.
As I described in this Twitter thread, I immediately encountered a Gradle issue that broke the build.
A plugin from the eventuate-plugins-gradle
project that ran a Git command failed to determine the current branch.
Surprisingly, the command’s current working directory was no longer a project directory.
Instead, it was some internal Gradle daemon directory.
This could very well be a bug in the plugin rather than a Gradle issue.
I fixed the problem by explicitly specifying the project.rootDir
: e.g. git -C ${project.rootDir} rev-parse --abbrev-ref HEAD
.
Later on while running the tests, I encountered another problem that was also related to the Gradle daemon.
Gradle appeared to not always pass environment variables from the shell to the Gradle daemon.
This behavior caused Docker containers to be incorrectly configured and/or tests to fail.
I eventually solved the problem by replacing environment variables with Gradle projects properties that are specified on the command: ./gradlew ... -P x=y
.
Not only did eliminating environment variables fix this problem, but it improved the Gradle build logic since Gradle could now track changes to the project properties.
Finding a MySQL image that runs on Arm
As I mentioned above, the Eventuate Common project builds various database images that contain the Eventuate schema.
I decided to first work on supporting MySQL on ARM.
The project builds MySql 5 and MySql 8 Docker image using the mysql:5.7.13
and mysql:8.0.22
base images.
These base images are Intel specific and so I needed to find multi-architecture replacements.
When I searched Docker Hub, I found the mysql/mysql-server
image.
The MySql 5 tags are still Intel-specific but the MySql 8 tags support both Arm and Intel.
I decided, therefore, to focus on enhancing the Eventuate Common to run MySQL 8 on Arm.
Building the Eventuate MySQL 8 image
The mysql/mysql-server:8.0.27-1.2.6-server
is generally a drop in replacement for mysql:8.0.22
.
The notable difference is that by default, root
access is limited to localhost
.
In Eventuate applications, other containers, such as the Eventuate CDC, need root access.
This behavior is overridden by the MYSQL_ROOT_HOST
environment variable but I didn’t want to add that setting to every Eventuate example.
Therefore, I changed Dockerfile-mysql8
to run an additional configuration script - 0.configure-root-user.sh
- that allowed root access from anywhere.
Building a Zookeeper image for Arm
This project also builds a Zookeeper image.
It used the Intel-specific java:openjdk-8u91-jdk
as the base image.
I changed the Dockerfile to use the multi-architecture amazoncorretto:17.0.1-al2
image.
Running the tests
Once I’d made these changes, I was able to run build-and-test-all-mysql8.sh
, which builds and starts the Zookeeper and MySQL 8 images and runs the tests.
I also updated my local copy of the Eventuate Tram Customers and Orders example application to use these images.
As expected, the MySQL and Zookeeper containers ran without a problem.
However, most of the containers images were either flakey or slow.
There’s still more work to do.
Viewing the changes
To see the changes I made to the project, take a look at this Github commit.
Next steps
The next post describes how I changed this project to build multi-architecture images.