基础镜像 (oakapp-base)
nginx—— 用于提供静态文件或处理应用前端请求的代理。它同时暴露 DAI WebSocket 和前端在同一端口上。这对于通过 IP 地址访问尤其重要。编码流仅可通过 HTTPS 获取,而为设备通过 IP 访问启用 HTTPS 的唯一方式是使用自签名证书。浏览器每个 IP 只允许一个自签名证书,因此nginx为前端和 DAI WebSocket 创建反向代理,它们内部运行在不同端口,但必须通过单个端口公开暴露并附带一个证书。oak_webrtc—— 用于 WebRTC 通信的工具,通过*.luxonis.app域名提供对应用的远程访问。它使用 WebRTC 在应用与查看器之间建立连接,实现视频和其他数据的实时流传输。它可以在本地网络中直接连接,当网络容量允许时,应能处理高达 400 Mbps 的吞吐量。通过 WebSocket 的通信受浏览器性能和网络带宽限制,但可以无问题地处理 1 Gbps+。python 3.12—— Python 用于应用的后端,使用 DAI v3。请注意,DAI 本身安装在应用中;需求文件的示例如下:requirements.txt。
示例
默认应用
Toml
1identifier = "com.example.default"
2entrypoint = ["bash", "-c", "/usr/bin/runsvdir -P /etc/service"]
3app_version = "1.0.0"
4assign_frontend_port = trueidentifier—— 应用的名称,采用 Java 类似的格式(以点作为分隔符)。请注意,标识符在 Hub 中必须唯一,因此建议使用你的团队名称作为前缀。entrypoint—— 字符串数组(argv 格式的命令)。这是应用启动时执行的命令。在此例中,它运行服务管理器(runit监控器),负责运行所有默认服务以及使用基础镜像的应用中用户自定义的服务。它首先启动内部nginx,处理 HTTPS 和端口暴露。然后运行ak_webrtc工具,通过 WebRTC 管理远程访问。最后,执行/etc/service/文件夹中定义的任何脚本。在我们的案例中,即文件/etc/service/backend/run,其中包括exec python3.12 /app/main.py以启动应用的后端。你可以根据需要为应用添加更多服务。app_version—— 应用的版本。建议使用语义化版本。assign_frontend_port—— 如果为 true,应用将被分配一个前端端口,内部nginx服务器将使用该端口提供前端文件。如果为 false,应用不会获得前端端口分配,也无法在标准端口上提供任何前端文件。运行在 OAK4 上的代理负责端口分配,每个应用被分配一个唯一端口,因此无需在oakapp.toml文件中指定端口。
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 文件复制到容器中,并使用 pip 安装所需的 Python 包。这确保 了应用启动时所有必要的依赖都可用。此外,它保证依赖只安装一次,或者在执行 oakctl app run 命令时按需安装。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 脚本复制到适当位置,并设置必要的权限使其可执行。该脚本负责启动应用的后端。你可以根据需要为应用添加更多服务。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 镜像,因为它专为 OAK4 Apps 设计,并包含了所有必要的依赖项和配置。另一个重要的部分是文件 backend-run.sh,其中包含一个简单的命令用于启动 Python 后端。它使用 Python 3.12,这是基础镜像的一部分,因此无需再次安装。开放词汇目标检测(Open Vocabulary Object Detection)
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 安装 Node.js 版本 24,然后构建前端应用。前端构建在 static_frontend.build 部分执行,使用 npm 安装依赖并构建应用。该构建过程也在设备上执行,因此只需运行 oakctl app run . 即可构建整个应用,包括前端。dist_path– 构建后的前端应用路径;构建过程完成后,构建好的文件位于此处。建议遵循本示例的结构,即一个文件夹存放后端,另一个存放前端。这不是必须的,但有助于保持结构清晰有序。source_path– 前端应用的源代码路径;构建过程开始前,源代码位于此处。steps– 字符串数组,每个字符串代表一个在容器中执行的命令,用于构建前端应用。在本例中,使用npm安装依赖并构建应用。设置NODE_OPTIONS环境变量以增加 Node.js 的内存限制,有助于避免构建过程中出现内存不足的错误。前端使用 React.js 库@luxonis/depthai-viewer-common,该库提供了用于渲染流和注释的高级组件,并通过 WebSocket 实现直接访问、通过 WebRTC 实现通过*.luxonis.app域名的远程访问,从而实现与后端的通信。