Dockerfile 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. ARG OPENHANDS_BUILD_VERSION=dev
  2. FROM node:21.7.2-bookworm-slim AS frontend-builder
  3. WORKDIR /app
  4. COPY ./frontend/package.json frontend/package-lock.json ./
  5. RUN npm install -g npm@10.5.1
  6. RUN npm ci
  7. COPY ./frontend ./
  8. RUN npm run build
  9. FROM python:3.12.3-slim AS backend-builder
  10. WORKDIR /app
  11. ENV PYTHONPATH='/app'
  12. ENV POETRY_NO_INTERACTION=1 \
  13. POETRY_VIRTUALENVS_IN_PROJECT=1 \
  14. POETRY_VIRTUALENVS_CREATE=1 \
  15. POETRY_CACHE_DIR=/tmp/poetry_cache
  16. RUN apt-get update -y \
  17. && apt-get install -y curl make git build-essential \
  18. && python3 -m pip install poetry==1.8.2 --break-system-packages
  19. COPY ./pyproject.toml ./poetry.lock ./
  20. RUN touch README.md
  21. RUN export POETRY_CACHE_DIR && poetry install --without evaluation,llama-index --no-root && rm -rf $POETRY_CACHE_DIR
  22. FROM python:3.12.3-slim AS openhands-app
  23. WORKDIR /app
  24. ARG OPENHANDS_BUILD_VERSION #re-declare for this section
  25. ENV RUN_AS_OPENHANDS=true
  26. # A random number--we need this to be different from the user's UID on the host machine
  27. ENV OPENHANDS_USER_ID=42420
  28. ENV SANDBOX_LOCAL_RUNTIME_URL=http://host.docker.internal
  29. ENV USE_HOST_NETWORK=false
  30. ENV WORKSPACE_BASE=/opt/workspace_base
  31. ENV OPENHANDS_BUILD_VERSION=$OPENHANDS_BUILD_VERSION
  32. ENV SANDBOX_USER_ID=0
  33. ENV FILE_STORE=local
  34. ENV FILE_STORE_PATH=/.openhands-state
  35. RUN mkdir -p $FILE_STORE_PATH
  36. RUN mkdir -p $WORKSPACE_BASE
  37. RUN apt-get update -y \
  38. && apt-get install -y curl ssh sudo
  39. # Default is 1000, but OSX is often 501
  40. RUN sed -i 's/^UID_MIN.*/UID_MIN 499/' /etc/login.defs
  41. # Default is 60000, but we've seen up to 200000
  42. RUN sed -i 's/^UID_MAX.*/UID_MAX 1000000/' /etc/login.defs
  43. RUN groupadd app
  44. RUN useradd -l -m -u $OPENHANDS_USER_ID -s /bin/bash openhands && \
  45. usermod -aG app openhands && \
  46. usermod -aG sudo openhands && \
  47. echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
  48. RUN chown -R openhands:app /app && chmod -R 770 /app
  49. RUN sudo chown -R openhands:app $WORKSPACE_BASE && sudo chmod -R 770 $WORKSPACE_BASE
  50. USER openhands
  51. ENV VIRTUAL_ENV=/app/.venv \
  52. PATH="/app/.venv/bin:$PATH" \
  53. PYTHONPATH='/app'
  54. COPY --chown=openhands:app --chmod=770 --from=backend-builder ${VIRTUAL_ENV} ${VIRTUAL_ENV}
  55. RUN playwright install --with-deps chromium
  56. COPY --chown=openhands:app --chmod=770 ./openhands ./openhands
  57. COPY --chown=openhands:app --chmod=777 ./openhands/runtime/plugins ./openhands/runtime/plugins
  58. COPY --chown=openhands:app --chmod=770 ./openhands/agenthub ./openhands/agenthub
  59. COPY --chown=openhands:app ./pyproject.toml ./pyproject.toml
  60. COPY --chown=openhands:app ./poetry.lock ./poetry.lock
  61. COPY --chown=openhands:app ./README.md ./README.md
  62. COPY --chown=openhands:app ./MANIFEST.in ./MANIFEST.in
  63. COPY --chown=openhands:app ./LICENSE ./LICENSE
  64. # This is run as "openhands" user, and will create __pycache__ with openhands:openhands ownership
  65. RUN python openhands/core/download.py # No-op to download assets
  66. # Add this line to set group ownership of all files/directories not already in "app" group
  67. # openhands:openhands -> openhands:app
  68. RUN find /app \! -group app -exec chgrp app {} +
  69. COPY --chown=openhands:app --chmod=770 --from=frontend-builder /app/build ./frontend/build
  70. COPY --chown=openhands:app --chmod=770 ./containers/app/entrypoint.sh /app/entrypoint.sh
  71. USER root
  72. WORKDIR /app
  73. ENTRYPOINT ["/app/entrypoint.sh"]
  74. CMD ["uvicorn", "openhands.server.listen:app", "--host", "0.0.0.0", "--port", "3000"]