ON THIS PAGE

  • Configuration (oakapp.toml)
  • Configuration Fields
  • App Metadata
  • App Build and Runtime Configuration
  • App Layers
  • Base Image
  • Runtime And Build Layer
  • App Layer
  • Mounts
  • Static frontend
  • DepthAI Models Cache
  • Environment Variables

Configuration (oakapp.toml)

Within each app's directory, there must be a oakapp.toml file that contains static app's metadata and build steps. Metadata includes the app's identifier and version. Build steps are commands that are executed in the container to build or run the app. Example oakapp.toml file:
Toml
1# (Required) App Identifier
2identifier = "com.luxonis.python_demo"
3# (Required) App Entrypoint
4entrypoint = ["bash", "-c", "python3 /app/main.py"]
5
6# (Optional) Prepare container commands
7# Here is the place where you can install all the dependencies that are needed at run-time
8prepare_container = [
9    { type = "COPY", source = "requirements.txt", target = "requirements.txt" },
10    { type = "RUN", command = "apt-get update" },
11    { type = "RUN", command = "apt-get install -y python3-pip" },
12    { type = "RUN", command = "pip3 install -r /app/requirements.txt --break-system-packages" },
13]
14
15# (Optional) Prepare build dependencies
16# Here is the place where you can install all the dependencies that are needed at build-time
17prepare_build_container = [
18    # Example: npm, gcc, ...
19]
20
21# (Optional) Additional commands after all the app files are copied to the container
22build_steps = []

Configuration Fields

App Metadata

  • identifier - name of the app in Java-like format (with dots as separators; e.g., com.my_company.my_app)
    • com.luxonis namespace is reserved for official apps
    • com.example namespace is is not recommended for production apps
  • app_version - version of the app in format major.minor.patch (e.g., 1.0.0)

App Build and Runtime Configuration

  • entrypoint - array of strings (a command in argv format)
  • cwd - (optional, default is / ) current working directory for the container
  • app_dir_name (optional/advanced; default is app ) - directory inside the container where the app files are copied; use only if you already use this directory name for something else

App Layers

Similar to Docker, an app is built in multiple layers:
  1. Base Image layer (specified in base_image section)
  2. Runtime layer (built in prepare_container section)
  3. Build layer (built in prepare_build_container section; this layer is disconnected from runtime layer after build)
  4. App layer (all the files from the app's directory and the build_steps are executed here)
Next to App layer, there are two additional parallel layers:
  • Static Frontend layer (if specified in static_frontend section)
  • DepthAI Models Cache layer (if specified in depthai_models section)
If any of these layers change, all the subsequent layers are rebuilt. Parallel layers are rebuilt independently of each other as they do not have mutual dependencies.

Base Image

Base image for the container needs to be debian based. The current default is debian/bookworm-slim, see example below:
Toml
1[base_image]
2api_url = "https://registry-1.docker.io" # Service https address
3service = "registry.docker.io" # Name of Image Registry Service
4oauth_url = "https://auth.docker.io/token" # address to oauth 2.0 token for this service
5auth_type = "repository" # scope type
6auth_name = "library/debian" # name of resource
7
8image_name = "library/debian"
9image_tag = "bookworm-slim"
If you need a different Docker image as a base layer, you just need to define this image in oakapp.toml using:
Toml
1[base_image]
2image_name = "library/debian"
3image_tag = "bookworm-slim"
By default, it downloads images from Docker Hub, but you can specify a different repository. There are several limitations for the Docker image you can use:
  • It must be a Debian 12-based image
  • It must support ARM architecture
  • It must be compatible with Docker's Manifest V2
Alternatively, you can use a locally running registry and configure the [base_image] setting in oakapp.toml as follows:
Toml
1[base_image]
2 api_url = "http://localhost:5000" # Service http address visible from the device
3 image_name = "debian"
4 image_tag = "bookworm-slim"
Plus serve this on local network:
Command Line
1podman run -d -p 5000:5000 --name registry registry:2.7
2 
3npm install -g regctl
4wget <URL>/debian_bookworm-slim.tar
5 
6regctl registry set --tls=disabled localhost:5000
7regctl image import localhost:5000/debian:bookworm-slim debian_bookworm-slim.tar
Keep in mind that the app is built on the device, so the registry must be accessible from the device. The base_image.api_url has to point to the device's network-accessible address.

Runtime And Build Layer

Both prepare_container and prepare_build_container are arrays of commands that are executed in the container to prepare the respective layers. The only difference is that the build layer is not present at runtime.The available command types are:
  • RUN - run a command in the container
Toml
1prepare_container = [
2    { type = "RUN", command = "apt-get update" },
3    { type = "RUN", command = "apt-get install -y python3-pip" },
4]
  • COPY - copy a file from the app's directory to the container sooner than in the App layer. This is useful for copying dependency files like requirements.txt. It is not necessary to copy the actual app files here, as they are copied later in the App layer.
    • source - path to the source file relative to the app's directory on the host
    • target - path to app directory inside the container (relative to app_dir_name if specified)
Toml
1prepare_container = [
2    { type = "COPY", source = "requirements.txt", target = "requirements.txt" },
3]

App Layer

First, all the files from the app's directory are copied to the container (into app_dir_name if specified). Then, the commands in build_steps are executed in order.
  • build_steps - steps to build an application or other preparation commands to be executed (array of strings)
Toml
1build_steps = [
2    "g++ -o /app/my_app /app/main.cpp",
3    "chmod +x /app/my_app",
4]
You can ignore files from being copied to the container by adding a .oakignore file to your app's directory. The syntax is similar to .gitignore. Example:
Plain Text
1# Ignore all .log files
2*.log
3# Ingore node_modules/ directory
4node_modules/

Mounts

Mounts allow you to link directories or devices from the device running the app into the app's container. You cannot mount directories from the host this way. Mounts that are required must be present at both build time and run time.
  • required_mounts, required_devices - mounts that are required - if not present on startup of container, the app is stopped with error
Syntax is source[:target[:options]]; defaults:
  • source=target
  • options="rbind,rw"
Example:
Toml
1required_mounts = [
2    "/data/my-storage:/app/storage:rw",
3]
  • optional_mounts, optional_devices - if not present of startup of container, these mounts are ignored
  • additional_mounts ( source , target , type , options , required ) array of objects, see below for example:
Toml
1additional_mounts = [
2    { source = "/run/user/1000/pulse", target = "/run/user/1000/pulse", type = "none", options = [
3        "rbind",
4        "rw",
5    ], required = true },
6    { source = "/home/root/.config/pulse/cookie", target = "/root/.config/pulse/cookie", type = "none", options = [
7        "bind",
8        "ro",
9    ], required = true },
10]
  • allowed_devices - list of devices that the app is allowed to access inside the container
Toml
1allowed_devices = [{ allow = true, access = "rwm" }]

Static frontend

Static frontend layer allows you to build and serve a static web frontend alongside your app. See example on GitHub.
  • static_frontend
    • dist_path - path to the built frontend files (relative to the app's directory on the host)
      • build (optional) - build configuration for the frontend
        • source_path - path to the frontend source files
        • steps - array of commands to build the frontend
Toml
1[static_frontend]
2dist_path = "./frontend/dist" # path to the built frontend files
3
4[static_frontend.build]
5source_path = "./frontend" # path to the frontend source files
6steps = ["bash -c 'cd /app/frontend/src && npm install && npm run build'"]
  • assign_frontend_port - if set to true, an available port will be assigned to OAKAPP_STATIC_FRONTEND_PORT environment variable inside the container; this can be used even if static_frontend is not specified
Toml
1assign_frontend_port = true
  • static_frontend_dir_name (optional/advanced; default is static_frontend) - directory inside the container where the static frontend files are mounted (will be stored in OAKAPP_STATIC_FRONTEND_PATH environment variable); use only if you already use this directory name for something else

DepthAI Models Cache

This section allows you to specify a folder with DepthAI models in *.yaml format that will be cached inside the container during build time. This way, you can create apps that work offline without the need to download models at runtime.
  • depthai_models
    • yaml_path - path to the DepthAI models folder in *.yaml format
    • use_only_cache - if set to true, only the cached models will be used, and no new models will be downloaded at runtime (sets DEPTHAI_ZOO_INTERNET_CHECK environment variable)
Toml
1depthai_models = { yaml_path = "./backend/src/depthai_models" }
  • depthai_models_dir_name (optional/advanced; default is depthai_models) - directory inside the container where the DepthAI models are mounted; use only if you already use this directory name for something else

Environment Variables

Environment variables are set for runtime only.
Toml
1[env]
2MY_ENV_VAR = "some_value"
3ANOTHER_ENV_VAR = "another_value"