Building a QNX Container application image

In this section, you build a container application image.

Building a container application image starts with building a regular QNX application using the conventions and tools defined in Conventions for Recursive Makefiles and Directories of the QNX OS Programmer's Guide And then running the make command.

The following discussion assumes a simple application, named hello-container, which prints the message Hello from a QNX container! to stdout once a second.
Note:
Usage of the printfs command in your application doesn't show up immediately in the container logs due to buffering. There are ways to turn this off. In your C applications, for example, you can call setbuf() or fflush().
To convert the QNX application into a QNX Container application image, you need to complete the following steps:
  1. Define a new Makefile, container.mk, at the same level as the common.mk, which contains the container build commands that gets appended to the install step.
  2. Define a new Dockerfile with the specifics of the container image to include files, environment variables, and the container process to launch.
  3. Run the make install command which uses the two new files to generate a local QNX Container application image.
The following example shows a sample container.mk for hello-container application binary:
ifndef __NTO_VERSION
__NTO_VERSION=800
endif

CONTAINER_NAME = hello-container

INSTALLDIR := $(CONTAINER_NAME)/$(INSTALLDIR)

IMAGE_VER = v0
IMAGE_TAG = $(CONTAINER_NAME)-$(CPU)-qnx$(__NTO_VERSION):$(IMAGE_VER)

DOCKER_FILE = $(PROJECT_ROOT)/Dockerfile
DOCKER_IGNORE_FILE = $(PROJECT_ROOT)/.dockerignore

CONTAINER_INSTALL_DIR = $(INSTALL_ROOT_$(BUILD_TYPE))/$(CONTAINER_NAME)

define CONTAINER_CREATE
	@$(CP_HOST) $(DOCKER_FILE) $(CONTAINER_INSTALL_DIR)
	@$(CP_HOST) $(DOCKER_IGNORE_FILE) $(CONTAINER_INSTALL_DIR)
	docker build -t $(IMAGE_TAG) $(CONTAINER_INSTALL_DIR) --build-arg="ARCH=$(CPU)" --build-arg="NTO_VER=$(__NTO_VERSION)" --platform=linux/$(CPU)
endef

POST_INSTALL = $(CONTAINER_CREATE)

define CONTAINER_DELETE
	$(RM_HOST) -rf $(CONTAINER_INSTALL_DIR)
	docker image rm -f $(IMAGE_TAG)
endef

POST_UNINSTALL = $(CONTAINER_DELETE)
This file instructs the QNX OS makefile system to do the following steps on a make install:
  1. Install the build artifacts under the path, target/qnx8/nto/[arch]/<container_name>/usr/..., rather than the default path, target/qnx8/nto/[arch]/usr/...
  2. Copy the Dockerfile and the .dockerignore files to that same installation directory
  3. Run the docker build command from that directory to create the local QNX Container application image
In addition, on a make uninstall, the following results occurs:
  1. The target/qnx8/nto/[arch]/<container_name> path is removed
  2. The local QNX Container application image is deleted
To enable this new container.mk file, add the following entry to the end of your common.mk file:
# Container configuration
include $(PROJECT_ROOT)/container.mk
Next, create Dockerfile using the base image you created earlier:
ARG ARCH=x86_64
ARG NTO_VER=800

FROM qnx-base-${ARCH}:${NTO_VER}

ENV PATH=/proc/boot:/system/bin:/usr/bin

ENV LD_LIBRARY_PATH=/proc/boot:/system/lib

ADD . /

CMD ["/hello-container"]
And your .dockerignore as follows:
Dockerfile
.dockerignore
# Any other files we want the docker build to ignore when building the container image
The project directory should contain the following files:
  • nto
  • .dockerignore
  • Dockerfile
  • Makefile
  • common.mk
  • container.mk
  • hello-container.c
  • hello-container.use
Running a make install command from this directory should produce your local QNX Container application image - one for each architecture specified in your nto folder:
make install
make  -Cnto -fMakefile install
make[1]: Entering directory ...
make  -Caarch64 -fMakefile install 
...
docker build -t hello-container-aarch64-qnx800:v0 ... --build-arg="ARCH=aarch64" --build-arg="NTO_VER=800" --platform=linux/aarch64
[+] Building 0.2s (7/7) FINISHED                                                              docker:default
=> [internal] load build definition from Dockerfile                                                     0.0s
=> => transferring dockerfile: 235B                                                                     0.0s
=> [internal] load metadata for docker.io/library/qnx-base-aarch64:800                                  0.0s
=> [internal] load .dockerignore                                                                        0.0s
=> => transferring context: 77B                                                                         0.0s
=> [internal] load build context                                                                        0.0s
=> => transferring context: 12.20kB                                                                     0.0s
=> [1/2] FROM docker.io/library/qnx-base-aarch64:800                                                    0.0s
=> [2/2] ADD . /                                                                                        0.0s
=> exporting to image                                                                                   0.0s
=> => exporting layers                                                                                  0.0s
=> => writing image sha256:02f18a6674dde6c35605cc01cc56a3def28502a406d6e4851218a563d6ccc016             0.0s
=> => naming to docker.io/library/hello-container-aarch64-qnx800:v0                                     0.0s
make[2]: Leaving directory ...
make  -Cx86_64 -fMakefile install
...
docker build -t hello-container-x86_64-qnx800:v0 ... --build-arg="ARCH=x86_64" --build-arg="NTO_VER=800" --platform=linux/x86_64
[+] Building 0.1s (7/7) FINISHED                                                              docker:default
=> [internal] load build definition from Dockerfile                                                     0.0s
=> => transferring dockerfile: 235B                                                                     0.0s
=> [internal] load metadata for docker.io/library/qnx-base-x86_64:800                                   0.0s
=> [internal] load .dockerignore                                                                        0.0s
=> => transferring context: 77B                                                                         0.0s
=> [internal] load build context                                                                        0.0s
=> => transferring context: 11.83kB                                                                     0.0s
=> [1/2] FROM docker.io/library/qnx-base-x86_64:800                                                     0.0s
=> [2/2] ADD . /                                                                                        0.0s
=> exporting to image                                                                                   0.0s
=> => exporting layers                                                                                  0.0s
=> => writing image sha256:cab3e5f365175ce5057ae80fcffe0673941af61f93099e9f519c79d4b96c4572             0.0s
...

❯ docker images
REPOSITORY                        TAG       IMAGE ID       CREATED         SIZE
hello-container-x86_64-qnx800     v0        cab3e5f36517   3 seconds ago   4.34MB
hello-container-aarch64-qnx800    v0        02f18a6674dd   3 seconds ago   4.23MB
CAUTION:
By default, container image files are owned by root, unless otherwise defined in the Dockerfile. If qcmgr is given -U and -G options to restrict the UID or GID of the extracted files as part of a container image, then make sure that the ranges given to qcmgr include 0, or make sure that the owners (users or groups) of the container image files are part of the permitted range specified in the arguments of qcmgr.
Page updated: