The AI Compute Platform for frontier teams. SkyPilot turns fragmented AI compute into one AI supercomputer, so frontier AI teams build custom intelligence...
docker pull skypilot-org/skypilot:latest
docker run -d --name skypilot --restart always skypilot-org/skypilot:latest
podman run -d --name skypilot --restart always skypilot-org/skypilot:latest
skopeo inspect docker://docker.io/skypilot-org/skypilot:latest
oras pull skypilot-org/skypilot:latest
# 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