Base Image (oakapp-base)
The base image is a minimal Docker image that provides the necessary environment for running complex OAK 4 Apps. It includes Python 3.12 and other essential libraries, allowing developers to build and deploy applications on OAK 4 cameras. Key components of the base image include:nginx
- a proxy used to serve static files or handle requests to the app's frontend. It exposes both the DAI WebSocket and the frontend on the same port. This is important, especially for access via IP address. Encoded streams are available only via HTTPS, and the only way to enable HTTPS for device access via IP is to use a self-signed certificate. Browsers allow only one self-signed certificate per IP, songinx
creates a reverse proxy for the frontend and DAI WebSocket, which internally run on different ports but must be publicly exposed on a single port with one certificate.oak_webrtc
- a tool for WebRTC communication, used to provide remote access to the app via the*.luxonis.app domain
. It uses WebRTC to establish a connection between the app and the viewer, allowing for real-time streaming of video and other data. It can connect directly on a local network and should handle up to 400 Mbps throughput when network capacity allows. Communication via WebSocket is limited by browser performance and network bandwidth, but it can handle 1 Gbps+ without issues.python 3.12
- Python is used for the backend of the app, which utilizes DAI v3. Please note that DAI itself is installed in the application; an example of requirements file is here: requirements.txt.
Examples
Default App
You can check it in this definition oakapp.toml. Key parts are as follows:Toml
1identifier = "com.example.default"
2entrypoint = ["bash", "-c", "/usr/bin/runsvdir -P /etc/service"]
3app_version = "1.0.0"
4assign_frontend_port = true
identifier
- the name of the app in Java-like format (with dots as separators). Please note that the identifier must be unique in the Hub, so it is recommended to use your team name as a prefix.entrypoint
- an array of strings (a command in argv format). This is the command executed when the app starts; in this case, it runs the service manager, which then starts the Python backend and other services jakonginx
oroak_webrtc
.app_version
- the version of the app. It is recommended to use semantic versioning.assign_frontend_port
- if true, the app will be assigned a frontend port, which is then used by the internalnginx
server to serve the frontend files. If false, the app will not get a frontend port assigned and will not be able to serve any frontend files on the standard port. The agent running on OAK4 handles port assignment, and a unique port is assigned to each app, so it is not necessary to specify the port in theoakapp.toml
file.
Toml
1prepare_container = [
2 { type = "COPY", source = "./requirements.txt", target = "./requirements.txt" },
3 { type = "RUN", command = "python3.12 -m pip install -r /app/requirements.txt --break-system-packages"}
4]
requirements.txt
file into the container and installing the required Python packages using pip
. This ensures that all necessary dependencies are available when the application starts. Additionally, it guarantees that dependencies are installed only once or as needed when the oakctl app run
command is executed.Toml
1build_steps = [
2 "mkdir -p /etc/service/backend",
3 "cp /app/backend-run.sh /etc/service/backend/run",
4 "chmod +x /etc/service/backend/run",
5]
backend-run.sh
script to the appropriate location, and sets the necessary permissions to make it executable. This script is responsible for starting the backend of the application. You can add more services as needed for your app to run.Toml
1[base_image]
2api_url = "https://registry-1.docker.io"
3service = "registry.docker.io"
4oauth_url = "https://auth.docker.io/token"
5auth_type = "repository"
6auth_name = "luxonis/oakapp-base"
7image_name = "luxonis/oakapp-base"
8image_tag = "1.2.5"
luxonis/oakapp-base
image, as it is specifically designed for OAK 4 Apps and includes all necessary dependencies and configurations.Another important part is the file backend-run.sh, which includes a simple command to start the Python backend. It uses Python 3.12, which is part of the base image, so it is not necessary to install it again.Dynamic Yolo World
This is a more complex example that uses all features. The app definition is available here: oakapp.toml. Key differences from the previous example are:Toml
1prepare_build_container = [{type = "RUN", command = "bash -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash && . \"$HOME/.nvm/nvm.sh\" && nvm install 24'"}]
2build_steps = [
3 "mkdir -p /etc/service/backend",
4 "cp /app/backend-run.sh /etc/service/backend/run",
5 "chmod +x /etc/service/backend/run",
6]
7
8[static_frontend]
9dist_path = "./frontend/dist"
10
11[static_frontend.build]
12source_path = "./frontend"
13steps = ["bash -c 'cd /app/frontend/src && export NODE_OPTIONS=--max-old-space-size=4096 && . $HOME/.nvm/nvm.sh && npm install && npm run build'"]
nvm
to install Node.js version 24 and then builds the frontend application. The frontend build is performed in the static_frontend.build
section, where npm
is used to install dependencies and build the application. This build is performed on the device as well, so running oakctl app run .
is enough to build the entire app, including the frontend.dist_path
- the path to the built frontend application; this is where the built files are located after the build process is finished. It is recommended to follow the structure in this example, with one folder for the backend and another for the frontend. This is not required, but it helps keep the structure clean and organized.source_path
- the path to the source code of the frontend application; this is where the source code is located before the build process starts.steps
- an array of strings, each representing a command that will be executed in the container to build the frontend application. In this case,npm
is used to install dependencies and build the application. TheNODE_OPTIONS
environment variable is set to increase the memory limit for Node.js, helping to avoid out-of-memory errors during the build process. The frontend uses the React.js library@luxonis/depthai-viewer-common
, which provides high-level components for rendering streams and annotations, and enables communication with the backend using WebSocket for direct access and WebRTC for remote access via the*.luxonis.app domain
.