Saltar a contenido

Snippets — Docker

Histrix

Makefile de gestión

Makefile para operar el contenedor de Histrix sin tener que recordar los comandos de docker exec. Guardar como Makefile en la raíz del proyecto.

Por defecto asume que el contenedor se llama histrix. Si el tuyo tiene otro nombre:

make pull CONTAINER_NAME=mi-contenedor
# O exportar para toda la sesión
export CONTAINER_NAME=mi-contenedor

Si el usuario necesita sudo para docker, ejecutar con USE_SUDO=true:

make pull USE_SUDO=true

Referencia rápida de comandos

Comando Qué hace
make pull Git pull dentro del contenedor
make push Git push desde dentro del contenedor
make restart-php Reinicia php-fpm via supervisord
make restart-nginx Reinicia nginx via supervisord
make restart-all Reinicia php-fpm y nginx
make clean-redis Flushea todo Redis
make composer-install composer install
make composer-dump composer dumpautoload
make composer-update composer update
make logs Tail de los últimos 100 logs del contenedor
make status Estado de servicios supervisord
make sh Shell dentro del contenedor

Makefile

# Configuración principal
CONTAINER_NAME ?= histrix
REDIS_CONTAINER_NAME ?= histrix-redis-1
USE_SUDO ?= false

# Prefijo sudo si está habilitado
SUDO = $(if $(filter true,$(USE_SUDO)),sudo,)

# --- Git dentro del contenedor ---
pull:
    $(SUDO) docker exec -t -i $(CONTAINER_NAME) /usr/bin/pull
push:
    $(SUDO) docker exec -t -i $(CONTAINER_NAME) /usr/bin/push

# --- Servicios supervisados ---
restart-php:
    $(SUDO) docker exec -t -i $(CONTAINER_NAME) supervisorctl restart php-fpm
restart-nginx:
    $(SUDO) docker exec -t -i $(CONTAINER_NAME) supervisorctl restart nginx
restart-all: restart-php restart-nginx

# --- Redis (contenedor separado) ---
clean-redis:
    $(SUDO) docker exec -t -i $(REDIS_CONTAINER_NAME) redis-cli flushall

# --- Composer (usar composer.phar) ---
composer-install:
    $(SUDO) docker exec -t -i $(CONTAINER_NAME) ./composer.phar install
composer-dump:
    $(SUDO) docker exec -t -i $(CONTAINER_NAME) ./composer.phar dumpautoload
composer-update:
    $(SUDO) docker exec -t -i $(CONTAINER_NAME) ./composer.phar update

# --- Logs del contenedor principal ---
logs:
    $(SUDO) docker logs --tail=100 -f $(CONTAINER_NAME)

# --- Estado de servicios ---
status:
    $(SUDO) docker exec -t -i $(CONTAINER_NAME) supervisorctl status

# --- Shell dentro del contenedor principal ---
sh:
    $(SUDO) docker exec -it $(CONTAINER_NAME) /bin/sh

PostgreSQL + pgAdmin + WebSocket Proxy

Stack de desarrollo local para proyectos que necesitan PostgreSQL con soporte WebSocket (usado por ejemplo en integraciones con Neon o clientes que consumen la DB via WS).

Levanta tres servicios:

  • postgres — PostgreSQL 16 con extensión PostGIS
  • pgadmin — interfaz web para administrar la base en http://localhost:5050
  • pg_proxy — proxy WebSocket de Neon que expone postgres en el puerto 5433

Uso:

docker compose up -d

Conectarse desde el cliente: - Directo: postgresql://root:admin@localhost:5432/started-db - Via WebSocket: postgresql://root:admin@localhost:5433/started-db

Solo para desarrollo

Las credenciales hardcodeadas (root / admin) son solo para local. En staging/producción usar variables de entorno reales.

services:
  postgres:
    image: postgis/postgis:16-3.4
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: admin
      POSTGRES_DB: started-db
    restart: unless-stopped
    ports:
      - 5432:5432
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "root"]
      interval: 10s
      timeout: 5s
      retries: 3

  pgadmin:
    container_name: pgadmin
    image: dpage/pgadmin4
    environment:
      PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-pgadmin4@pgadmin.org}
      PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-admin}
      PGADMIN_CONFIG_SERVER_MODE: "False"
    ports:
      - "5050:80"
    restart: unless-stopped
    depends_on:
      - postgres

  pg_proxy:
    image: ghcr.io/neondatabase/wsproxy:latest
    environment:
      APPEND_PORT: "postgres:5432"
      ALLOW_ADDR_REGEX: ".*"
      LOG_TRAFFIC: "true"
    ports:
      - "5433:80"
    depends_on:
      - postgres
    restart: unless-stopped

volumes:
  postgres_data:

Nginx Proxy Automático + SSL

Proxy reverso con generación automática de certificados SSL via Let's Encrypt. Lo usamos en los servidores para exponer múltiples servicios en el mismo host sin tocar configuraciones de Nginx a mano — alcanza con agregar variables de entorno al contenedor que querés exponer.

Setup inicial (una sola vez por servidor)

Antes de levantar el compose, crear la red externa que van a compartir todos los contenedores:

docker network create proxy

Luego levantar el proxy:

docker compose up -d

Cómo conectar un servicio al proxy

En el docker-compose.yml del proyecto que querés exponer, agregar las variables de entorno y conectarlo a la red proxy:

services:
  mi-app:
    image: mi-imagen
    environment:
      - VIRTUAL_HOST=midominio.com
      - LETSENCRYPT_HOST=midominio.com
    networks:
      - proxy

networks:
  proxy:
    external: true

Con eso solo el proxy detecta el contenedor automáticamente, configura el virtual host y gestiona el certificado SSL sin tocar nada más.

Múltiples dominios

Se pueden poner varios dominios separados por coma: VIRTUAL_HOST=midominio.com,www.midominio.com

El dominio tiene que apuntar al servidor

Let's Encrypt valida que el dominio resuelva a la IP del servidor antes de emitir el certificado. Si el DNS todavía no propagó, el certificado no se genera.

docker-compose.yml

services:
  nginx-proxy:
    image: nginxproxy/nginx-proxy
    container_name: nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - certs:/etc/nginx/certs
      - vhost:/etc/nginx/vhost.d
      - html:/usr/share/nginx/html
    networks:
      - proxy
    restart: always

  letsencrypt:
    image: nginxproxy/acme-companion
    container_name: nginx-proxy-letsencrypt
    volumes_from:
      - nginx-proxy
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - acme:/etc/acme.sh
    environment:
      - DEFAULT_EMAIL=soporte@mundoit.com.ar
    depends_on:
      - nginx-proxy
    networks:
      - proxy
    restart: always

volumes:
  certs:
  vhost:
  html:
  acme:

networks:
  proxy:
    external: true

ZeroTier Proxy — Acceso a redes privadas de clientes

Compose para conectarse a la red ZeroTier de un cliente y exponer su servidor interno via Nginx como proxy reverso. Lo usamos cuando el cliente tiene servidores en una red local que no son accesibles desde internet directamente.

El contenedor se une a la red ZeroTier del cliente y hace de bridge — el proxy (Nginx o Traefik) lo detecta como cualquier otro servicio y le enruta el tráfico.

Requisitos

  • Red proxy ya creada: docker network create proxy
  • El contenedor tiene que tener acceso a /dev/net/tun (disponible en la mayoría de VPS)
  • La IP del cliente (BACKEND_IP) es la IP que tiene el servidor del cliente dentro de la red ZeroTier

Variables a cambiar por cliente

Variable Descripción
ZEROTIER_NETWORK_ID ID de la red ZeroTier del cliente
BACKEND_IP IP del servidor del cliente en la red ZeroTier
alvarez-zerotier Reemplazar por nombre-cliente-zerotier en todo el archivo

Con Nginx Proxy (el que usamos normalmente)

Agregar las variables de entorno del proxy al servicio:

environment:
  - ZEROTIER_NETWORK_ID=xxxxxxxxxxxxxxxx
  - BACKEND_IP=xxx.xx.xxx.xx
  - VIRTUAL_HOST=cliente.histrix.com.ar
  - LETSENCRYPT_HOST=cliente.histrix.com.ar

docker-compose.yml

services:
  alvarez-zerotier:
    image: mundoit/nginx-zerotier:bc01ad4
    container_name: alvarez-zerotier
    restart: unless-stopped
    networks:
      - proxy
    environment:
      - ZEROTIER_NETWORK_ID=xxxxxxxxxxxxxxxx  # <- red ZeroTier del cliente
      - BACKEND_IP=xxx.xx.xxx.xx              # <- IP del servidor en ZeroTier
    devices:
      - "/dev/net/tun:/dev/net/tun"
    cap_add:
      - NET_ADMIN
      - SYS_ADMIN
    volumes:
      - alvarez-zerotier:/var/lib/zerotier-one

networks:
  proxy:
    external: true

volumes:
  alvarez-zerotier:

ZeroTier CUPS — Servidor de impresión remoto

Igual que el proxy ZeroTier pero en vez de Nginx expone un servidor CUPS. Lo usamos cuando el cliente necesita imprimir desde Histrix a impresoras que están en su red local — el contenedor se une a su red ZeroTier y queda accesible como servidor de impresión desde dentro del stack.

A diferencia del proxy Nginx, este no se expone al exterior — usa expose en vez de ports, así que solo es accesible desde otros contenedores en la misma red (histrix_backend).

Variables a cambiar por cliente

Variable Descripción
ZEROTIER_NETWORK_ID ID de la red ZeroTier del cliente
mis15 Reemplazar por el identificador del cliente en todo el archivo
El alias mis15-cups.histrix.com.ar Es como lo van a llamar los otros contenedores para mandarle a imprimir

docker-compose.yml

services:
  mis15-cups-zerotier:
    image: mundoit/cups-zerotier:f811d32
    container_name: mis15-cups-zerotier
    restart: unless-stopped
    networks:
      proxy:
      histrix_backend:
        aliases:
          - mis15-cups.histrix.com.ar   # <- nombre-cliente-cups.histrix.com.ar
    environment:
      - ZEROTIER_NETWORK_ID=xxxxxxxxxxxxxxxx  # <- red ZeroTier del cliente
    expose:
      - "631"   # puerto CUPS, solo accesible internamente
    devices:
      - "/dev/net/tun:/dev/net/tun"
    cap_add:
      - NET_ADMIN
      - SYS_ADMIN
    volumes:
      - mis15-cups-zerotier:/var/lib/zerotier-one
      - cups-config-mis15:/etc/cups
      - cups-data-mis15:/var/spool/cups
      - /var/run/dbus:/var/run/dbus

networks:
  proxy:
    external: true
  histrix_backend:
    external: true

volumes:
  mis15-cups-zerotier:
  cups-config-mis15:
  cups-data-mis15:

Al implementar

Al momento de implementar, ahi que hacer un cambio a mano en el docker no recuerdo, por lo cual llegado el momento de implementar, avisar asi se ve el cambio y se deja documentado. Es un cambio menor, pero es importante dejarlo registrado para no olvidarlo.