Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
**/.DS_Store
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/charts
**/docker-compose*
**/compose.y*ml
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/secrets.dev.yaml
**/values.dev.yaml
/bin
/target
LICENSE
257 changes: 215 additions & 42 deletions README.md

Large diffs are not rendered by default.

10 changes: 3 additions & 7 deletions config/client_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ MAX_LOG_ENTRIES: &max-log-entries 100
SLO_TIMEOUT: &slo-timeout 200 # TODO: change this
QUIC_SHM_SIZE: &quic-shm-size 50000000

# needed for ping loop
DST_IP: &dst-ip 136.118.43.70

main_client_config_list:
- service_id: 1
max_entries: *max-log-entries
Expand Down Expand Up @@ -87,7 +84,6 @@ bandwidth_allocator_config:
bidirectional_zmq_ping_handler_sockname: ping-handler

ping_handler_config:
dst_ip: *dst-ip
max_entries: 100
thread_concurrency: 5
bidirectional_zmq_sockname: ping-handler
Expand All @@ -103,7 +99,7 @@ camera_stream_config_list:
shmem_buf_size: *quic-shm-size
camera_np_size: [1080, 1920, 3]
zmq_kill_switch_sockname: camera-kill-1-switch
mock_camera_image_path: null # set to a file path (e.g. mock_webcam_image.jpg) to use a static image instead of webcam
mock_camera_image_path: /home/hwei/turbo/src/python/camera_stream/mock_webcam_image.jpg # only used when --mock-camera is passed
- camera_id: 2 # FRONT LEFT
usb_id: 4 # TODO: CONFIGURE THIS
max_entries: *max-log-entries
Expand All @@ -113,7 +109,7 @@ camera_stream_config_list:
shmem_buf_size: *quic-shm-size
camera_np_size: [1080, 1920, 3]
zmq_kill_switch_sockname: camera-kill-2-switch
mock_camera_image_path: null
mock_camera_image_path: /home/hwei/turbo/src/python/camera_stream/mock_webcam_image.jpg # only used when --mock-camera is passed
- camera_id: 3 # FRONT RIGHT
usb_id: 8 # TODO: CONFIGURE THIS
max_entries: *max-log-entries
Expand All @@ -123,7 +119,7 @@ camera_stream_config_list:
shmem_buf_size: *quic-shm-size
camera_np_size: [1080, 1920, 3]
zmq_kill_switch_sockname: camera-kill-3-switch
mock_camera_image_path: null
mock_camera_image_path: /home/hwei/turbo/src/python/camera_stream/mock_webcam_image.jpg # only used when --mock-camera is passed

main_plotter_config:
# service 4 is for junk stream
Expand Down
12 changes: 6 additions & 6 deletions config/server_config_gcloud.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ server_config_list:
thread_concurrency: 10
shm_filesize: *shm-filesize
zmq_kill_switch_sockname: remote-server-kill-switch-1
mock_inference_output_path: null # set to a file path (e.g. example_effdet_d4_output.npz) to skip model loading and return mock detections
mock_model_latency_csv_path: null # set to experiment_model_info.csv path to simulate per-model inference latency in mock mode
mock_inference_output_path: /home/hwei/turbo/src/python/camera_stream/example_effdet_d4_output.npy # only used when --mock-inference is passed
mock_model_latency_csv_path: /home/hwei/turbo/experiment_model_info.csv # only used when --mock-inference is passed
- service_id: 2
max_entries: *max-log-entries
model_metadata_list: *model-list-ref
Expand All @@ -51,8 +51,8 @@ server_config_list:
thread_concurrency: 10
shm_filesize: *shm-filesize
zmq_kill_switch_sockname: remote-server-kill-switch-2
mock_inference_output_path: null
mock_model_latency_csv_path: null
mock_inference_output_path: /home/hwei/turbo/src/python/camera_stream/example_effdet_d4_output.npy # only used when --mock-inference is passed
mock_model_latency_csv_path: /home/hwei/turbo/experiment_model_info.csv # only used when --mock-inference is passed
- service_id: 3
max_entries: *max-log-entries
model_metadata_list: *model-list-ref
Expand All @@ -64,5 +64,5 @@ server_config_list:
thread_concurrency: 10
shm_filesize: *shm-filesize
zmq_kill_switch_sockname: remote-server-kill-switch-3
mock_inference_output_path: null
mock_model_latency_csv_path: null
mock_inference_output_path: /home/hwei/turbo/src/python/camera_stream/example_effdet_d4_output.npy # only used when --mock-inference is passed
mock_model_latency_csv_path: /home/hwei/turbo/experiment_model_info.csv # only used when --mock-inference is passed
51 changes: 51 additions & 0 deletions docker/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Host user/group IDs — set these to match your host user (id -u / id -g)
# so that bind-mounted files are accessible inside containers.
HOST_UID=1000
HOST_GID=1000

# quic client-side only
# Same-host: use Docker bridge gateway (10.64.89.1). Remote: use server host's routable IP.
QUIC_CLIENT_ADDR=10.64.89.1:12345
QUIC_CLIENT_PORT=5000

QUIC_DOCKER_CLIENT_CONFIG_PATH=./config/quic_config_client_docker.yaml

# quic server-side only
QUIC_SERVER_ADDR=0.0.0.0:12345
QUIC_SERVER_PORT=12345

QUIC_DOCKER_SERVER_CONFIG_PATH=./config/quic_config_gcloud_docker.yaml

# python client config
PYTHON_DOCKER_CLIENT_CONFIG_PATH=./config/client_config_docker.yaml

# python server config
PYTHON_DOCKER_SERVER_CONFIG_PATH=./config/server_config_gcloud_docker.yaml

# both client and server-side
DOCKER_LOG_CONFIG_PATH=./config/logging_config_docker.yaml
EXPERIMENT_OUTPUT_DIR=/path/to/experiment2-out

# client-side only
DASHBOARD_PORT=5000
MODEL_FULL_EVAL_DIR=/path/to/full-eval

# server-side only
EFFDET_MODELS_DIR=/path/to/av-models

# for quic cargo build
SSL_KEY_PATH=./src/quic/ssl_key.pem
SSL_CERT_PATH=./src/quic/ssl_cert.pem

# rust env vars
RUST_LOG=info
RUST_BACKTRACE=full

# for both client and server
EXPERIMENT_MODEL_INFO_PATH=../experiment_model_info.csv
MOCK_EFFDET_OUTPUT_PATH=../src/python/camera_stream/example_effdet_d4_output.npy
MOCK_EFFDET_INPUT_PATH=../src/python/camera_stream/mock_webcam_image.jpg

# Mock modes — set to any non-empty value (e.g. "true") to enable, leave empty to disable
MOCK_CAMERA=
MOCK_INFERENCE=
42 changes: 42 additions & 0 deletions docker/Dockerfile_turbo_python_base
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# syntax=docker/dockerfile:1

# doesn't build with torch for python3.10-alpine
FROM ghcr.io/astral-sh/uv:python3.10-trixie AS python_build

# Enable bytecode compilation
ENV UV_COMPILE_BYTECODE=1

# Copy from the cache instead of linking since it's a mounted volume
ENV UV_LINK_MODE=copy

# Omit development dependencies
ENV UV_NO_DEV=1

# Ensure installed tools can be executed out of the box
ENV UV_TOOL_BIN_DIR=/usr/local/bin

WORKDIR /app

RUN apt-get update && apt-get install ffmpeg libsm6 libxext6 --yes

# Install the project's dependencies using the lockfile and settings
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --no-install-project --locked

# Then, add the rest of the project source code and install it
# Installing separately from its dependencies allows optimal layer caching
COPY ./src/python /app/src/python

RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
--mount=type=bind,source=README.md,target=README.md \
uv sync --locked

# Place executables in the environment at the front of the path
ENV PATH="/app/.venv/bin:$PATH"

ARG GID
RUN groupadd --system --gid ${GID} nonroot
28 changes: 28 additions & 0 deletions docker/Dockerfile_turbo_python_binary
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# syntax=docker/dockerfile:1

FROM base_image AS final
WORKDIR /app

ARG EXECUTABLE_DIR
ARG EXECUTABLE_NAME

# Create a non-privileged user that the app will run under.
# See https://docs.docker.com/go/dockerfile-user-best-practices/
ARG GID=515
ARG UID=999

# Setup a non-root user
RUN useradd --system --gid ${GID} --uid ${UID} --create-home nonroot
USER nonroot


ENV EXECUTABLE_DIR=${EXECUTABLE_DIR}
ENV EXECUTABLE_NAME=${EXECUTABLE_NAME}

# What the container should run when it is started.
# Signal handling is provided by `init: true` in compose.yaml (tini as PID 1).
# `exec` is optional here — it just avoids a redundant /bin/sh parent process.
# We call python directly instead of `uv run` because uv spawns python as a
# child and may not forward signals. The venv is already on PATH
# (set in Dockerfile_turbo_python_base), so `python` resolves correctly.
CMD cd ${EXECUTABLE_DIR} && exec python ${EXECUTABLE_NAME} "-c" "/app/python_config.yaml"
39 changes: 39 additions & 0 deletions docker/Dockerfile_turbo_quic_binary
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# syntax=docker/dockerfile:1

FROM base_image
ARG APP_NAME
WORKDIR /app

FROM alpine:3.18 AS final
ARG APP_NAME
ARG QUIC_BIND_ADDR
ARG QUIC_DOCKER_PORT

# Create a non-privileged user that the app will run under.
# See https://docs.docker.com/go/dockerfile-user-best-practices/
ARG UID=10001
ARG GID=999
RUN addgroup -g "${GID}" sharedgroup && \
adduser \
--disabled-password \
--gecos "" \
--home "/nonexistent" \
--shell "/sbin/nologin" \
--no-create-home \
--uid "${UID}" \
--ingroup sharedgroup \
appuser
USER appuser

# Copy the executable from the "build" stage.
COPY --from=base_image /bin/$APP_NAME /bin/server

# Expose the port that the application listens on.
EXPOSE ${QUIC_DOCKER_PORT}

ENV QUIC_BIND_ADDR=${QUIC_BIND_ADDR}

# What the container should run when it is started.
# Signal handling is provided by `init: true` in compose.yaml (tini as PID 1).
# `exec` is optional here — it just avoids a redundant /bin/sh parent process.
CMD exec /bin/server "/app/quic_config.yaml" "${QUIC_BIND_ADDR}"
36 changes: 36 additions & 0 deletions docker/Dockerfile_turbo_rust_base
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# syntax=docker/dockerfile:1

ARG RUST_VERSION=1.93.0

FROM rust:${RUST_VERSION}-alpine AS rust_build
ARG APP_NAME_LIST
ARG SSL_CERT_PATH
ARG SSL_KEY_PATH
WORKDIR /app

# Install host build dependencies.
RUN apk add --no-cache clang lld musl-dev git

# Build the application.
# Leverage a cache mount to /usr/local/cargo/registry/
# for downloaded dependencies, a cache mount to /usr/local/cargo/git/db
# for git repository dependencies, and a cache mount to /app/target/ for
# compiled dependencies which will speed up subsequent builds.
# Leverage a bind mount to the src directory to avoid having to copy the
# source code into the container. Once built, copy the executable to an
# output directory before the cache mounted /app/target is unmounted.
RUN --mount=type=bind,source=src/quic/quic_client,target=quic_client \
--mount=type=bind,source=src/quic/quic_conn,target=quic_conn \
--mount=type=bind,source=src/quic/quic_server,target=quic_server \
--mount=type=bind,source=src/quic/Cargo.toml,target=Cargo.toml \
--mount=type=bind,source=src/quic/Cargo.lock,target=Cargo.lock \
--mount=type=bind,source=${SSL_CERT_PATH},target=ssl_cert.pem \
--mount=type=bind,source=${SSL_KEY_PATH},target=ssl_key.pem \
--mount=type=cache,target=/app/target/ \
--mount=type=cache,target=/usr/local/cargo/git/db \
--mount=type=cache,target=/usr/local/cargo/registry/ \
cargo build --locked --release && \
IFS=',' && \
for app_name in $APP_NAME_LIST; do \
echo $app_name && echo $(ls ./target/release) && cp ./target/release/$app_name /bin/$app_name; \
done
Loading