cv2.VideoCapture(0) not working inside Docker on macOS (Apple Silicon / M1), but works locally

Hi all,

I’m currently working on a Python application using OpenCV (cv2) on macOS (Apple Silicon M1). The app captures video from the default webcam using:

import cv2

cap = cv2.VideoCapture(0)

if not cap.isOpened():
    print("Cannot open camera")
    exit()

Here is my docker build file

FROM --platform=amd64 python:3.12-slim-bullseye

RUN apt-get update && apt-get install -y --no-install-recommends \
	libgl1 \
	libglib2.0-0 \
	v4l-utils \  
	libv4l-dev \
	libgl1-mesa-glx \
	&& rm -rf /var/lib/apt/lists/*

COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv

WORKDIR /app

COPY . /app

RUN uv sync --frozen --no-cache

EXPOSE 9000

CMD ["/app/.venv/bin/fastapi", "run", "app/main.py", "--port", "9000"]

Here is my docker compose file:

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    image: muktadirdocker/klassy-python-backend:latest
    container_name: klassy-python-container
    ports:
      - "9000:9000"
    devices:
      - "/dev/video0:/dev/video0"
    group_add:
      - "video"
    volumes:
      - "/dev:/dev:ro"
    privileged: true
    restart: unless-stopped

Here is my Docker container logs:

Searching for package file structure from directories with


__init__.py files


Importing from /app




module 📁 app


├── 🐍 __init__.py


└── 🐍 main.py




code Importing the FastAPI app object from the module with the following


code:




from app.main import app




app Using import string: app.main:app




server Server started at http://0.0.0.0:9000⁠


server Documentation at http://0.0.0.0:9000/docs⁠




Logs:




INFO: Created TensorFlow Lite XNNPACK delegate for CPU.


WARNING: All log messages before absl::InitializeLog() is called are written to STDERR


W0000 00:00:1746288955.743384 30 inference_feedback_manager.cc:114] Feedback manager requires a model with a single signature inference. Disabling support for feedback tensors.


INFO Started server process [1]


INFO Waiting for application startup.


INFO Application startup complete.


INFO Uvicorn running on http://0.0.0.0:9000⁠ (Press CTRL+C to quit)


W0000 00:00:1746288955.825012 30 inference_feedback_manager.cc:114] Feedback manager requires a model with a single signature inference. Disabling support for feedback tensors.


INFO 192.168.65.1:58227 - "GET /api/lipcolor/stream HTTP/1.1" 200


[ WARN:0@6.414] global cap_v4l.cpp:913 open VIDEOIO(V4L2:/dev/video0): can't open camera by index


[ERROR:0@6.416] global obsensor_uvc_stream_channel.cpp:158 getStreamChannelGroup Camera index out of range


Error: Could not open camera.

:magnifying_glass_tilted_left: What I’ve tried:

  • Adding --device=/dev/video0:/dev/video0 to docker run — doesn’t work on macOS since Docker Desktop uses a Linux VM and doesn’t expose macOS hardware devices like /dev/video0.
  • Tried privileged mode, mounting /dev, etc. — again, no luck (since the container doesn’t actually run natively on macOS).
  • I understand this would work on a native Linux system, where /dev/video0 is available and can be passed into the container.

You cannot mount devices in Docker Desktop as everything is inside a virtual Machine, including the Docker daemon.

1 Like

Locally, it works fine, which means we need to find an alternative solution to address the cv2.VideoCapture(0) issue. Since there is no direct way to access host devices from within a Docker container on macOS, using WebRTC is a suitable approach for accessing and processing video streams from the host device.

Why would you recommend WebRTC?

I agree that you could probably stream camera data into a container with a utility on host through socket or TCP/UDP, but WebRTC is a very complex protocol for such a simple use case.

1 Like

My primary issue is that cv2.VideoCapture(0) cannot open the camera index. Is there any way to resolve this? If a solution exists, it would help me fix the problem.

You could try to use a tool like obsproject.com to turn a local webcam into a RTSP video streaming device, which could be accessed from inside VM and container via network.

1 Like