OpenHands / Dockerfile
Backup-bdg's picture
Update Dockerfile
bbdb7f0 verified
# ===== MULTI-STAGE DOCKERFILE FOR OPENHANDS WEBAPP =====
# This Dockerfile builds and runs the complete OpenHands application
# including both the React frontend and Python FastAPI backend
# ===== FRONTEND BUILD STAGE =====
FROM node:22.13.1-bookworm-slim AS frontend-builder
WORKDIR /app/frontend
# Copy package files first for better layer caching
COPY frontend/package.json frontend/package-lock.json ./
# Install frontend dependencies
RUN npm ci --only=production
# Copy frontend source code
COPY frontend/ ./
# Build the React application
RUN npm run build
# ===== BACKEND BUILD STAGE =====
FROM python:3.12.8-slim AS backend-builder
WORKDIR /app
# Set Poetry environment variables
ENV POETRY_NO_INTERACTION=1 \
POETRY_VIRTUALENVS_IN_PROJECT=1 \
POETRY_VIRTUALENVS_CREATE=1 \
POETRY_CACHE_DIR=/tmp/poetry_cache
# Install system dependencies for building Python packages
RUN apt-get update -y \
&& apt-get install -y --no-install-recommends \
curl \
make \
git \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# Install Poetry
RUN python3 -m pip install poetry==1.8.2 --break-system-packages
# Copy Python dependency files first for better layer caching
COPY pyproject.toml poetry.lock ./
RUN touch README.md
# Install Python dependencies
RUN poetry install --no-root --no-dev && rm -rf $POETRY_CACHE_DIR
# ===== FINAL RUNTIME STAGE =====
FROM python:3.12.8-slim AS runtime
WORKDIR /app
# Build arguments
ARG OPENHANDS_BUILD_VERSION=dev
# Environment variables for OpenHands
ENV RUN_AS_OPENHANDS=true \
OPENHANDS_USER_ID=42420 \
SANDBOX_LOCAL_RUNTIME_URL=http://host.docker.internal \
USE_HOST_NETWORK=false \
WORKSPACE_BASE=/opt/workspace_base \
OPENHANDS_BUILD_VERSION=$OPENHANDS_BUILD_VERSION \
SANDBOX_USER_ID=0 \
FILE_STORE=local \
FILE_STORE_PATH=/.openhands-state \
PYTHONPATH='/app' \
VIRTUAL_ENV=/app/.venv \
PATH="/app/.venv/bin:$PATH"
# Create necessary directories
RUN mkdir -p $FILE_STORE_PATH $WORKSPACE_BASE
# Install runtime system dependencies
RUN apt-get update -y \
&& apt-get install -y --no-install-recommends \
curl \
ssh \
sudo \
git \
&& rm -rf /var/lib/apt/lists/*
# Configure user management for different UID ranges
RUN sed -i 's/^UID_MIN.*/UID_MIN 499/' /etc/login.defs \
&& sed -i 's/^UID_MAX.*/UID_MAX 1000000/' /etc/login.defs
# Create app group and openhands user
RUN groupadd app \
&& useradd -l -m -u $OPENHANDS_USER_ID -s /bin/bash openhands \
&& usermod -aG app openhands \
&& usermod -aG sudo openhands \
&& echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
# Set ownership and permissions
RUN chown -R openhands:app /app && chmod -R 770 /app \
&& chown -R openhands:app $WORKSPACE_BASE && chmod -R 770 $WORKSPACE_BASE
# Switch to openhands user for application setup
USER openhands
# Copy Python virtual environment from builder stage
COPY --chown=openhands:app --chmod=770 --from=backend-builder /app/.venv /app/.venv
# Copy Python application code
COPY --chown=openhands:app --chmod=770 ./microagents ./microagents
COPY --chown=openhands:app --chmod=770 ./openhands ./openhands
COPY --chown=openhands:app --chmod=777 ./openhands/runtime/plugins ./openhands/runtime/plugins
COPY --chown=openhands:app --chmod=770 ./openhands/agenthub ./openhands/agenthub
# Copy configuration and metadata files
COPY --chown=openhands:app ./pyproject.toml ./poetry.lock ./README.md ./MANIFEST.in ./LICENSE ./
# Download assets (run as openhands user to set correct ownership)
RUN python openhands/core/download.py
# Copy built frontend from frontend-builder stage
COPY --chown=openhands:app --chmod=770 --from=frontend-builder /app/frontend/build ./frontend/build
# Copy entrypoint script
COPY --chown=openhands:app --chmod=770 ./containers/app/entrypoint.sh /app/entrypoint.sh
# Ensure all files are in the app group
RUN find /app \! -group app -exec chgrp app {} + 2>/dev/null || true
# Switch back to root for entrypoint execution
USER root
# Health check to ensure the application is running
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD curl -f http://localhost:3000/ || exit 1
# Expose the application port
EXPOSE 3000
# Set entrypoint and default command
ENTRYPOINT ["/app/entrypoint.sh"]
CMD ["uvicorn", "openhands.server.listen:app", "--host", "0.0.0.0", "--port", "3000"]