Estoy trabajando en una herramienta DevOps enfocada al despliegue eficiente y simple de Odoo en producción y desarrollo. Como framework general para interactuar con la misma estoy usando Typer y mi idea inicial era que python fuera llamando los diferentes comandos necesarios usando una mezcla de subprocess y os. Todo iba muy lindo, pero a medida que el proyecto crecía (y sigue creciendo muchísimo) cai que usar subprocess, por ejemplo, para ejecutar un comando dentro de un contenedor, se hacia bastante engorroso, propenso a errores y además se me complicaba el el post procesamiento de las salidas. Y ahí es cuando me pregunté: ¿Existirá algo qué me permita interactuar con docker desde Python? La respuesta es SI y es el SDK oficial de Docker para Python

Instalación#

Suponiendo que ya tengas un ambiente creado y activado, la instalación es muy sencilla:

pip install docker

Código básico#

Voy a tirar algunos tips piolas que pueden servir de puntapié para arrancar usando el SDK. Si necesitan algo mas avanzado o profundizar no hay nada mejor que leer la Documentación.

Listando todos los contenedores#

import docker

client = docker.from_env()
# Traemos absolutamente todos los contenedores 
containers = client.containers.list(all=True) 

Con este código nos vamos a traer una lista con todos los contenedores que estén declarados en nuestra máquina. Se pueden filtrar contenedores usando la opción filter:

import docker

client = docker.from_env()
# Se filtran solo los contenedores levantados mediante docker compose
containers = client.containers.list(
    all=True,
    filters={"label": "com.docker.compose.project"}
)

Cada contenedor será un objeto Contenedor y tendrá sus propiedades y métodos particulares.

Propiedades y métodos de un contenedor#

Explicar absolutamente todo lo que se puede hacer sería una locura, por lo que a modo de ejemplo solo voy a mostrar como parar y volver a iniciar un contenedor, traerme las variables de entorno de un contenedor y ejecutar un comando dentro del mismo.

Parar e iniciar un contenedor#

import docker

client = docker.from_env()
containers = client.containers.list(all=True)
container = containers[0].stop() #Se detiene un contenedor
container = containers[0].start() #Se inicia un contenedor

Obteniendo las variables de entorno#

Voy a tomar el primer contenedor que me salga y vamos a chusmear, por ejemplo, las variables de entorno.

import docker

client = docker.from_env()
containers = client.containers.list(all=True)
env_data = containers[0].attrs["Config"]["Env"] #(En formato string ¡Ojo!)
env_dict = {}
env_dict = dict(item.split("=") for item in env_data) #Acá lo pasamos a formato dict para que sea mas cómodo de trabajar.

Ejecutando un comando dentro de un contenedor#

import docker
## Variables de ejemplo

db_user = "usuario"
db_password = "password"
db = "odoo"

client = docker.from_env()
containers = client.containers.list(all=True)

# Query para botener todos los módulos presentes en una db postgresql de Odoo.
query = "SELECT name, latest_version FROM ir_module_module;"
result = containers[0].exec_run(
    [
                "psql",
                f"postgresql://{db_user}:{db_password}@db:5432/{db}",
                "-t",
                "-A",
                "-F",
                "|",
                "-c",
                query,
            ]
)
output = result[1].decode().strip()

Y hasta acá llega la entrada del día. Si quiero incentivar que, cada vez que puedan y necesiten, prueben el SDK de Docker en Python porque es excelente y se pueden ahorrar mas que un dolor de cabeza administrando contenedores, volúmenes, redes…