Databricks Tips #7: Docker en Databricks — contenedores custom para entornos que no se rompen

Databricks Tips
Data Engineering
Delta Lake
Databricks Container Services, imágenes custom, golden containers, CI/CD con Docker y los errores que te van a hacer perder horas.
Autor
Publicado

30 de mayo de 2026

Laboratorio práctico — Dockerfile + notebook para probar DCS en Databricks Free Edition.


Séptima entrega de Databricks Tips. Sí, Databricks Runtime ya te da un entorno curado con Spark, pandas, MLflow y todo lo estándar pre-instalado. Entonces, ¿para qué Docker? El problema aparece cuando necesitás algo que el runtime no trae: librerías de sistema como GDAL o compiladores de C, versiones específicas que chocan con las del runtime, o un entorno bloqueado que no cambie entre releases de DBR. Ahí es donde Databricks Container Services entra en juego.

Docker en 2 minutos (para los que nunca lo usaron)

Si ya sabés qué es Docker, saltá a la siguiente sección. Si no, acá va la versión corta.

Imaginate que tenés una receta de cocina. Podés darle la receta a alguien y esperar que tenga los mismos ingredientes, el mismo horno y la misma temperatura… o podés darle la cocina entera empaquetada con todo adentro. Docker es eso: empaquetás tu código + dependencias + configuración en una imagen que corre igual en cualquier máquina.

Sin Docker cada máquina tiene versiones distintas; con Docker, misma imagen y mismo resultado en todos los entornos.

Sin Docker cada máquina tiene versiones distintas; con Docker, misma imagen y mismo resultado en todos los entornos.

Los conceptos clave:

  • Imagen: el paquete con todo adentro (OS + librerías + config). Se construye con un Dockerfile.
  • Container: una instancia corriendo de esa imagen. Podés tener muchos containers de la misma imagen.
  • Registry: donde guardás las imágenes (Docker Hub, Amazon ECR, Azure ACR). Es como un “GitHub para imágenes Docker”.
  • Dockerfile: la receta para construir la imagen. Cada línea RUN agrega algo al entorno.
Listado 1: Dockerfile básico: imagen base, dependencias y código
# Ejemplo básico de Dockerfile
FROM python:3.11-slim          # Partís de una imagen base
RUN pip install pandas==2.2.3  # Instalás dependencias
COPY mi_script.py /app/        # Copiás tu código

Eso es todo lo que necesitás saber para entender el resto del post.

Qué es Databricks Container Services (DCS)

En vez de usar el runtime por defecto, DCS te permite arrancar tu compute con una imagen Docker propia. Vos definís las dependencias exactas, las bakeás en la imagen, y Databricks la usa como entorno de ejecución.

Pero ojo: vos no metés Spark en la imagen. Lo que pasa internamente cuando lanzás un cluster con DCS es esto (fuente):

  1. Se adquieren VMs del cloud provider
  2. Se descarga tu imagen Docker del registry
  3. Databricks crea un contenedor a partir de tu imagen
  4. El código del Databricks Runtime (Spark, JVM, dbutils) se copia dentro del contenedor
  5. Se ejecutan los init scripts (si hay)

Es decir, Databricks inyecta Spark en tu contenedor al arrancar. Por eso ignora CMD y ENTRYPOINT — necesita controlar el proceso de inicio. Vos solo ponés las dependencias, ellos ponen el runtime.

Flujo de Databricks Container Services: build de la imagen, push al registry, configuración del cluster y launch.

Flujo de Databricks Container Services: build de la imagen, push al registry, configuración del cluster y launch.

Lo nuevo (2025-2026): DCS ahora soporta Standard Compute (shared clusters con aislamiento). Antes solo funcionaba en Dedicated Compute. Esto cambia todo, porque ahora podés tener un entorno Docker compartido sin necesidad de un cluster por persona.

0. Habilitar DCS (prerequisito)

Antes de hacer cualquier cosa, un workspace admin tiene que habilitar Container Services. Si no lo hacés, el tab Docker no aparece al crear compute.

En AWS: Settings → Advanced → Container Services → Enabled.

En Azure (no hay toggle en la UI): se hace por CLI:

Listado 2: Habilitar y verificar DCS en Azure vía Databricks CLI
# Habilitar DCS en Azure Databricks
databricks workspace-conf set-status --json '{"enableDcs": "true"}' --profile <tu-profile>

# Verificar que quedó habilitado (tiene que devolver "true")
databricks workspace-conf get-status enableDcs --profile <tu-profile>
# Respuesta esperada:
# {
#   "enableDcs": "true"
# }

El set-status no devuelve output si funciona — eso es normal. Verificá siempre con el get-status.

Para Standard Compute (Beta): además del paso anterior, ir a Settings → Previews → activar “DCS for Standard Compute”.

Importante: después de habilitar, el tab Docker solo aparece si elegís un access mode compatible:

  • Single User o No Isolation Shared → aparece el tab Docker
  • Shared o Standard → no aparece (salvo la beta con DBR 18.3+)
  • Serverless → no soportado

Si habilitaste todo y seguís sin ver el tab, verificá que tu workspace sea Premium tier.

1. El golden container: inmutabilidad en producción

El caso de uso más potente de DCS es el golden container: una imagen Docker que pasa CI/CD, se escanea por seguridad, y se deploya como el único entorno autorizado para producción.

Listado 3: Golden container: dependencias fijas y librerías de sistema
# golden.Dockerfile
FROM databricksruntime/standard:16.4-LTS

# Dependencias fijas — NUNCA usar pip install sin versiones
RUN /databricks/python3/bin/pip install --no-cache-dir \
    pandas==2.2.3 \
    scikit-learn==1.5.2 \
    great-expectations==1.3.0 \
    delta-spark==3.3.0

# Librerías de sistema que pip no puede instalar
RUN apt-get update && apt-get install -y --no-install-recommends \
    libgdal-dev \
    libgeos-dev \
    && rm -rf /var/lib/apt/lists/*
Listado 4: Build y push de la imagen golden al registry
# Build + push
docker build -f golden.Dockerfile -t mi-ecr.amazonaws.com/dbx-golden:v2.1.0 .
docker push mi-ecr.amazonaws.com/dbx-golden:v2.1.0

La regla de oro: nunca uses tags :latest en producción. Siempre versioná tus imágenes. Si alguien pushea un :latest nuevo y tu cluster se reinicia, tu job se rompe.

2. Configurar el cluster con Docker

Hay dos formas: UI y API/CLI.

Desde la UI:

  1. Crear nuevo compute → Advanced Options → Docker tab
  2. Seleccionar “Use your own Docker container”
  3. Ingresar la URL de la imagen
  4. Configurar autenticación (si tu registry es privado)

Desde la API (para automatizar):

El endpoint es POST /api/2.0/clusters/create (referencia):

Listado 5: Crear cluster con imagen Docker vía REST API
curl -X POST "https://<tu-workspace>.cloud.databricks.com/api/2.0/clusters/create" \
  -H "Authorization: Bearer $DATABRICKS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "cluster_name": "prod-golden-container",
    "spark_version": "16.4.x-scala2.12",
    "docker_image": {
      "url": "mi-ecr.amazonaws.com/dbx-golden:v2.1.0",
      "basic_auth": {
        "username": "{{secrets/docker/user}}",
        "password": "{{secrets/docker/pass}}"
      }
    },
    "node_type_id": "i3.xlarge",
    "autoscale": {
      "min_workers": 1,
      "max_workers": 4
    }
  }'

O con la Databricks CLI:

Listado 6: Crear cluster con imagen Docker vía Databricks CLI
databricks clusters create --json '{
  "cluster_name": "prod-golden-container",
  "spark_version": "16.4.x-scala2.12",
  "docker_image": {
    "url": "mi-ecr.amazonaws.com/dbx-golden:v2.1.0",
    "basic_auth": {
      "username": "{{secrets/docker/user}}",
      "password": "{{secrets/docker/pass}}"
    }
  },
  "node_type_id": "i3.xlarge",
  "autoscale": {
    "min_workers": 1,
    "max_workers": 4
  }
}'

Tip: usá Databricks Secrets para las credenciales del registry. Nunca hardcodees usuarios y passwords en la config del cluster.

3. Dedicated vs Standard Compute: cuándo usar cada uno

Con la llegada de DCS para Standard Compute, ahora tenés dos opciones:

Dedicated Compute Standard Compute (Beta)
Imagen base databricksruntime/standard:16.x databricksruntime/environment:v5-standard
DBR mínimo Varía 18.3+
Init scripts Modifican Python NO modifican Python
Instancias ARM No soportado Soportado (Graviton)
Aislamiento Single user / No isolation Standard (con aislamiento)
Libraries UI Soportado No soportado

Mi recomendación:

  • Usá Dedicated si necesitás init scripts que modifiquen el entorno Python o si tu DBR es anterior a 18.3.
  • Usá Standard si querés compartir un cluster entre varios usuarios con entorno Docker unificado.

4. El error más común: instalar paquetes en el path equivocado

Esto te va a pasar, te lo garantizo. Construís tu imagen, todo verde en local, lanzás el cluster y… tus notebooks no encuentran las librerías.

Listado 7: Error frecuente: instalar paquetes en el path correcto
# MALO — instala en el Python del sistema
RUN pip install pandas==2.2.3

# MALO — crea un virtualenv separado
RUN python -m venv /opt/myenv && /opt/myenv/bin/pip install pandas==2.2.3

# BIEN — usa el Python de Databricks
RUN /databricks/python3/bin/pip install pandas==2.2.3

Los notebooks y jobs de Databricks usan /databricks/python3 como intérprete. Si instalás paquetes en otro path, no los van a encontrar.

5. Caso de uso real: pipeline geoespacial con GDAL + Prophet

Donde DCS se vuelve indispensable es cuando necesitás librerías de sistema que no se pueden instalar con pip. Un ejemplo real: un pipeline que cruza datos de delivery con geometrías de zonas y predice demanda por área.

El Dockerfile para este caso:

Listado 8: Dockerfile geoespacial: GDAL, GeoPandas y Prophet
FROM databricksruntime/standard:16.4-LTS

# Librerías de sistema para geoespacial
RUN apt-get update && apt-get install -y --no-install-recommends \
    libgdal-dev \
    libgeos-dev \
    libproj-dev \
    gdal-bin \
    && rm -rf /var/lib/apt/lists/*

# Stack geoespacial + forecasting
RUN /databricks/python3/bin/pip install --no-cache-dir \
    geopandas==1.0.1 \
    shapely==2.0.6 \
    fiona==1.10.1 \
    prophet==1.1.6 \
    pystan==3.10.0

# Validar que GDAL se linkea bien (esto falla silenciosamente si no)
RUN /databricks/python3/bin/python -c "from osgeo import gdal; print(f'GDAL {gdal.__version__}')"

Sin Docker, este setup requiere un init script de ~40 líneas que instala apt packages + compila dependencias de C. Tarda ~8 minutos en cada arranque del cluster y falla 1 de cada 5 veces por timeouts de apt-get. Con Docker, las dependencias ya están bakeadas: el cluster arranca en ~2 minutos y nunca falla por dependencias.

El notebook queda limpio:

Listado 9: Pipeline geoespacial: forecast de demanda por zona con Prophet
# El notebook solo tiene lógica de negocio — cero setup
import geopandas as gpd
from prophet import Prophet

# Leer zonas de delivery desde Unity Catalog
zonas = spark.table("prod.geo.zonas_delivery").toPandas()
geo_zonas = gpd.GeoDataFrame(zonas, geometry=gpd.points_from_xy(zonas.lng, zonas.lat))

# Forecast por zona
for zona_id in geo_zonas["zona_id"].unique():
    historico = spark.table("prod.demand.historico") \
        .filter(f"zona_id = '{zona_id}'") \
        .select("ds", "y").toPandas()

    modelo = Prophet(yearly_seasonality=True, weekly_seasonality=True)
    modelo.fit(historico)
    futuro = modelo.make_future_dataframe(periods=30)
    forecast = modelo.predict(futuro)

    # Guardar predicciones como Delta table
    spark.createDataFrame(forecast[["ds", "yhat", "yhat_lower", "yhat_upper"]]) \
        .withColumn("zona_id", lit(zona_id)) \
        .write.mode("append") \
        .saveAsTable("prod.demand.forecast_por_zona")

6. CI/CD: Docker como pieza central del deploy

Donde DCS realmente brilla es cuando lo integrás con tu pipeline de CI/CD. En vez de instalar dependencias en cada arranque (init scripts), las bakeás en la imagen y las testeás antes de llegar a producción:

Listado 10: GitHub Actions: CI/CD para build, test y push del golden container
# .github/workflows/docker-dbx.yml
name: Build & Push Golden Container

on:
  push:
    paths:
      - 'docker/golden.Dockerfile'
      - 'docker/requirements.txt'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        run: |
          docker build -f docker/golden.Dockerfile \
            -t ${{ secrets.ECR_REGISTRY }}/dbx-golden:${{ github.sha }} .

      - name: Test — verificar que los imports funcionan
        run: |
          docker run --rm ${{ secrets.ECR_REGISTRY }}/dbx-golden:${{ github.sha }} \
            /databricks/python3/bin/python -c "
              import pandas; import sklearn; import great_expectations
              print('All imports OK')
            "

      - name: Push to ECR
        run: |
          aws ecr get-login-password | docker login --username AWS --password-stdin ${{ secrets.ECR_REGISTRY }}
          docker push ${{ secrets.ECR_REGISTRY }}/dbx-golden:${{ github.sha }}

      - name: Tag como latest-stable
        run: |
          docker tag ${{ secrets.ECR_REGISTRY }}/dbx-golden:${{ github.sha }} \
                     ${{ secrets.ECR_REGISTRY }}/dbx-golden:latest-stable
          docker push ${{ secrets.ECR_REGISTRY }}/dbx-golden:latest-stable

7. Gotchas que te van a hacer perder horas

Acá van las trampas que nadie te cuenta en la documentación:

Docker Hub rate limits: si lanzás muchos clusters en poco tiempo (autoescalado agresivo, pools grandes), Docker Hub te va a bloquear. Solución: usá un registry en la misma región y cloud que tu workspace (ECR en AWS, ACR en Azure).

Init scripts en Standard Compute: en Dedicated, los init scripts pueden instalar paquetes Python. En Standard, no. Todo tiene que estar en la imagen Docker. Si venís de usar init scripts para dependencias, tenés que migrar todo al Dockerfile.

Instrucciones de Docker ignoradas: Databricks ignora CMD, ENTRYPOINT, USER, EXPOSE y HEALTHCHECK. No perdás tiempo configurándolas.

No hay DBR for ML: DCS no es compatible con Databricks Runtime for Machine Learning. Si necesitás TensorFlow o PyTorch con GPU, tenés que instalarlos vos en la imagen, incluyendo CUDA y cuDNN.

El tab Docker no aparece: verificá tres cosas: (1) que DCS esté habilitado (en Azure solo por CLI), (2) que el access mode sea Single User o No Isolation Shared, y (3) que tu workspace sea Premium tier. Si falta alguno de los tres, el tab no aparece y no te dice por qué.

8. Cuándo NO usar Docker en Databricks

DCS no es para todos. No lo uses si:

  • Tu equipo es chico y las dependencias son simples (un requirements.txt con 5 librerías)
  • No tenés un pipeline de CI/CD para construir y testear imágenes
  • Necesitás instalar librerías rápidamente para experimentar (los init scripts o las cluster libraries son más ágiles para exploración)
  • Usás Databricks Runtime for ML y no querés reconstruir todo el stack de GPU

Usalo cuando:

  • Necesitás reproducibilidad garantizada entre ambientes (dev/staging/prod usan la misma imagen)
  • Tenés dependencias de sistema (apt packages, librerías C) que no se pueden instalar con pip
  • Querés un entorno bloqueado y aprobado por seguridad
  • Tu equipo es grande y los init scripts se volvieron inmantenibles

Checklist de DCS

Paso Pregunta Si no lo hacés…
Habilitación DCS está habilitado en tu workspace? (CLI en Azure) El tab Docker no aparece
Access mode Estás usando Single User o No Isolation Shared? El tab Docker no aparece
Imagen base Estás extendiendo la imagen oficial de Databricks? Posibles incompatibilidades con el runtime
Path de Python Instalás en /databricks/python3? Notebooks no encuentran tus libs
Versionado Usás tags con versión (no :latest)? Builds no reproducibles
Registry Tu registry está en la misma región/cloud? Arranques lentos + rate limits
CI/CD Testeás los imports antes de pushear? Clusters que arrancan pero fallan al ejecutar
Secrets Las credenciales del registry están en Databricks Secrets? Credenciales expuestas en config

Referencias

Otros posts de la serie

Si te sirvió este post, mirá los anteriores de Databricks Tips:


Próxima semana: Lakeflow Declarative Pipelines (ex-DLT) — expectations, materialized views y serverless compute.