diff --git a/extra-addons/open_workshop/open_workshop_mqtt/__manifest__.py b/extra-addons/open_workshop/open_workshop_mqtt/__manifest__.py index 84d1bfa..2b2ea38 100644 --- a/extra-addons/open_workshop/open_workshop_mqtt/__manifest__.py +++ b/extra-addons/open_workshop/open_workshop_mqtt/__manifest__.py @@ -42,8 +42,8 @@ 'data/mqtt_broker_data.xml', 'data/ir_cron.xml', 'views/mqtt_bridge_views.xml', - 'views/mqtt_broker_views.xml', 'views/mqtt_device_views.xml', + 'views/mqtt_broker_views.xml', 'views/mqtt_session_views.xml', 'views/iot_event_views.xml', 'views/mqtt_menus.xml', diff --git a/iot_bridge/Dockerfile b/iot_bridge/Dockerfile index d3cc37b..179298c 100644 --- a/iot_bridge/Dockerfile +++ b/iot_bridge/Dockerfile @@ -16,18 +16,22 @@ RUN pip install --no-cache-dir --user -r requirements.txt # Stage 2: Runtime - Minimal image FROM python:3.11-slim -LABEL maintainer="Open Workshop MQTT IoT Bridge" -LABEL description="MQTT Bridge for Odoo IoT Device Integration with Session Detection" -LABEL version="1.0.0" +LABEL maintainer="Open Workshop MQTT IoT Bridge" \ + description="MQTT Bridge for Odoo IoT Device Integration with Session Detection" \ + version="1.0.0" WORKDIR /app +# Install runtime utilities +RUN apt-get update && \ + apt-get install -y --no-install-recommends curl && \ + rm -rf /var/lib/apt/lists/* + # Copy installed packages from builder to site-packages (not user directory) COPY --from=builder /root/.local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages -# Copy application code -COPY *.py ./ -COPY config.example.yaml ./ +# Copy application code (subdirectories api/, clients/, config/, core/, parsers/, utils/ included) +COPY . . # Create non-root user for security RUN useradd -m -u 1000 bridge && \ @@ -35,12 +39,16 @@ RUN useradd -m -u 1000 bridge && \ mkdir -p /app/logs /data && \ chown -R bridge:bridge /app/logs /data +# Declare persistent data directories +VOLUME ["/app/logs", "/data"] + # Switch to non-root user USER bridge # Environment variables (can be overridden at runtime) ENV BRIDGE_CONFIG=/app/config.yaml \ PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ LOG_LEVEL=INFO \ BRIDGE_PORT=8080 @@ -49,8 +57,7 @@ EXPOSE 8080 # Health check via HTTP endpoint HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ - CMD python3 -c "import requests; requests.get('http://localhost:8080/health', timeout=3).raise_for_status()" || exit 1 -# CMD python -c "import socket; s=socket.socket(); s.connect(('localhost',8080)); s.close()" || exit 1 + CMD curl -f http://localhost:${BRIDGE_PORT}/health || exit 1 -# Run bridge with unbuffered output -CMD ["python", "-u", "main.py"] +# Run bridge +CMD ["python", "main.py"] diff --git a/iot_bridge/Dockerfile.dev b/iot_bridge/Dockerfile.dev new file mode 100644 index 0000000..d3cc37b --- /dev/null +++ b/iot_bridge/Dockerfile.dev @@ -0,0 +1,56 @@ +# Multi-stage build for IoT MQTT Bridge +# Stage 1: Builder - Install dependencies +FROM python:3.11-slim AS builder + +WORKDIR /app + +# Install build dependencies +RUN apt-get update && \ + apt-get install -y --no-install-recommends gcc && \ + rm -rf /var/lib/apt/lists/* + +# Copy requirements and install dependencies +COPY requirements.txt . +RUN pip install --no-cache-dir --user -r requirements.txt + +# Stage 2: Runtime - Minimal image +FROM python:3.11-slim + +LABEL maintainer="Open Workshop MQTT IoT Bridge" +LABEL description="MQTT Bridge for Odoo IoT Device Integration with Session Detection" +LABEL version="1.0.0" + +WORKDIR /app + +# Copy installed packages from builder to site-packages (not user directory) +COPY --from=builder /root/.local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages + +# Copy application code +COPY *.py ./ +COPY config.example.yaml ./ + +# Create non-root user for security +RUN useradd -m -u 1000 bridge && \ + chown -R bridge:bridge /app && \ + mkdir -p /app/logs /data && \ + chown -R bridge:bridge /app/logs /data + +# Switch to non-root user +USER bridge + +# Environment variables (can be overridden at runtime) +ENV BRIDGE_CONFIG=/app/config.yaml \ + PYTHONUNBUFFERED=1 \ + LOG_LEVEL=INFO \ + BRIDGE_PORT=8080 + +# Expose HTTP Config API port +EXPOSE 8080 + +# Health check via HTTP endpoint +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ + CMD python3 -c "import requests; requests.get('http://localhost:8080/health', timeout=3).raise_for_status()" || exit 1 +# CMD python -c "import socket; s=socket.socket(); s.connect(('localhost',8080)); s.close()" || exit 1 + +# Run bridge with unbuffered output +CMD ["python", "-u", "main.py"] diff --git a/iot_bridge/requirements.txt b/iot_bridge/requirements.txt index f0ae837..6350eb2 100644 --- a/iot_bridge/requirements.txt +++ b/iot_bridge/requirements.txt @@ -22,10 +22,5 @@ python-dotenv>=1.0.0 # Logging structlog>=24.1.0 -# Testing -pytest>=8.0.0 -pytest-cov>=4.1.0 -pytest-asyncio>=0.23.0 - # Type Hints typing-extensions>=4.9.0