# Capability: docker

Operar Docker desde Go y Bash. Cubre: build (`docker_build_image`), run/stop/rm (`docker_run`, `docker_stop_container`, `docker_rm_container`), Docker Compose (`docker_compose_up`, `down`, `restart`, `ps`, remoto via SSH), inspect/logs/exec, networks, volumes, registry push/pull. Pipelines de deploy combinan estas atomicas: `deploy_app`, `dockerize_app`, `docker_compose_remote_deploy`.

## Funciones

| ID | Firma | Que hace |
|---|---|---|
| `assert_docker_container_running_bash_infra` | `assert_docker_container_running(container_name: string) -> void` | Verifica que un contenedor Docker está corriendo. Sale con exit code 1 si no está activo, con mensaje a stderr. |
| `deploy_app_go_infra` | `func DeployApp(appDir string, imageName string, port int, envVars map[string]string) (string, error)` | Orquesta el deploy completo de una app Go en Docker. Pasos: genera Dockerfile, lo escribe a disco, construye la imagen y lanza el contenedor en modo detach con port mapping. Retorna el container ID. |
| `docker_build_image_go_infra` | `func DockerBuildImage(contextDir, tag string, buildArgs map[string]string) (string, error)` | Construye una imagen Docker desde un directorio con Dockerfile. Soporta build args opcionales. Retorna el image ID de la imagen construida. |
| `docker_compose_down_go_infra` | `func DockerComposeDown(composeFile string, removeVolumes bool) (string, error)` | Baja un stack docker-compose desde el archivo dado. Si removeVolumes es true elimina también los volumes declarados (-v). Retorna el stdout del comando. |
| `docker_compose_remote_deploy_bash_infra` | `docker_compose_remote_deploy(host: string, remote_dir: string, branch: string, compose_files: string) -> json` | Despliega un stack Docker Compose en un host remoto via SSH. Verifica conectividad, hace git pull del branch indicado, actualiza imagenes con docker-compose pull y levanta/recrea los servicios modificados con docker-compose up -d. Soporta compose files adicionales. Retorna JSON con status, containers corriendo y duracion. |
| `docker_compose_up_go_infra` | `func DockerComposeUp(composeFile string, detach bool) (string, error)` | Levanta un stack docker-compose desde el archivo dado. Si detach es true ejecuta en background (-d). Retorna el stdout del comando. |
| `docker_container_logs_go_infra` | `func DockerContainerLogs(nameOrID string, tail int) (string, error)` | Obtiene los logs de un contenedor Docker. El parámetro tail limita a las últimas N líneas (0 devuelve todos los logs). |
| `docker_container_running_py_infra` | `docker_container_running(name: str, timeout: float = 5.0) -> bool` | Comprueba si un contenedor Docker existe y está corriendo. True solo si docker inspect retorna State.Running=true. Cualquier fallo (docker ausente, contenedor inexistente, daemon caído, timeout) devuelve False sin excepción. |
| `docker_cp_file_bash_infra` | `docker_cp_file(local_path: string, container_name: string, dest_path: string) -> string` | Copia un archivo local a un contenedor Docker y verifica que el tamaño coincide. Imprime JSON con local_size y remote_size a stdout. Sale con exit code 1 si docker cp falla o los tamaños difieren. |
| `docker_create_network_go_infra` | `func DockerCreateNetwork(name, driver string) (string, error)` | Crea una red Docker con el nombre y driver dados. Si driver está vacío usa bridge por defecto. Devuelve el ID de la red creada. |
| `docker_inspect_container_go_infra` | `func DockerInspectContainer(nameOrID string) (map[string]any, error)` | Devuelve los detalles completos de un contenedor Docker como mapa JSON genérico. Útil para inspeccionar configuración, red, volumes, etc. |
| `docker_list_containers_go_infra` | `func DockerListContainers(all bool) ([]ContainerInfo, error)` | Lista contenedores Docker locales. Si all es true incluye contenedores detenidos. Parsea la salida JSON de docker ps. |
| `docker_list_images_go_infra` | `func DockerListImages() ([]ImageInfo, error)` | Lista las imágenes Docker disponibles localmente. Parsea la salida JSON de docker images. |
| `docker_pull_image_go_infra` | `func DockerPullImage(image string) error` | Descarga una imagen Docker desde el registry remoto (Docker Hub u otro configurado). Acepta formato image:tag. |
| `docker_remove_container_go_infra` | `func DockerRemoveContainer(nameOrID string, force bool) error` | Elimina un contenedor Docker. Con force=true puede eliminar contenedores en ejecución (equivale a docker rm -f). |
| `docker_remove_image_go_infra` | `func DockerRemoveImage(image string, force bool) error` | Elimina una imagen Docker local. Con force=true fuerza la eliminación incluso si hay contenedores que la usan. |
| `docker_remove_network_go_infra` | `func DockerRemoveNetwork(nameOrID string) error` | Elimina una red Docker por nombre o ID. |
| `docker_run_container_go_infra` | `func DockerRunContainer(image string, opts DockerRunOpts) (string, error)` | Ejecuta un contenedor Docker nuevo a partir de una imagen. Soporta puertos, env vars, volumes, network, detach y auto-remove. Devuelve el ID del contenedor. |
| `docker_start_container_go_infra` | `func DockerStartContainer(nameOrID string) error` | Inicia un contenedor Docker existente que está detenido. Recibe nombre o ID del contenedor. |
| `docker_stop_container_go_infra` | `func DockerStopContainer(nameOrID string, timeoutSecs int) error` | Detiene un contenedor Docker en ejecución. timeoutSecs controla el tiempo de gracia antes de SIGKILL (0 usa el default de Docker). |
| `docker_tui_go_infra` | `func main() — TUI fullscreen para gestionar Docker` | Pipeline que compone componentes TUI de DevFactory con comandos Docker para crear una aplicacion de terminal interactiva. Gestiona containers, images, volumes, networks y compose. |
| `docker_volume_create_go_infra` | `func DockerVolumeCreate(name string) (string, error)` | Crea un volume Docker con el nombre dado. Retorna el nombre del volume creado tal como lo confirma Docker. |
| `docker_volume_list_go_infra` | `func DockerVolumeList() ([]map[string]string, error)` | Lista los volumes Docker disponibles localmente. Parsea la salida JSON de docker volume ls. Retorna slice de maps con campos Driver, Name, Scope, Labels, Mountpoint. |
| `docker_volume_remove_go_infra` | `func DockerVolumeRemove(name string, force bool) error` | Elimina un volume Docker por nombre. Si force es true fuerza la eliminación aunque esté en uso. |
| `dockerize_app_bash_pipelines` | `dockerize_app(app_name: string, [--domain DOMAIN], [--port PORT], [--ssh-host HOST], [--remote-dir DIR], [--basic-auth USER:PASS], [--no-auth], [--no-gzip], [--env KEY=VAL]..., [--volume NAME], [--build-cmd CMD], [--standalone], [--dry-run]) -> json` | Empaqueta una app Go del registry para deploy a VPS organic-machine via Docker + Traefik + Coolify. Genera Dockerfile multi-stage, docker-compose.yml, traefik-dynamic.yml con basicAuth opcional y gzip, sube via rsync al VPS y arranca el stack remoto. Replica el patron de apps/registry_api/. |
| `generate_compose_traefik_go_infra` | `func GenerateComposeTraefik(cfg ComposeTraefikConfig) string` | Genera el texto YAML de un docker-compose.yml para una app Go desplegada behind Traefik + Coolify. Replica el patron de apps/registry_api/docker-compose.yml. Determinista: orden de EnvVars sigue el orden de entrada. |
| `generate_dockerfile_go_infra` | `func GenerateDockerfile(binaryName string, port int, envVars map[string]string) string` | Genera el texto de un Dockerfile multi-stage para una app Go. Stage build con golang:1.23-alpine, stage final con alpine:latest. Incluye ENV vars del map con orden determinista. Funcion pura sin I/O. |
| `init_metabase_go_infra` | `func main() — Despliega stack Metabase + Postgres en Docker` | Pipeline que inicializa un contenedor Metabase con su base de datos Postgres. Crea red Docker, pull de imágenes, inicia Postgres con volume persistente, espera health check y lanza Metabase conectado. |
| `metabase_add_ops_db_py_pipelines` | `metabase_add_ops_db(app_name: str) -> None` | Registra la operations.db de una app en Metabase como database SQLite. Verifica duplicados y muestra el mount necesario para el contenedor Docker. |
| `metabase_fix_permissions_py_pipelines` | `metabase_fix_permissions() -> None` | Arregla permisos SQLITE_READONLY_DIRECTORY en el contenedor Metabase. Hace chmod 777/666 en directorios y archivos .db bajo /data/ para que el usuario metabase (UID 2000) pueda crear journal files. |
| `nordvpn_container_run_go_infra` | `func NordVPNContainerRun(opts NordVPNContainerRunOpts) (string, error)` | Ejecuta un container Docker cuyo trafico pasa por el gateway NordVPN usando --network=container:<gateway>. El container hereda la IP y tunel VPN del gateway. |
| `nordvpn_container_start_go_infra` | `func NordVPNContainerStart(opts NordVPNContainerOpts) (string, error)` | Levanta un container Docker con NordVPN como gateway de red. Otros containers pueden rutear su trafico a traves de este con --network=container:<name>. Espera hasta 30s a que el tunel este activo. |
| `nordvpn_container_stop_go_infra` | `func NordVPNContainerStop(gateway string, clientNames ...string) error` | Detiene y elimina el container gateway NordVPN y opcionalmente los containers cliente que usan su red. |
| `setup_geo_stack_docker_pipeline_py_pipelines` | `def setup_geo_stack_docker_pipeline(compose_path: str, wait_seconds: int, verify: bool) -> dict` | Levanta el geo stack Docker (Valhalla + PostGIS + Martin) via docker compose up -d y verifica que los tres servicios responden. |
| `setup_metabase_volume_bash_pipelines` | `setup_metabase_volume([registry_db_path: string], [container_name: string], [dest_path: string]) -> void` | Copia registry.db al contenedor Docker de Metabase verificando existencia del archivo, disponibilidad de docker, estado del contenedor y coincidencia de tamaños. Todos los argumentos son opcionales con defaults razonables. |
| `setup_registry_api_bash_infra` | `setup_registry_api(ssh_host: string, api_token: string, basic_auth_user: string, basic_auth_pass: string) -> json` | Deploy completo de registry_api en VPS con Docker + Traefik (Coolify proxy). Sincroniza el repo via rsync, genera el hash bcrypt para basicAuth, sube el traefik-dynamic.yml, crea el .env con el token, hace docker compose build+up y verifica el health check. |
| `stop_app_go_infra` | `func StopApp(containerName string, removeImage bool) error` | Para y elimina el contenedor de una app desplegada. Si removeImage es true elimina también la imagen Docker. containerName debe coincidir con el imageName usado en deploy_app. |
| `write_dockerfile_go_infra` | `func WriteDockerfile(dir, content string) (string, error)` | Escribe content en dir/Dockerfile. Crea el directorio si no existe. Retorna el path absoluto del archivo escrito. Compañera impura de generate_dockerfile. |


## Ejemplo canonico

### Build + run local

```bash
./fn run docker_build_image --path . --tag myapp:latest
./fn run docker_run --image myapp:latest --name myapp --port 8080:8080 --detach
./fn run docker_inspect_container --name myapp | jq .
./fn run docker_container_logs --name myapp --tail 100
```

### Docker Compose local

```bash
./fn run docker_compose_up --file docker-compose.yml --detach
./fn run docker_compose_ps
./fn run docker_compose_restart --service api
./fn run docker_compose_down
```

### Deploy a VPS con Compose + git pull

```bash
./fn run docker_compose_remote_deploy \
  --host organic-machine \
  --remote-dir /srv/coolify/myapp \
  --branch master \
  --compose-files "docker-compose.yml docker-compose.prod.yml"
```

## Fronteras

- **NO maneja Kubernetes ni Swarm**. Solo Docker engine + Compose.
- **NO instala Docker**. Asume `docker` y `docker compose` ya disponibles en PATH (local + remoto).
- **NO genera Dockerfiles a partir de codigo**. Solo opera contenedores y composes. Generacion: `generate_dockerfile_go_infra` del grupo `deploy`.
- **NO maneja secretos Docker Swarm**. Pasa secrets via env vars o files montados via `--volume`.
