Skip to content

Telegram bot for remote Docker container management via direct socket communication

License

Notifications You must be signed in to change notification settings

luall0/dockergram

Repository files navigation

DockerGram

Docker Hub GitHub

A Telegram bot for managing Docker containers via docker.sock.

Designed for individual use - Perfect for managing personal home servers, remote development environments, or homelab setups. While it can technically be used in enterprise contexts, managing company service stacks through Telegram is not recommended for production environments.

Features

  • 🐳 Manage Docker containers through Telegram
  • 🔧 Configurable command prefix (default: /dg)
  • 🔐 User authentication via Telegram user IDs
  • 🔌 Direct access to Docker daemon via socket
  • 📊 Real-time container resource monitoring (CPU, memory, network, disk I/O)
  • 📝 View container logs with configurable line count
  • 📎 Automatic file attachment for large outputs (>4096 chars)
  • 📦 Docker Compose project grouping
  • 💾 Volume management with detailed inspection and pruning
  • 🖼️ Image management (list, history, prune, remove)
  • ▶️ Start/stop containers and projects with dependency handling
  • 🔄 Smart container restart with network dependency detection
  • 🎯 Dependency-aware compose project operations (topological sort)
  • 🛡️ Self-container protection (prevents accidental bot disconnection)
  • 🤖 No command conflicts with other bots
  • ✅ Comprehensive test suite

Available Commands

All commands require a prefix to avoid conflicts with other bots. The default prefix is /dg, but you can customize it via the COMMAND_PREFIX environment variable.

Commands

Information:

  • /<prefix> help - Show help message with available commands
  • /<prefix> ps - List running containers
  • /<prefix> all - List all containers (including stopped)
  • /<prefix> status <name|id> - Get detailed container status (includes CPU/memory for running containers)
  • /<prefix> log <name|id> [lines] - Get container logs (default: 50 lines)
  • /<prefix> exec <name|id> <command> [args...] - Execute command in running container
  • /<prefix> stats - Show resource stats for all running containers (grouped by project)
  • /<prefix> stats <name|id> [<name|id> ...] - Show stats for specific container(s)
  • /<prefix> stats -p <project> [<project> ...] - Show stats for compose project(s)
  • /<prefix> stats --full|-f - Include network and block I/O stats

Container Control:

  • /<prefix> start <name|id> [<name|id> ...] - Start one or more containers
  • /<prefix> start --with-deps|-w <name|id> - Start container and its network dependents (if stopped)
  • /<prefix> start --restart-deps|-r <name|id> - Start container and restart its network dependents
  • /<prefix> stop <name|id> [<name|id> ...] - Stop one or more containers
  • /<prefix> stop --with-deps|-w <name|id> - Stop container and its network dependents
  • /<prefix> restart <name|id> - Smart restart of a container (with network dependents)

Project Control:

  • /<prefix> start-project <project> [<project> ...] - Start compose project(s) in dependency order
  • /<prefix> stop-project <project> [<project> ...] - Stop compose project(s) in reverse dependency order (with self-container protection)
  • /<prefix> stop-project --force|-f <project> - Force stop including the bot itself
  • /<prefix> restart-project <project> - Restart entire Docker Compose project (dependency-aware, with self-container protection)
  • /<prefix> restart-project --force|-f <project> - Force restart including the bot itself

Volume Management:

  • /<prefix> volume ls [--detailed|-d] - List all Docker volumes (with optional container usage)
  • /<prefix> volume <name> - Inspect a specific volume with container details
  • /<prefix> volume prune [--all|-a] - Remove unused volumes (anonymous only, or all with --all)

Image Management:

  • /<prefix> image ls - List all Docker images with repository, tag, ID, creation date, and size
  • /<prefix> image history <name|id> - Show image layer history
  • /<prefix> image prune [--all|-a] - Remove unused images (dangling only, or all with --all)
  • /<prefix> image rm <name|id> [<name|id> ...] - Delete specific image(s) not in use

Note: All flags support both long format (--flag) and short format (-f) for convenience.

Examples (with default prefix /dg)

/dg help                         # Show help message
/dg ps                           # Quick list of running containers
/dg all                          # List all containers
/dg status nginx                 # Get status of container named "nginx"
/dg log nginx 100                # Get last 100 lines of logs
/dg exec nginx ls -la            # Execute command in container
/dg exec app npm run test        # Run tests inside app container
/dg exec db psql -U postgres -c "SELECT * FROM users LIMIT 10"  # Query database
/dg stats                        # Show stats for all running containers
/dg stats nginx                  # Show stats for single container
/dg stats nginx app db           # Show stats for multiple containers
/dg stats -p myapp               # Show stats for entire project
/dg stats --full                 # Show stats with network & block I/O
/dg stats -f -p myapp            # Show full stats for project

# Container control
/dg start nginx                  # Start single container
/dg start nginx app db           # Start multiple containers
/dg start --with-deps gluetun    # Start gluetun and any stopped dependents
/dg start -w gluetun             # Same as --with-deps (shorthand)
/dg start --restart-deps gluetun # Start gluetun and restart running dependents
/dg start -r gluetun             # Same as --restart-deps (shorthand)
/dg stop nginx app               # Stop multiple containers
/dg stop --with-deps gluetun     # Stop gluetun and its dependents
/dg stop -w gluetun              # Same as --with-deps (shorthand)
/dg restart app                  # Restart with auto-detection of network dependents

# Project control
/dg start-project myapp          # Start all containers in myapp project
/dg stop-project myapp media     # Stop containers (skips bot if it's in the project)
/dg stop-project --force myapp   # Force stop including bot itself
/dg stop-project -f myapp        # Same as --force (shorthand)
/dg restart-project myapp        # Restart entire project (skips bot if it's in the project)
/dg restart-project --force myapp # Force restart including bot itself
/dg restart-project -f myapp     # Same as --force (shorthand)

# Volume management
/dg volume ls                    # List all volumes (compact view)
/dg volume ls --detailed         # List volumes with container usage details
/dg volume ls -d                 # Same as --detailed (shorthand)
/dg volume my-volume             # Inspect specific volume with container details
/dg volume prune                 # Remove unused anonymous volumes only
/dg volume prune --all           # Remove ALL unused volumes (including named)
/dg volume prune -a              # Same as --all (shorthand)

# Image management
/dg image ls                     # List all images
/dg image history nginx:latest   # Show layer history for nginx image
/dg image prune                  # Remove dangling images only
/dg image prune --all            # Remove ALL unused images
/dg image prune -a               # Same as --all (shorthand)
/dg image rm nginx:old           # Remove specific image
/dg image rm nginx:old redis:6   # Remove multiple images

Output Handling

For commands that may produce large output (ps, all, log, exec, stats, volume ls, image ls, image history):

  • Small outputs (≤4096 chars): Displayed inline in Telegram with Markdown formatting
  • Large outputs (>4096 chars): Automatically sent as a downloadable .txt file attachment

This ensures you never lose data due to Telegram's message length limits.

Container Statistics

DockerGram provides real-time resource monitoring for your Docker containers. The stats command shows CPU usage, memory usage/limit/percentage, and optionally network and block I/O statistics.

Usage:

/dg stats                         # All running containers (grouped by project)
/dg stats <name|id> [...]         # Specific container(s)
/dg stats -p <project> [...]      # Entire project(s)
/dg stats --full|-f               # Include network & block I/O stats

Examples:

/dg stats                         # Overview of all running containers
/dg stats nginx                   # Single container stats
/dg stats nginx redis postgres    # Multiple containers
/dg stats -p media_server         # All containers in a project
/dg stats --full                  # All containers with I/O stats
/dg stats -f -p myapp             # Project stats with I/O

What's Included:

  • CPU Usage: Percentage based on host CPU cores
  • Memory: Usage / Limit (Percentage)
  • Network I/O (with --full): RX/TX bytes across all interfaces
  • Block I/O (with --full): Read/Write bytes

Important Notes:

  • Only works on running containers
  • Stats are real-time snapshots (not averages)
  • CPU percentage can exceed 100% on multi-core systems (e.g., 200% = using 2 cores fully)
  • Large stats outputs automatically sent as downloadable files
  • The status command also includes CPU/memory stats for running containers

Exec Command

The exec command allows you to run arbitrary commands inside running containers, similar to docker exec -it <container> <command>.

Usage:

/dg exec <container-name|id> <command> [args...]

Examples:

/dg exec nginx ls -la                           # List files in nginx container
/dg exec nginx cat /etc/nginx/nginx.conf        # View nginx config
/dg exec app npm run test                       # Run tests
/dg exec db psql -U postgres -c "SELECT version()"  # Query PostgreSQL
/dg exec redis redis-cli INFO stats             # Get Redis stats

Important Notes:

  • Only works on running containers
  • Captures both stdout and stderr
  • Output sent as file if it exceeds Telegram's message limit
  • Commands run non-interactively (no TTY allocation)
  • Useful for quick debugging, inspections, and one-off commands

Volume Management

DockerGram provides comprehensive volume management capabilities for inspecting, monitoring, and cleaning up Docker volumes.

Usage:

/dg volume ls [--detailed|-d]    # List all volumes
/dg volume <name>                # Inspect specific volume
/dg volume prune [--all|-a]      # Remove unused volumes

Volume Listing:

/dg volume ls                    # Quick list: name, driver, size
/dg volume ls --detailed         # Detailed: includes containers using each volume

The detailed view shows which containers are using each volume (running or stopped), making it easy to understand volume usage across your system.

Volume Inspection:

/dg volume my-data               # Get detailed info for specific volume

Shows:

  • Volume name and driver
  • Mount point path
  • Labels (compose project, etc.)
  • Size and reference count
  • All containers using this volume (with state)

Volume Pruning:

/dg volume prune                 # Remove unused anonymous volumes only (safe)
/dg volume prune --all           # Remove ALL unused volumes (including named)

Docker distinguishes between:

  • Anonymous volumes: Auto-generated names (e.g., a1b2c3d4e5f6...)
  • Named volumes: User-specified names (e.g., db-data, my-volume)

By default, prune only removes unused anonymous volumes (Docker's default behavior). Use --all to remove all unused volumes including named ones.

Important Notes:

  • Volume list with --detailed may be sent as file if you have many volumes
  • Pruning is permanent - deleted volumes cannot be recovered
  • A volume is "unused" if no containers (running or stopped) reference it
  • The bot will show you exactly which volumes will be deleted and space reclaimed

Image Management

DockerGram provides comprehensive image management capabilities for listing, inspecting, cleaning, and removing Docker images.

Usage:

/dg image ls                     # List all images
/dg image history <name|id>      # Show image layer history
/dg image prune [--all|-a]       # Remove unused images
/dg image rm <name|id> [...]     # Delete specific images

Image Listing:

/dg image ls                     # Shows: repository, tag, ID, creation date, size

Displays all images on your Docker daemon with total size summary. Large lists are automatically sent as downloadable files.

Image History:

/dg image history nginx:latest   # View layer-by-layer build history
/dg image history abc123def456   # Works with image IDs too

Shows detailed layer history including:

  • Layer ID
  • Creation timestamp
  • Layer size
  • Build command used

Perfect for understanding image composition and debugging build issues. Large histories are sent as files.

Image Pruning:

/dg image prune                  # Remove dangling images only (safe)
/dg image prune --all            # Remove ALL unused images

Docker distinguishes between:

  • Dangling images: Untagged layers from builds (e.g., <none>:<none>)
  • Unused images: Tagged images not referenced by any containers

By default, prune only removes dangling images (Docker's default behavior). Use --all to remove all unused images including tagged ones.

Image Removal:

/dg image rm nginx:latest        # Remove single image
/dg image rm nginx:old redis:6   # Remove multiple images at once

Removes specific images with validation:

  • Checks if image is in use by any container (running or stopped)
  • Prevents accidental removal of images needed by containers
  • Supports batch removal with per-image success/failure reporting
  • Shows descriptive error if image is in use

Important Notes:

  • Only removes images not referenced by any containers (running or stopped)
  • Pruning and removal are permanent - deleted images must be re-pulled or rebuilt
  • An image is "unused" if no containers reference it in their Image or ImageID fields
  • The bot shows exactly which images will be deleted and space reclaimed
  • Use docker pull to re-download removed images if needed

Prerequisites

  • Docker daemon running
  • Telegram Bot Token (from @BotFather)
  • Your Telegram User ID (send /start to @userinfobot)

Quick Start with Docker

Using Docker Run

docker run -d \
  --name dockergram \
  --restart unless-stopped \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e TELEGRAM_BOT_TOKEN=your_bot_token_here \
  -e ALLOWED_USER_IDS=123456789 \
  -e COMMAND_PREFIX=dg \
  luall0/dockergram:latest

Using Docker Compose

Create a docker-compose.yml:

services:
  dockergram:
    image: luall0/dockergram:latest
    container_name: dockergram
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      TELEGRAM_BOT_TOKEN: your_bot_token_here
      ALLOWED_USER_IDS: 123456789,987654321     # Comma-separated for multiple users
      COMMAND_PREFIX: dg                         # Optional, defaults to 'dg'
      DOCKER_SOCKET_PATH: /var/run/docker.sock   # Optional, defaults to this path
      ALLOW_SELF_RESTART: false                  # Optional, prevents accidental bot disconnection
    healthcheck:
      test: ["CMD", "node", "dist/healthcheck.js"]
      interval: 30s
      timeout: 5s
      start_period: 10s
      retries: 3

Start the bot:

docker compose up -d

Environment Variables:

  • TELEGRAM_BOT_TOKEN (required): Your Telegram bot token from BotFather
  • ALLOWED_USER_IDS (required): Comma-separated list of authorized Telegram user IDs
  • COMMAND_PREFIX (optional): Command prefix for bot commands (default: dg)
  • DOCKER_SOCKET_PATH (optional): Path to Docker socket (default: /var/run/docker.sock)
  • ALLOW_SELF_RESTART (optional): Allow project commands to stop/restart the bot (default: false)

Health Check: The Docker image includes a built-in health check that verifies:

  • Docker daemon connectivity (via docker.ping())
  • Telegram API connectivity (via bot.telegram.getMe())

The health check runs every 30 seconds and marks the container as unhealthy if either check fails. This allows Docker Compose or orchestration tools to automatically restart the container if connectivity is lost.

Installation from Source

For development or building from source:

Prerequisites:

  • Node.js >= 18.0.0
  • Yarn package manager
  1. Clone the repository

  2. Install dependencies:

    yarn install
  3. Copy .env.example to .env and configure:

    cp .env.example .env
  4. Set your environment variables in .env:

    • TELEGRAM_BOT_TOKEN: Your Telegram bot token
    • DOCKER_SOCKET_PATH: Path to Docker socket (default: /var/run/docker.sock)
    • COMMAND_PREFIX: Command prefix for all bot commands (default: dg)
    • ALLOWED_USER_IDS: Comma-separated list of authorized Telegram user IDs

Development

Run in development mode with hot reload:

yarn dev

Build

Compile TypeScript to JavaScript:

yarn build

Production

Run the compiled bot:

yarn start

Scripts

  • yarn dev - Run in development mode with hot reload
  • yarn build - Compile TypeScript
  • yarn start - Run production build
  • yarn lint - Lint the codebase
  • yarn typecheck - Type check without emitting files
  • yarn test - Run all tests
  • yarn test:watch - Run tests in watch mode
  • yarn test:coverage - Generate test coverage report

Container and Project Control

DockerGram provides intelligent container and project management with dependency-aware operations. This goes beyond Docker's basic commands and is critical for containers using shared network namespaces.

The Problem with Basic Restart

When you use Docker's basic restart command on a container that shares its network with dependents (using network_mode: "service:<container>" or container:<id>), the dependent containers lose network connectivity:

  1. Parent container (e.g., gluetun VPN) restarts
  2. Docker creates a new network namespace for the parent
  3. Dependent containers (e.g., qbittorrent) remain attached to the old namespace
  4. Network connectivity breaks - containers can no longer communicate

Common Use Cases

This is especially critical for:

  • VPN containers (gluetun, wireguard) with services routing through them
  • Reverse proxies (nginx, traefik) with services using their network
  • Network sidecars (tailscale, cloudflared) sharing network namespaces

Example Docker Compose setup:

services:
  gluetun:
    image: qmcgaw/gluetun
    # VPN configuration

  qbittorrent:
    image: linuxserver/qbittorrent
    network_mode: "service:gluetun"  # Routes through gluetun's VPN
    depends_on:
      - gluetun

Our Solution: Dependency-Aware Operations

1. Start/Stop with Dependency Options

Start a container with its dependents:

/dg start --with-deps gluetun
/dg start -w gluetun             # Short form
  • Starts gluetun first
  • Then starts any dependent containers that are stopped
  • Perfect for bringing up a VPN with its services

Start a container and restart running dependents:

/dg start --restart-deps gluetun
/dg start -r gluetun             # Short form
  • Starts gluetun
  • Force-restarts any running dependents (to re-attach to new network namespace)
  • Use when you need dependents to reconnect immediately

Stop a container with its dependents:

/dg stop --with-deps gluetun
/dg stop -w gluetun              # Short form
  • Stops dependents first (clean shutdown)
  • Then stops the parent container
  • Maintains proper shutdown order

2. Single Container Restart (/dg restart <container>)

Automatically detects and restarts network-dependent containers:

/dg restart gluetun

What happens:

  1. ✅ Detects qbittorrent uses gluetun's network
  2. ✅ Stops qbittorrent first
  3. ✅ Stops and starts gluetun (creates new namespace)
  4. ✅ Starts qbittorrent (attaches to new namespace)
  5. ✅ Shows you which dependents were restarted

Why stop-then-start instead of restart?

  • Docker's restart command doesn't allow dependents to detach/reattach
  • We use stop()start() sequence to ensure clean namespace recreation
  • This is the only way to preserve network connectivity

3. Project Start/Stop (/dg start-project and /dg stop-project)

Start entire Docker Compose projects in dependency order:

/dg start-project media_server

What happens:

  1. ✅ Analyzes depends_on labels and network_mode settings
  2. ✅ Builds dependency graph with topological sort
  3. ✅ Starts containers in correct order (parents before children)
  4. ✅ Handles complex multi-level dependencies automatically

Stop entire Docker Compose projects in reverse dependency order:

/dg stop-project media_server

What happens:

  1. ✅ Analyzes dependencies
  2. ✅ Stops containers in reverse order (children before parents)
  3. ✅ Ensures clean shutdown without breaking dependencies

4. Project Restart (/dg restart-project <name>)

Restarts entire Docker Compose projects in dependency order:

/dg restart-project media_server

What happens:

  1. ✅ Stops ALL containers in the project
  2. ✅ Analyzes depends_on labels and network_mode settings
  3. ✅ Builds dependency graph with topological sort
  4. ✅ Starts containers in correct order (parents before children)
  5. ✅ Handles complex multi-level dependencies automatically

Why this matters:

  • Docker Compose's restart: true feature only works with docker compose commands
  • DockerGram uses the Docker API directly (bypasses Docker Compose)
  • We implement dependency resolution at the API level
  • Ensures services like tailscale start after nginx, qbittorrent starts after gluetun, etc.

Self-Container Protection

When DockerGram runs inside a Docker Compose project, there's a risk of accidentally stopping or restarting the bot itself, causing immediate disconnection. To prevent this, DockerGram includes self-container protection.

How It Works:

  • The bot's Docker image includes a label: dockergram.self=true
  • When you run stop-project or restart-project, the bot automatically skips itself
  • You'll see a message: "⚠️ Skipped 1 self-container(s): dockergram. Use --force to override"
  • Direct container commands (stop, restart) are never restricted

Overriding Protection:

There are two ways to override this protection when you need to restart the bot:

  1. Per-command override (use --force or -f flag):

    /dg stop-project --force myproject
    /dg stop-project -f myproject         # Short form
    /dg restart-project --force myproject
    /dg restart-project -f myproject      # Short form
    
  2. Global override (set environment variable):

    environment:
      ALLOW_SELF_RESTART: true

Important Notes:

  • start-project has no protection - starting a stopped bot is harmless (you need the bot running to issue commands)
  • Direct container commands (/dg stop dockergram, /dg restart dockergram) always work - advanced users retain full control
  • Protection only applies to project-level operations where accidental disconnection is most likely

Technical Details

Network Mode Detection: DockerGram detects dependencies by checking for:

  • network_mode: "container:<name>"
  • network_mode: "service:<name>"
  • network_mode: "container:<full-64-char-id>"
  • network_mode: "container:<short-12-char-id>"

Dependency Resolution:

  • Parses com.docker.compose.depends_on labels from containers
  • Builds dependency graph using Kahn's topological sort algorithm
  • Avoids double-counting (e.g., when both depends_on and network_mode reference same container)
  • Falls back gracefully on circular dependencies

Comparison: Basic vs Dependency-Aware Operations

Operation Basic Docker Commands DockerGram Dependency-Aware
Start container ✅ Works ✅ Works + optional dependent handling
Stop container ✅ Works ✅ Works + optional dependent handling
Restart container ❌ Breaks network dependents ✅ Auto-restarts dependents
Start compose project ❌ Random order ✅ Respects dependency order
Stop compose project ❌ Random order ✅ Reverse dependency order
VPN + apps setup ❌ Apps lose VPN on restart ✅ Maintains VPN routing
Reverse proxy + services ❌ Services lose proxy ✅ Maintains proxy connection

Custom Prefix

You can set any prefix you want in your .env file:

COMMAND_PREFIX=docker    # Use /docker ps, /docker all, etc.
COMMAND_PREFIX=bot       # Use /bot ps, /bot all, etc.

Note: All commands require the configured prefix. Commands without the prefix will be ignored to prevent conflicts with other bots.

Project Structure

dockergram/
├── src/
│   ├── commands/       # Bot command handlers
│   ├── config/         # Configuration management
│   ├── middleware/     # Telegraf middleware (auth, prefix, etc.)
│   ├── services/       # Docker service integration
│   ├── utils/          # Utility functions (logger, formatters, etc.)
│   └── index.ts        # Application entry point
├── tests/
│   ├── helpers/        # Shared test utilities
│   ├── unit/           # Unit tests (pure functions)
│   └── integration/    # Integration tests (with mocks)
├── .env.example        # Environment variables template
├── jest.config.js      # Jest test configuration
├── package.json        # Project dependencies
└── tsconfig.json       # TypeScript configuration

Testing

DockerGram includes a comprehensive test suite covering unit and integration scenarios.

Running Tests

# Run all tests
yarn test

# Run tests in watch mode (for development)
yarn test:watch

# Generate coverage report
yarn test:coverage

Test Organization

  • Unit Tests (tests/unit/): Test pure functions without external dependencies

    • Formatters (container list formatting, status formatting)
    • Telegram utilities (message size handling)
  • Integration Tests (tests/integration/): Test components with mocked dependencies

    • Command handlers (ps, all, status, log, exec, stats, start, stop, restart, start/stop/restart-project, volume, image)
    • Docker service operations (including exec, stats, volume management, image management, network dependency detection and topological sort)
    • Authentication middleware

Test Features

  • No External Dependencies: All tests use mocks (no real Docker or Telegram required)
  • Fast Execution: Tests run quickly without external services
  • Type-Safe Mocking: Uses jest-mock-extended for TypeScript support
  • CI/CD Ready: Perfect for continuous integration pipelines

Adding Tests

When adding new features:

  1. Commands: Add integration tests in tests/integration/<command>.command.test.ts
  2. Utilities: Add unit tests in tests/unit/<module>.test.ts
  3. Use shared helpers from tests/helpers/test-utils.ts to reduce duplication

See CLAUDE.md for detailed testing guidelines and patterns.

Security

This bot requires access to the Docker socket, which provides full control over Docker. Ensure you:

  • Configure ALLOWED_USER_IDS to restrict access
  • Never expose your bot token
  • Run with appropriate permissions
  • Review and understand the security implications

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass (yarn test)
  6. Submit a pull request

Special Thanks

Big shoutout to Claude Code and Anthropic for building such an incredible tool that empowers developers and makes building projects like this so much more efficient and enjoyable.

License

Apache 2.0

About

Telegram bot for remote Docker container management via direct socket communication

Topics

Resources

License

Stars

Watchers

Forks

Languages