---
title: Docker Deployment
description: Deploy Alita Robot using Docker and docker-compose.
---

Docker is the recommended way to deploy Alita Robot. The provided `docker-compose.yml` includes all required services with optimized configurations for production use.

## Prerequisites

- **Docker** 20.10 or higher
- **docker compose** v2 (comes with Docker Desktop)
- A Telegram bot token from [@BotFather](https://t.me/BotFather)
- Your Telegram user ID (get it from [@userinfobot](https://t.me/userinfobot))

## Quick Start

1. **Clone the repository**

    ```bash
    git clone https://github.com/divkix/Alita_Robot.git
    cd Alita_Robot
    ```

2. **Copy and configure environment variables**

    ```bash
    cp sample.env .env
    ```

    Edit `.env` with your configuration. The supplied Compose file runs in
    webhook mode, so set BOT_TOKEN,
    OWNER_ID,
    MESSAGE_DUMP,
    WEBHOOK_DOMAIN, and
    WEBHOOK_SECRET.

    The Compose file reads only these five values from `.env`; every other
    setting in `.env` is ignored. To change another variable (for example
    `ENABLED_LOCALES` or `TYPESAFE_API_KEY`), add it under
    `services.alita.environment` in `docker-compose.yml`.

3. **Start all services**

    ```bash
    docker compose up -d
    ```

## Docker Compose Configuration

The `docker-compose.yml` deploys three services:

```yaml
# Production Docker Compose for Alita Robot
# Uses pre-built images from GHCR

services:
  alita:
    image: ghcr.io/divkix/alita_robot:latest
    container_name: alita-robot
    restart: always
    environment:
      DATABASE_URL: postgresql://alita:alita@postgres:5432/alita
      REDIS_ADDRESS: redis:6379
      REDIS_PASSWORD: redis
      AUTO_MIGRATE: "true"
      USE_WEBHOOKS: "true"
      HTTP_PORT: "8080"
      DROP_PENDING_UPDATES: "true"
      BOT_TOKEN: ${BOT_TOKEN}
      OWNER_ID: ${OWNER_ID}
      MESSAGE_DUMP: ${MESSAGE_DUMP}
      WEBHOOK_DOMAIN: ${WEBHOOK_DOMAIN}
      WEBHOOK_SECRET: ${WEBHOOK_SECRET}
    ports:
      - "8080:8080"
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "/app/alita_robot", "--health"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      resources:
        limits:
          memory: 1G
          cpus: "1.0"
        reservations:
          memory: 256M
          cpus: "0.25"

  postgres:
    image: postgres:17-alpine
    container_name: alita-postgres
    restart: always
    environment:
      POSTGRES_USER: alita
      POSTGRES_PASSWORD: alita
      POSTGRES_DB: alita
      POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U alita -d alita"]
      interval: 10s
      timeout: 5s
      retries: 5
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: "0.5"

  redis:
    image: redis:7-alpine
    container_name: alita-redis
    restart: always
    command: redis-server --requirepass redis
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "redis", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    deploy:
      resources:
        limits:
          memory: 256M
          cpus: "0.25"

volumes:
  postgres_data:
```

## Service Descriptions

### alita (Bot Service)

The main Telegram bot service.

| Configuration | Value | Description |
|--------------|-------|-------------|
| **Image** | `ghcr.io/divkix/alita_robot:latest` | Pre-built image from GitHub Container Registry |
| **Port** | 8080 | HTTP server for health, metrics, and webhooks |
| **Memory Limit** | 1GB | Maximum memory allocation |
| **Memory Reservation** | 256MB | Guaranteed minimum memory |
| **CPU Limit** | 1.0 | Maximum CPU cores |
| **CPU Reservation** | 0.25 | Guaranteed minimum CPU |

:::tip[Health Check]
The health check uses the built-in `--health` flag, which is ideal for distroless container images that lack curl or wget. No additional tooling is needed inside the container.
:::

:::tip[Debug Compose]
For development, use `debug.docker-compose.yml` which builds from local source with a debug Dockerfile. It runs with `cp sample.env .env` once `BOT_TOKEN`, `OWNER_ID` and `MESSAGE_DUMP` are filled in; Postgres and Redis credentials default to `password` / `alita_robot` / `redisPassword` unless `POSTGRES_PASSWORD`, `POSTGRES_DB` or `REDIS_PASSWORD` are set in `.env`.
:::

### postgres (Database)

PostgreSQL 17 with Alpine Linux for a minimal footprint.

| Configuration | Value | Description |
|--------------|-------|-------------|
| **Image** | `postgres:17-alpine` | PostgreSQL 17 on Alpine Linux |
| **Memory Limit** | 512MB | Maximum memory allocation |
| **Encoding** | UTF8 | Database character encoding |
| **Locale** | C | Collation locale |

Data is persisted in a Docker volume named `postgres_data`.

### redis (Cache)

Redis for caching and session management.

| Configuration | Value | Description |
|--------------|-------|-------------|
| **Image** | `redis:7-alpine` | Redis 7 on Alpine Linux |
| **Memory Limit** | 256MB | Maximum memory allocation |
| **Authentication** | Password `redis` | Hard-coded in `docker-compose.yml`; to change it, edit `--requirepass` and the healthcheck's `-a` on the redis service and `REDIS_PASSWORD` on the alita service together |

## Environment Variables

Set these five in your `.env` file (Compose substitutes them into `docker-compose.yml`):

```bash
# Required
BOT_TOKEN=your_bot_token_here
OWNER_ID=your_telegram_id
MESSAGE_DUMP=-100xxxxxxxxxx

# For webhook mode (production)
WEBHOOK_DOMAIN=https://your-domain.com
WEBHOOK_SECRET=your-random-secret
```

To set any other variable from the [Environment Reference](/api-reference/environment/), add it to the `alita` service's `environment:` block in `docker-compose.yml`.

## Resource Limits

The compose file includes recommended resource limits:

| Service | Memory Limit | CPU Limit | Use Case |
|---------|-------------|-----------|----------|
| alita | 1GB | 1.0 | Handles bot traffic |
| postgres | 512MB | 0.5 | Database operations |
| redis | 256MB | 0.25 | Caching |

For high-traffic deployments, increase these limits:

```yaml
deploy:
  resources:
    limits:
      memory: 2G
      cpus: "2.0"
```

## Updating the Bot

1. **Pull the latest images**

    ```bash
    docker compose pull
    ```

2. **Recreate containers with new images**

    ```bash
    docker compose up -d
    ```

3. **Remove old images (optional)**

    ```bash
    docker image prune -f
    ```

## Viewing Logs

**All Services**

```bash
docker compose logs -f
```

**Bot Only**

```bash
docker compose logs -f alita
```

**Last 100 Lines**

```bash
docker compose logs --tail=100 alita
```

**PostgreSQL**

```bash
docker compose logs -f postgres
```

## Common Operations

### Restart the bot

```bash
docker compose restart alita
```

### Stop all services

```bash
docker compose down
```

### Stop and remove volumes

:::danger[Data Loss]
This command deletes all data including the PostgreSQL database. Make sure you have a backup before running this.
:::

```bash
docker compose down -v
```

### Access PostgreSQL shell

```bash
docker compose exec postgres psql -U alita -d alita
```

### Access Redis CLI

```bash
docker compose exec redis redis-cli -a redis
```

## Health Checks

:::tip
The bot includes built-in health checks accessible at `http://localhost:8080/health`. Use this endpoint for load balancer health probes and uptime monitoring.
:::

```json
{
  "status": "healthy",
  "checks": {
    "database": true,
    "redis": true
  },
  "version": "2.17.24",
  "uptime": "24h30m15s"
}
```

## Troubleshooting

### Container keeps restarting

Check the logs for error messages:

```bash
docker compose logs alita
```

Common issues:
- Invalid `BOT_TOKEN`
- `MESSAGE_DUMP` empty or not a number (a wrong but non-zero channel ID does not stop the bot; it only logs `Failed to send startup message to log group`)
- Database connection failed (wait for postgres to be ready)

### Database connection errors

Ensure postgres is healthy before alita starts:

```bash
docker compose ps
```

The postgres container should show `healthy` status.

### Webhook not working

1. Ensure `WEBHOOK_DOMAIN` is set correctly (must include `https://`)
2. Check that `WEBHOOK_SECRET` is configured
3. Verify port 8080 is accessible externally

See [Webhooks Guide](/self-hosting/webhooks/) for detailed setup.
