Deployment Testing of EMQX on NXP iMX8MP ARM Platform

Introduction

EMQX is an open-source MQTT message server developed on the Erlang/OTP platform, widely used in the Internet of Things (IoT) field for message transmission and control between devices and servers. This document is based on the NXP i.MX8M Plus ARM processor platform, deploying and testing EMQX by integrating a Docker environment into the Yocto Linux BSP.

The platform demonstrated in this article is from the Toradex Verdin i.MX8MP embedded platform.

Preparation

The Verdin i.MX8MP ARM core version is paired with the Dahlia carrier board and connected to a debug serial port for testing.

Verdin i.MX8MP Yocto Linux Compilation and Deployment

First, refer to the instructions here to create the Yocto/Openembedded compilation framework. The current latest version corresponds to the Toradex Yocto Linux BSP 7.x version of the scarthgap-7.x.y branch.

Add the meta-virtualization layer that includes Docker support.

### add meta-virtualization ###
$ cd <OE_ROOT_PATH>/layers
$ git clone -b scarthgap git://git.yoctoproject.org/meta-virtualization

### add meta-clang layer for PySide6 ###
$ git clone -b kirkstone https://github.com/kraj/meta-clang.git

Create a customized layer meta-customer-demos to add additional modifications and configurations required for Docker. First, add the layer configuration file.

$ mkdir -p ../oe_core/layers/meta-customer-demos/conf
$ cd .../oe_core/layers/meta-customer-demos/conf
### create layer.conf file ###
# We have a conf and classes directory, append to BBPATH
BBPATH .= ":${LAYERDIR}"

# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"

BBFILE_COLLECTIONS += "customer-demos"
BBFILE_PATTERN_customer-demos = "^${LAYERDIR}/"
BBFILE_PRIORITY_customer-demos = "24"

# Let us add layer-specific bbappends which are only applied when that
# layer is included in our configuration
BBFILES += "${@' '.join('${LAYERDIR}/%s/recipes*/*/*.bbappend' % layer \
               for layer in BBFILE_COLLECTIONS.split())}"
# Add layer-specific bb files too
BBFILES += "${@' '.join('${LAYERDIR}/%s/recipes*/*/*.bb' % layer \
               for layer in BBFILE_COLLECTIONS.split())}"

LAYERDEPENDS_customer-demos = " \
    core \
    yocto \
    openembedded-layer gnome-layer multimedia-layer networking-layer \
"
LAYERSERIES_COMPAT_customer-demos = "hardknott honister kirkstone scarthgap"

Add a Docker bbappend file under the customized layer meta-customer-demos to configure Docker to start automatically.

$ cd .../oe_core/layers/meta-customer-demos/
$ mkdir -p recipes-containers/docker
$ cd recipes-containers/docker
### create docker-moby_git.bbappend file ###
FILES:${PN} += "${sysconfdir}/systemd/system/docker.service"

SYSTEMD_SERVICE:${PN} = "docker.service"
SYSTEMD_AUTO_ENABLE:${PN} = "enable"

The Docker daemon requires additional network-related Kernel Modules such as IPSec/Netfilter/NF_table, so the following additional Linux Kernel configurations are needed.

$ cd .../oe_core/layers/meta-customer-demos/
$ mkdir -p recipes-kernel/linux/
$ cd recipes-kernel/linux
### create linux-toradex%.bbappend file ###
SRCREV_meta-custom = "1e293f75e7e5569f0d86d752fbf4180dd3fac6eb"
SRCREV_meta-custom:use-head-next = "${AUTOREV}"

KMETABRANCH = "scarthgap-7.x.y"
KMETAVIRTUALITION = "kernel-meta-custom"

KMETAREPOSITORY="github.com/toradex/toradex-kernel-cache.git"
KMETAPROTOCOL="https"

SRC_URI += "git://${KMETAREPOSITORY};protocol=${KMETAPROTOCOL};type=kmeta;name=meta-custom;branch=${KMETABRANCH};destsuffix=${KMETAVIRTUALITION}"

## Compose additional .scc file including docker requirement and include it to our build.
KERNEL_FEATURES += "bsp/${MACHINE}-${LINUX_KERNEL_TYPE}-torizon.scc"

The final complete file structure of the meta-customer-demos layer is as follows:

meta-customer-demos
├── conf
│   └── layer.conf
├── recipes-containers
│   └── docker
│       └── docker-moby_git.bbappend
└── recipes-kernel
    └── linux
        └── linux-toradex%.bbappend

Modify the bblayers.conf and local.conf files.

### modify bblayer.conf ###
--- a/build/conf/bblayers.conf  
+++ b/build/conf/bblayers.conf  
@@ -34,7 +34,7 @@
   ${TOPDIR}/../layers/meta-openembedded/meta-python \
   ${TOPDIR}/../layers/meta-freescale-distro \
   ${TOPDIR}/../layers/meta-toradex-demos \
+  ${TOPDIR}/../layers/meta-virtualization \
+  ${TOPDIR}/../layers/meta-customer-demos \
   \
   \
   ${TOPDIR}/../layers/meta-toradex-distro \

### add below to local.conf ###
# enable meta-virtualization
DISTRO_FEATURES:append = " virtualization"

# enable docker support
IMAGE_INSTALL:append = " docker docker-compose"

# add Freescale EULA
ACCEPT_FSL_EULA = "1"

Compile the Yocto Linux image.

### compile Reference-Multimedia image ###
$ MACHINE="verdin-imx8mp" bitbake tdx-reference-multimedia-image

Deployment of the Yocto Linux image.

Refer to the instructions here to update and deploy the compiled image to the module using the Toradex Easy Installer.

EMQX Deployment Testing

For more information and introduction about EMQX, please refer to the following link:https://docs.emqx.com/en/emqx/latest/getting-started/getting-started.html

On the Verdin i.MX8MP device, confirm that the Docker daemon is successfully running with the following command:

root@verdin-imx8mp-06849028:~# systemctl is-enabled docker.service
enabled
root@verdin-imx8mp-06849028:~# systemctl status docker.service                                
* docker.service - Docker Application Container Engine
     Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; preset: enabled)
     Active: active (running) since Fri 2025-03-28 01:54:37 UTC; 5h 16min ago
TriggeredBy: * docker.socket
       Docs: https://docs.docker.com
   Main PID: 685 (dockerd)
      Tasks: 19
     Memory: 99.6M (peak: 146.5M)
        CPU: 14.376s
     CGroup: /system.slice/docker.service
             `-685 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

...
Mar 28 01:54:37 verdin-imx8mp-06849028 dockerd[685]: time="2025-03-28T01:54:37.583078000Z" level=info msg="Daemon has completed initialization"
Mar 28 01:54:37 verdin-imx8mp-06849028 dockerd[685]: time="2025-03-28T01:54:37.684308375Z" level=info msg="API listen on /run/docker.sock"
Mar 28 01:54:37 verdin-imx8mp-06849028 systemd[1]: Started Docker Application Container Engine.

Refer to the instructions here to install and run the EMQX ARM64 Docker Image using the following commands. This article adopts the offline method; if network conditions permit, the online method can also be used.

### download
$ wget https://www.emqx.com/en/downloads/broker/5.8.6/emqx-5.8.6-docker-arm64.tar.gz
### install
$ docker load < emqx-5.8.6-docker-arm64.tar.gz
###
$ docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx:5.8.6

At this point, on the development host, you can view the running EMQX console page through the browser at the following URL. The default login information is admin/public, which can be changed later.

http://<verdin_imx8mp_ip_address>:18083/

Deployment Testing of EMQX on NXP iMX8MP ARM PlatformDeployment Testing of EMQX on NXP iMX8MP ARM PlatformDeployment Testing of EMQX on NXP iMX8MP ARM PlatformAfter entering the client, first connect to the Verdin i.MX8MP core node device.Deployment Testing of EMQX on NXP iMX8MP ARM PlatformThen subscribe to the default topic “testtopic”.Deployment Testing of EMQX on NXP iMX8MP ARM PlatformFinally, after modifying the payload content, click publish, and you can see that the core node can receive data normally.Deployment Testing of EMQX on NXP iMX8MP ARM Platform

Conclusion

This article demonstrates the deployment and operation of the EMQX MQTT message server in a Docker environment based on the NXP i.MX8MP processor.

Leave a Comment