# syntax=docker/dockerfile:1 # Stage 1: Install Google Cloud SDK using APT FROM python:3.13.15-slim AS gcloud-apt-install # Keep in sync with _GCLOUD_VERSION in sky/clouds/gcp.py. Pinned so the apt # install layer doesn't bake in a stale version via buildx registry caching # (the RUN command's hash is the cache key, so without a version specifier # the layer is reused indefinitely from whatever apt resolved at first build). # 567.0.0 ships gsutil 5.37, which replaced OpenSSL.crypto.sign with the # cryptography library — required after pyopenssl 24.3 dropped that API (#8070). ARG GCLOUD_VERSION=567.0.0-0 RUN apt-get update && \ apt-get install -y curl gnupg lsb-release && \ echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" > /etc/apt/sources.list.d/google-cloud-sdk.list && \ curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg && \ apt-get update && \ apt-get install --no-install-recommends -y \ google-cloud-cli=${GCLOUD_VERSION} \ google-cloud-cli-gke-gcloud-auth-plugin=${GCLOUD_VERSION} && \ apt-get clean && rm -rf /usr/lib/google-cloud-sdk/platform/bundledpythonunix \ /var/lib/apt/lists/* # Stage 2: Process the source code for INSTALL_FROM_SOURCE FROM python:3.13.15-slim AS process-source # Control installation method - default to install from source ARG INSTALL_FROM_SOURCE=true ARG NEXT_BASE_PATH=/dashboard WORKDIR /skypilot RUN pip install --no-cache-dir setuptools==78.1.1 # Run NPM and node install in a separate step for caching. RUN if [ "$INSTALL_FROM_SOURCE" = "true" ]; then \ echo "Installing NPM and Node.js for dashboard build" && \ apt-get update -y && \ apt-get install --no-install-recommends -y git curl ca-certificates gnupg && \ curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ apt-get install -y nodejs && \ apt-get clean && rm -rf /var/lib/apt/lists/*; \ fi COPY sky/dashboard/package.json sky/dashboard/package-lock.json \ /skypilot/sky/dashboard/ RUN if [ "$INSTALL_FROM_SOURCE" = "true" ]; then \ echo "Installing dashboard dependencies in Stage 2" && \ npm --prefix sky/dashboard ci --no-audit --fund=false; \ fi COPY sky/dashboard /skypilot/sky/dashboard RUN --mount=type=cache,id=dashboard-next-cache,target=/skypilot/sky/dashboard/.next/cache \ if [ "$INSTALL_FROM_SOURCE" = "true" ]; then \ echo "Building dashboard in Stage 2" && \ NEXT_BASE_PATH=${NEXT_BASE_PATH} npm --prefix sky/dashboard run build && \ echo "Cleaning up dashboard build-time dependencies" && \ rm -rf sky/dashboard/node_modules ~/.npm /root/.npm; \ fi COPY . /skypilot RUN cd /skypilot && \ if [ "$INSTALL_FROM_SOURCE" != "true" ]; then \ echo "Removing source code (wheel installation)" && \ # Retain an /skypilot/dist dir to keep compatibility in stage 3. mv /skypilot/dist /dist.backup && cd .. && rm -rf /skypilot && mkdir /skypilot && mv /dist.backup /skypilot/dist; \ else \ echo "Keeping source code and record commit sha (editable installation)" && \ python -c "import setup; setup.replace_commit_hash()" && \ # Remove .git dir to reduce the final image size rm -rf .git; \ fi # Stage 3: Main image FROM python:3.13.15-slim ARG INSTALL_FROM_SOURCE=true # Copy Google Cloud SDK from Stage 1 COPY --from=gcloud-apt-install /usr/lib/google-cloud-sdk /opt/google-cloud-sdk # Set environment variable ENV PATH="/opt/google-cloud-sdk/bin:$PATH" # Detect architecture ARG TARGETARCH # Control Next.js basePath for staging deployments ARG NEXT_BASE_PATH=/dashboard # Install system packages RUN apt-get update -y && \ apt-get upgrade -y && \ apt-get install --no-install-recommends -y \ git gcc rsync sudo patch openssh-server \ pciutils nano fuse socat netcat-openbsd curl tini autossh jq logrotate && \ apt-get clean && rm -rf /var/lib/apt/lists/* # Install the session manager plugin for AWS CLI. RUN ARCH=$(case "${TARGETARCH:-$(uname -m)}" in \ "amd64"|"x86_64") echo "64bit" ;; \ "aarch64") echo "arm64" ;; \ *) echo "${TARGETARCH:-$(uname -m)}" ;; \ esac) && \ echo "Installing session manager plugin for AWS CLI for ${ARCH}" && \ curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_${ARCH}/session-manager-plugin.deb" -o "session-manager-plugin.deb" && \ sudo dpkg -i session-manager-plugin.deb && \ rm session-manager-plugin.deb # Install kubectl based on architecture RUN ARCH=${TARGETARCH:-$(case "$(uname -m)" in \ "x86_64") echo "amd64" ;; \ "aarch64") echo "arm64" ;; \ *) echo "$(uname -m)" ;; \ esac)} && \ curl -LO "https://dl.k8s.io/release/v1.33.7/bin/linux/$ARCH/kubectl" && \ install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl && \ rm kubectl # Install Nebius CLI RUN curl -sSL https://storage.eu-north1.nebius.cloud/cli/install.sh | NEBIUS_INSTALL_FOLDER=/usr/local/bin bash # Install uv RUN curl -LsSf https://astral.sh/uv/install.sh | sh && \ # Cap azure-cli<2.87.0: 2.87.0 pulls the broken azure-mgmt-storage 25.0.0 # (see sky/setup_files/dependencies.py). ~/.local/bin/uv pip install --prerelease allow "azure-cli<2.87.0" --system && \ # Upgrade setuptools in base image to mitigate CVE-2024-6345 ~/.local/bin/uv pip install --system --upgrade setuptools==78.1.1 && \ # Upgrade pip in base image: pip<26.2.2 vendors certifi<2026.10.19, which # bundles compromised emSign root CAs (GHSA-6q48-6c7w-9gw2) ~/.local/bin/uv pip install --system --upgrade "pip>=26.2.2" && \ ~/.local/bin/uv cache clean && \ rm -rf ~/.cache/pip ~/.cache/uv && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* # Add source code COPY --from=process-source /skypilot /skypilot # Install SkyPilot and set up dashboard based on installation method RUN cd /skypilot && \ if [ "$INSTALL_FROM_SOURCE" = "true" ]; then \ echo "Installing from source in editable mode" && \ ~/.local/bin/uv pip install -e ".[all]" --system; \ else \ echo "Installing from wheel file" && \ WHEEL_FILE=$(ls dist/*skypilot*.whl 2>/dev/null | head -1) && \ if [ -z "$WHEEL_FILE" ]; then \ echo "Error: No wheel file found in /skypilot/dist/" && \ ls -la /skypilot/dist/ && \ exit 1; \ fi && \ ~/.local/bin/uv pip install "${WHEEL_FILE}[all]" --system && \ echo "Skipping dashboard build for wheel installation"; \ fi && \ # Cleanup all caches to reduce the image size ~/.local/bin/uv cache clean && \ rm -rf ~/.cache/pip ~/.cache/uv && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* && \ # Remove the empty /skypilot dir for backward compatibility if [ "$INSTALL_FROM_SOURCE" != "true" ]; then \ rm -rf /skypilot; \ fi