Building Akri containers, whether locally or in the automated CI builds, leverages the same set of Dockerfiles. In order to help with local development, a set of Makefile
exists.
The Makefiles are using docker buildx
behind the scenes, ensure you have it installed, if you want to build for foreign architectures, you must also ensure you have correctly set up your docker builder to do so (see Docker buildx documentation)
In essence, Akri components can be thought of as:
- Runtime components
- Rust code: containers based on Rust code are built using
Cargo cross
and subsequentdocker build
commands include the cross-built binaries.Note: For Rust code,
build/Dockerfile.*
does NOT runcargo build
, instead they simply copy cross-built binaries into the container - Other code: these containers can be .NET or python or whatever else ... the
build/Dockerfile.*
must do whatever building is required.
- Rust code: containers based on Rust code are built using
- Intermediate components: these containers are used as part of the build process and are not used in production explicitly
The Akri core components are the containers that provide Akri's functionality. They include the agent, the controller, the webhook and the discovery handlers. All of these are written in Rust.
The samples containers are a set of brokers and applications that can be written in any language, such as .NET, python or Rust. They are used in documentation examples, quickstarts, and demos.
All components are built with a make
command. These are the supporting Makefiles:
Makefile
: this provides a single point of entry to build any Akri componentbuild/akri-containers.mk
: this provides the build and push functionality for Akri core containersbuild/samples.mk
: this provides the build and push functionality for containers used in the samples and documentationbuild/intermediate-container.mk
: this provides the build and push functionality for the opcvsharp base container
The makefiles allow for several configurations:
- PUSH: if set, the make commands will push the built container images to the registry
- LOAD: if set, the make command will load the built container images into the local docker daemon
- PLATFORMS: space separated list of architectures to build for (default to local architecture in LOAD mode, and to
"amd64 arm64 arm/v7"
otherwise) - REGISTRY: allows configuration of the container registry (defaults to imaginary: devcaptest.azurecr.io)
- UNIQUE_ID: allows configuration of container registry account (defaults to $USER)
- PREFIX: allows configuration of container registry path for containers
- LABEL_PREFIX: allows configuration of container labels
For a local build, some typical patterns are:
make akri
: build akri core container images for all architectures (build only, no push nor load)make akri PLATFORMS=arm64
: build akri core containers for ARM64 (build only, no push nor load)make akri PREFIX=ghcr.io/myaccount PUSH=1
: builds all of the Akri core containers and stores them in a container registry,ghcr.io/myaccount
.make akri PREFIX=ghcr.io/myaccount LABEL_PREFIX=local PUSH=1
: builds all of the Akri containers and stores them in a container registry,ghcr.io/myaccount
with labels set tolocal
.make akri PREFIX=ghcr.io/myaccount PLATFORMS=amd64
: builds all of the Akri containers for AMD64 and stores them in a container registry,ghcr.io/myaccount
.make akri-controller PREFIX=ghcr.io/myaccount PUSH=1
: builds the Akri controller container for all platforms and stores them in a container registry,ghcr.io/myaccount
.make akri LOAD=1
: build akri core containers for the local architecture and load them into the docker daemon
Here is the list of supported make targets:
all
: builds all core samples and intermediate container imagespush
: shortcut forall PUSH=1
load
: shortcut forall LOAD=1
akri
: builds all core container imagessamples
: builds all samples container imagesakri-<component>
: builds the container image for this specific core component, core components are currently one of these: agent, agent-full, controller, webhook-configuration, debug-echo-discovery-handler, onvif-discovery-handler, opcua-discovery-handler, udev-discovery-handler<sample-name>
: builds this specific sample container image, can be one of: opcua-monitoring-broker, onvif-video-broker, akri-udev-video-broker, anomaly-detection-app, video-streaming-appopencv-base
: see opencvsharp-build
To add a new Rust-based component, follow these steps:
- Add the new component to
build/akri-containers.mk
as a dependency to theakri
target - Add the new component to the list of components to build in the
build-others
job of.github/workflows/build-rust-containers.yml
These are the intermediate components:
This container is used by the onvif-video-broker as part of its build process. The main purpose of this container is to prevent each build from needing to build the OpenCV C# platform. This container can be built locally for all platforms using this command:
make opencv-base
If a change needs to be made to this container, 2 pull requests are needed.
- Create PR with desired
opencvsharp-build
changes (new dependencies, etc) AND updateBUILD_OPENCV_BASE_VERSION
inbuild/intermediate-containers.mk
. This PR is intended to create the new version ofopencvsharp-build
(not to use it). - After 1st PR is merged and the new version of
opencvsharp-build
is pushed to ghcr.io/akri, create PR with any changes that will leverage the new version ofopencvsharp-build
AND updateUSE_OPENCV_BASE_VERSION
inbuild/samples.mk
. This PR is intended to use the new version ofopencvsharp-build
.
The automated CI builds are using several jobs and leverages the docker build-push action, but it is equivalent to:
# Build and push all images on ghcr.io/project-akri using v<version>-dev label
make push PREFIX="ghcr.io/project-akri" LABEL_PREFIX="v$(cat version.txt)-dev"
For development and/or testing, it can be convenient to run Akri without a Container Registry. For example, the Akri CI tests that validate pull requests build Akri components locally, store the containers only in local docker, and configure Helm to only use the local docker containers.
There are two steps to this. For the sake of this demonstration, only the local architecture version of the agent and controller will be built, but this method can be extended to any and all components:
- Build:
# PREFIX can be anything, as long as it matches what is specified in the Helm command
PREFIX=no-container-registry
# LABEL_PREFIX can be anything, as long as it matches what is specified in the Helm command
LABEL_PREFIX=dev
# Build and load the controller and the agent
make akri-controller akri-agent LOAD=1
-
Runtime
# Specify pullPolicy as Never # Specify repository as $PREFIX/<component> # Specify tag as $LABEL_PREFIX helm install akri ./deployment/helm \ $AKRI_HELM_CRICTL_CONFIGURATION \ --set agent.image.pullPolicy=Never \ --set agent.image.repository="$PREFIX/agent" \ --set agent.image.tag="$LABEL_PREFIX" \ --set controller.image.pullPolicy=Never \ --set controller.image.repository="$PREFIX/controller" \ --set controller.image.tag="$LABEL_PREFIX"