# Copyright (c) Meta Platforms, Inc. and affiliates. # All rights reserved. # # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. # Multi-stage build using openenv-base # This Dockerfile is flexible and works for both: # - In-repo environments (with local src/core) # - Standalone environments (with openenv-core from pip) # The build script (openenv build) handles context detection and sets appropriate build args. ARG BASE_IMAGE=ghcr.io/meta-pytorch/openenv-base:latest FROM ${BASE_IMAGE} AS builder WORKDIR /app # Build argument to control whether we're building standalone or in-repo ARG BUILD_MODE=in-repo # Copy environment code (always at root of build context) COPY . /app/env # For in-repo builds, openenv-core is already in the pyproject.toml dependencies # For standalone builds, openenv-core will be installed from pip via pyproject.toml WORKDIR /app/env # Ensure uv is available (for local builds where base image lacks it) RUN if ! command -v uv >/dev/null 2>&1; then \ curl -LsSf https://astral.sh/uv/install.sh | sh && \ mv /root/.local/bin/uv /usr/local/bin/uv && \ mv /root/.local/bin/uvx /usr/local/bin/uvx; \ fi # Install git and system dependencies for Playwright browsers RUN apt-get update && apt-get install -y --no-install-recommends \ git \ wget \ curl \ # Playwright browser dependencies libnss3 \ libnspr4 \ libatk1.0-0 \ libatk-bridge2.0-0 \ libcups2 \ libdrm2 \ libdbus-1-3 \ libxkbcommon0 \ libatspi2.0-0 \ libxcomposite1 \ libxdamage1 \ libxfixes3 \ libxrandr2 \ libgbm1 \ libpango-1.0-0 \ libcairo2 \ libasound2 \ libxshmfence1 \ fonts-unifont \ fonts-noto-color-emoji \ && rm -rf /var/lib/apt/lists/* # Install dependencies using uv sync # First pass: install dependencies without the project (for better caching) # Second pass: install the project itself RUN --mount=type=cache,target=/root/.cache/uv \ if [ -f uv.lock ]; then \ uv sync --frozen --no-install-project --no-editable; \ else \ uv sync --no-install-project --no-editable; \ fi RUN --mount=type=cache,target=/root/.cache/uv \ if [ -f uv.lock ]; then \ uv sync --frozen --no-editable; \ else \ uv sync --no-editable; \ fi # Install Playwright browsers (Chromium by default) RUN .venv/bin/python -m playwright install chromium # Install MiniWoB++ tasks RUN git clone --depth 1 https://github.com/Farama-Foundation/miniwob-plusplus.git /app/miniwob-plusplus # Final runtime stage FROM ${BASE_IMAGE} WORKDIR /app # Install runtime system libraries for Playwright RUN apt-get update && apt-get install -y --no-install-recommends \ libnss3 \ libnspr4 \ libatk1.0-0 \ libatk-bridge2.0-0 \ libcups2 \ libdrm2 \ libdbus-1-3 \ libxkbcommon0 \ libatspi2.0-0 \ libxcomposite1 \ libxdamage1 \ libxfixes3 \ libxrandr2 \ libgbm1 \ libpango-1.0-0 \ libcairo2 \ libasound2 \ libxshmfence1 \ fonts-unifont \ fonts-noto-color-emoji \ && rm -rf /var/lib/apt/lists/* # Copy the virtual environment from builder COPY --from=builder /app/env/.venv /app/.venv # Copy the environment code COPY --from=builder /app/env /app/env # Copy MiniWoB++ tasks COPY --from=builder /app/miniwob-plusplus /app/miniwob-plusplus # Copy Playwright browsers from builder COPY --from=builder /root/.cache/ms-playwright /root/.cache/ms-playwright # Set PATH to use the virtual environment ENV PATH="/app/.venv/bin:$PATH" # Set PYTHONPATH so imports work correctly ENV PYTHONPATH="/app/env:$PYTHONPATH" # Set environment variables ENV PYTHONUNBUFFERED=1 ENV BROWSERGYM_BENCHMARK=miniwob ENV BROWSERGYM_TASK_NAME="click-test" ENV BROWSERGYM_HEADLESS=true ENV BROWSERGYM_VIEWPORT_WIDTH=1280 ENV BROWSERGYM_VIEWPORT_HEIGHT=720 ENV BROWSERGYM_TIMEOUT=10000 ENV BROWSERGYM_PORT=8000 ENV MINIWOB_HTML_DIR=/app/miniwob-plusplus/miniwob/html ENV MINIWOB_HTTP_PORT=8888 ENV MINIWOB_URL=http://127.0.0.1:8888/miniwob/ ENV ENABLE_WEB_INTERFACE=true # Expose ports EXPOSE 8000 EXPOSE 8888 # Health check using Python (more portable than curl/wget) HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1 # Run the server using start script or directly CMD ["sh", "-c", "cd /app/env && if [ -f server/start.sh ]; then chmod +x server/start.sh && ./server/start.sh; else uvicorn server.app:app --host 0.0.0.0 --port 8000; fi"]