A veces resulta útil trabajar con Selenium en Python dentro de un contenedor Docker. Esto plantea preguntas sobre los beneficios de esta práctica, la compatibilidad entre ChromeDriver y Chromium, y las particularidades de su implementación. En este artículo abordaremos los puntos clave y ofreceremos soluciones a los problemas más comunes.
Ejecutar Selenium dentro de un contenedor ofrece varias ventajas:
🧩 Portabilidad – Permite trasladar fácilmente el entorno entre diferentes máquinas, evitando conflictos de versiones y dependencias específicas del sistema operativo.
🧱 Aislamiento – El contenedor Selenium puede actualizarse o reemplazarse rápidamente sin afectar otros componentes del servidor.
Antes de comenzar, asegúrate de que Docker y Docker Compose estén instalados:
docker --version && docker compose version
💡 En algunas versiones, el comando se escribe docker-compose (con guion) en lugar de docker compose.
Si las herramientas están instaladas, verás sus versiones. Si no, instálalas antes de continuar.
Al implementar Selenium dentro de contenedores Docker, considera los siguientes aspectos:
la arquitectura del host,
los requisitos funcionales,
y el rendimiento esperado.
Las imágenes oficiales selenium/standalone-* están diseñadas para CPUs AMD64 (x86_64), mientras que seleniarm/standalone-* están adaptadas para arquitecturas ARM (como Apple Silicon o servidores ARM64).
Crea un archivo docker-compose.yml en la raíz del proyecto:
version: "3"
services:
app:
build: .
restart: always
volumes:
- .:/app
depends_on:
- selenium
platform: linux/amd64
selenium:
image: selenium/standalone-chromium:latest # For AMD64
# image: seleniarm/standalone-chromium:latest # For ARM64
container_name: selenium-container
restart: unless-stopped
shm_size: 2g
ports:
- "4444:4444" # Selenium WebDriver API
- "7900:7900" # VNC Viewer
environment:
- SE_NODE_MAX_SESSIONS=1
- SE_NODE_OVERRIDE_MAX_SESSIONS=true
- SE_NODE_SESSION_TIMEOUT=300
- SE_NODE_GRID_URL=http://localhost:4444
- SE_NODE_DETECT_DRIVERS=false
Selecciona la imagen adecuada para tu sistema descomentando la línea correspondiente. El servicio app ejecutará tu código principal en Python.
A continuación, define el servicio en un Dockerfile:
# Use a minimal Python image
FROM python:3.11-slim
# Set working directory
WORKDIR /app
# Install Python dependencies
COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt
# Copy project files
COPY . /app/
# Set environment variables (Chromium is in a separate container)
ENV SELENIUM_REMOTE_URL="http://selenium:4444/wd/hub"
# Run Python script
CMD ["python", "main.py"]
Este Dockerfile usa una imagen ligera de Python e instala automáticamente las dependencias necesarias.
Script principal (main.py)
import time # Used to create a delay for checking browser functionality
import os
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
# WebDriver settings
chrome_options = Options()
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--disable-webrtc")
chrome_options.add_argument("--hide-scrollbars")
chrome_options.add_argument("--disable-notifications")
chrome_options.add_argument("--start-maximized")
SELENIUM_REMOTE_URL = os.getenv("SELENIUM_REMOTE_URL", "http://selenium:4444/wd/hub")
driver = webdriver.Remote(
command_executor=SELENIUM_REMOTE_URL,
options=chrome_options
)
# Open a test page
driver.get("https://www.hostman.com")
time.sleep(9999)
# Shut down WebDriver
driver.quit()
requirements.txt
attrs==25.1.0
certifi==2025.1.31
h11==0.14.0
idna==3.10
outcome==1.3.0.post0
PySocks==1.7.1
selenium==4.28.1
sniffio==1.3.1
sortedcontainers==2.4.0
trio==0.28.0
trio-websocket==0.11.1
typing_extensions==4.12.2
urllib3==2.3.0
websocket-client==1.8.0
wsproto==1.2.0
Ejecuta los contenedores con:
docker compose up -d
Docker construirá las imágenes y las iniciará en segundo plano.
Comprueba el estado con:
docker compose ps
Si aparecen dos contenedores en ejecución, todo está funcionando correctamente. Ya puedes interactuar con sitios web usando Selenium.
En las imágenes oficiales de Selenium (como selenium/standalone-chrome o seleniarm/standalone-chromium), el acceso directo al Chrome DevTools Protocol (CDP) está gestionado por Selenium Grid. Cada sesión genera un nuevo puerto WebSocket, lo que impide el acceso directo desde fuera del contenedor.
Parámetros como --remote-debugging-port=9229 son ignorados o sobrescritos. En su lugar, estas imágenes incluyen VNC (Virtual Network Computing) integrado, similar a TeamViewer o AnyDesk.
⚠️ El modo headless debe estar desactivado, ya que VNC transmite la pantalla real, y si no hay interfaz visible, no se mostrará nada.
Accede a la interfaz web de VNC en:
http://<server_ip>:7900
Al conectar, se te pedirá una contraseña. Para generarla, accede al contenedor Selenium:
docker exec -it selenium-container bash
x11vnc -storepasswd
Introduce y confirma la contraseña. Luego, ingrésala en la interfaz web de VNC para acceder al navegador controlado por Selenium dentro del contenedor. Desde ahí puedes abrir DevTools, inspeccionar el DOM o depurar solicitudes de red.
Ejecutar Selenium dentro de contenedores Docker simplifica la portabilidad del entorno y elimina conflictos de versiones. Además, permite realizar depuración visual mediante VNC cuando sea necesario.
Solo asegúrate de:
elegir la imagen correcta para tu arquitectura (AMD64 o ARM64),
y desactivar el modo headless si necesitas una interfaz gráfica.
Esta configuración ofrece una infraestructura de pruebas flexible, estable y perfectamente integrada en pipelines de CI/CD.