# Docker Deployment Guide This guide explains how to deploy meshcore-bot using Docker and Docker Compose. ## Prerequisites - Docker Engine 20.10+ or Docker Desktop - Docker Compose 2.0+ (included with Docker Desktop) ## Quick Start 1. **Clone the repository** (if you haven't already): ```bash git clone cd meshcore-bot ``` 2. **Run the setup script** (recommended): ```bash ./docker-setup.sh ``` This will create the necessary directories and copy the example config file. **Or manually:** ```bash mkdir -p data/{config,databases,logs,backups} cp config.ini.example data/config/config.ini ``` 3. **Edit configuration file**: ```bash # Edit data/config/config.ini with your settings nano data/config/config.ini # or your preferred editor ``` 4. **Update database paths in config.ini**: The setup script (`./docker-setup.sh`) will automatically update these paths, but you can also set them manually: ```ini [Bot] db_path = /data/databases/meshcore_bot.db [Web_Viewer] db_path = /data/databases/meshcore_bot.db [Logging] log_file = /data/logs/meshcore_bot.log ``` **Important**: The log file path must be absolute (`/data/logs/...`), not relative. Relative paths will resolve to the config directory which is read-only. 5. **Start the container**: ```bash docker-compose up -d ``` 6. **View logs**: ```bash docker-compose logs -f ``` ## Configuration ### Volume Mappings The `docker-compose.yml` file maps the following directories: - `./data/config` → `/data/config` (read-only) - Configuration files - `./data/databases` → `/data/databases` - SQLite database files - `./data/logs` → `/data/logs` - Log files - `./data/backups` → `/data/backups` - Database backups ### Serial Port Access **⚠️ Important: Docker Desktop on macOS does NOT support serial device passthrough.** If you're using a serial connection, you have several options: **Option 1: Use TCP Connection (Recommended for macOS)** If your MeshCore device supports TCP/IP (via gateway or bridge), configure it in `config.ini`: ```ini [Connection] connection_type = tcp hostname = 192.168.1.60 # Your device's IP or hostname tcp_port = 5000 ``` Then comment out or remove the `devices` section in `docker-compose.yml`. **Option 2: Serial-to-TCP Bridge (macOS workaround)** Use a tool like `socat` to bridge the serial port to TCP on the host: ```bash # On macOS host, create TCP bridge socat TCP-LISTEN:5000,reuseaddr,fork FILE:/dev/cu.usbmodem1101,raw,nonblock,waitlock=/var/run/socat.pid ``` Then configure the bot to use TCP connection to `localhost:5000`. **Option 3: Device Mapping (Linux only)** On Linux, you can map the serial device directly: ```yaml devices: - /dev/ttyUSB0:/dev/ttyUSB0 ``` **Option 4: Host Network Mode (Linux only, for BLE)** For BLE connections on Linux, you may need host network access: ```yaml network_mode: host ``` **Note**: Host network mode gives the container full access to the host network, which has security implications. **Windows 11 (Docker Desktop / WSL2):** See [Connecting COM Ports to Docker on Windows 11](#connecting-com-ports-to-docker-on-windows-11) below. ### Web Viewer Port If you enable the web viewer, uncomment and adjust the `ports` section: ```yaml ports: - "8080:8080" ``` Make sure your `config.ini` has: ```ini [Web_Viewer] enabled = true host = 0.0.0.0 # Required for Docker port mapping port = 8080 ``` ## Building the Image ### Using Docker Compose **Important**: To avoid pull warnings, build the image first: ```bash docker compose build ``` Then start the container: ```bash docker compose up -d ``` Or build and start in one command: ```bash docker compose up -d --build ``` The `--build` flag ensures the image is built locally rather than attempting to pull from a registry. ### Using Docker directly ```bash docker build -t meshcore-bot:latest . ``` ## Running the Container ### Start in background ```bash docker-compose up -d ``` ### Start in foreground (see logs) ```bash docker-compose up ``` ### Stop the container ```bash docker-compose down ``` ### Restart the container ```bash docker-compose restart ``` ## Managing the Container ### View logs ```bash # Follow logs docker-compose logs -f # Last 100 lines docker-compose logs --tail=100 # Logs for specific service docker-compose logs meshcore-bot ``` ### Execute commands in container ```bash docker-compose exec meshcore-bot bash ``` ### Update the container ```bash # Pull latest changes git pull # Rebuild and restart docker-compose up -d --build ``` ## Using Pre-built Images If you're using GitHub Container Registry images: 1. **Update docker-compose.yml** to use the image: ```yaml services: meshcore-bot: image: ghcr.io/your-username/meshcore-bot:latest # Remove or comment out the 'build' section ``` 2. **Pull and start**: ```bash docker-compose pull docker-compose up -d ``` ## Troubleshooting ### Permission Issues If you encounter permission issues with database or log files: 1. **Check file ownership**: ```bash ls -la data/databases/ ls -la data/logs/ ``` 2. **Fix permissions** (if needed): ```bash sudo chown -R 1000:1000 data/ ``` The container runs as user ID 1000 (meshcore user). ### Serial Port Permission Denied If you see `[Errno 13] Permission denied` when accessing serial devices: 1. **Check device permissions** (on host): ```bash ls -l /dev/ttyUSB0 # or /dev/ttyACM0 # Should show: crw-rw---- 1 root dialout ... ``` 2. **Ensure device has dialout group** (on host): ```bash # Check current group ls -l /dev/ttyUSB0 | awk '{print $4}' # If not dialout, fix it (temporary - will reset on reboot) sudo chmod 666 /dev/ttyUSB0 # Or make it permanent with udev rules: sudo nano /etc/udev/rules.d/99-serial-permissions.rules # Add: KERNEL=="ttyUSB[0-9]*", MODE="0666", GROUP="dialout" # Then: sudo udevadm control --reload-rules ``` 3. **Rebuild the container** (to ensure user is in dialout group): ```bash docker compose build docker compose up -d ``` 4. **Alternative: Use privileged mode** (less secure, but works): ```yaml # In docker-compose.override.yml services: meshcore-bot: privileged: true ``` ### Serial Port Not Found 1. **Windows: "No such file or directory: 'COM3'"** Docker on Windows (WSL2) cannot see Windows COM ports. See [Connecting COM Ports to Docker on Windows 11](#connecting-com-ports-to-docker-on-windows-11) above. 2. **Check device exists** (Linux): ```bash ls -l /dev/ttyUSB0 # or your device ``` 3. **Use host network mode** if device mapping doesn't work: ```yaml network_mode: host ``` ### Database Locked Errors If you see database locked errors: 1. **Stop the container**: ```bash docker-compose down ``` 2. **Check for leftover database files**: ```bash ls -la data/databases/*.db-* ``` 3. **Remove lock files** (if safe): ```bash rm data/databases/*.db-shm data/databases/*.db-wal ``` 4. **Restart**: ```bash docker-compose up -d ``` ### Container Won't Start 1. **Check logs**: ```bash docker-compose logs ``` 2. **Verify config file exists**: ```bash ls -la data/config/config.ini ``` 3. **Test config file syntax**: ```bash docker-compose run --rm meshcore-bot python3 -c "import configparser; c = configparser.ConfigParser(); c.read('/data/config/config.ini'); print('Config OK')" ``` ### Build Failures on ARM Devices (Orange Pi, Raspberry Pi, etc.) If you encounter network errors during build like: ``` failed to add the host (veth...) <=> sandbox (veth...) pair interfaces: operation not supported ``` Try these solutions: 1. **Restart Docker daemon**: ```bash sudo systemctl restart docker ``` 2. **Check kernel modules are loaded**: ```bash lsmod | grep bridge lsmod | grep veth ``` If missing, load them: ```bash sudo modprobe bridge sudo modprobe veth ``` 3. **Build directly with docker build** (bypasses compose networking - RECOMMENDED): ```bash # Build the image directly DOCKER_BUILDKIT=0 docker build -t meshcore-bot:latest . # Then use docker compose normally (it will use the existing image) docker compose up -d ``` This bypasses Docker Compose's networking setup during build, which often fails on ARM devices. 4. **Use host network mode for build** (alternative): ```bash DOCKER_BUILDKIT=0 docker build --network=host -t meshcore-bot:latest . docker compose up -d ``` 5. **Check Docker bridge configuration**: ```bash sudo brctl show ``` If bridge doesn't exist, Docker may need to be reconfigured. 6. **Check Docker daemon logs**: ```bash sudo journalctl -u docker -n 50 ``` 7. **Reinstall Docker** (if other solutions fail): ```bash # Backup your data first! sudo apt-get remove docker docker-engine docker.io containerd runc # Then reinstall Docker following Armbian/Docker official instructions ``` ## Production Deployment For production deployments: 1. **Use specific image tags** instead of `latest`: ```yaml image: ghcr.io/your-username/meshcore-bot:v1.0.0 ``` 2. **Set resource limits** in `docker-compose.yml`: ```yaml deploy: resources: limits: cpus: '1.0' memory: 512M reservations: cpus: '0.5' memory: 256M ``` 3. **Use secrets management** for sensitive configuration: - Use Docker secrets (Docker Swarm) - Use environment variables for API keys - Mount secret files as read-only volumes 4. **Enable log rotation** (already configured in docker-compose.yml): ```yaml logging: driver: "json-file" options: max-size: "10m" max-file: "3" ``` 5. **Set up health checks** (already included in Dockerfile): The container includes a basic health check. Monitor with: ```bash docker-compose ps ``` ## Backup and Restore ### Backup ```bash # Backup databases docker-compose exec meshcore-bot tar czf /data/backups/backup-$(date +%Y%m%d).tar.gz /data/databases # Or from host tar czf backups/backup-$(date +%Y%m%d).tar.gz data/databases/ ``` ### Restore ```bash # Stop container docker-compose down # Restore databases tar xzf backups/backup-YYYYMMDD.tar.gz -C data/ # Start container docker-compose up -d ``` ## Security Considerations 1. **Non-root user**: The container runs as a non-root user (UID 1000) 2. **Read-only config**: Config directory is mounted read-only to prevent accidental modifications 3. **Network isolation**: By default, containers are isolated. Only expose ports you need 4. **Secrets**: Never commit API keys or sensitive data to version control. Use environment variables or secrets management 5. **Web viewer**: If enabled, ensure it's only accessible on trusted networks or use a reverse proxy with authentication ## Connecting COM Ports to Docker on Windows 11 {#connecting-com-ports-to-docker-on-windows-11} On Windows 11, Docker runs inside a Linux VM (WSL2). Linux does not see Windows COM ports by default, so the bot may fail with: ``` Connection failed: [Errno 2] could not open port COM3: [Errno 2] No such file or directory: 'COM3' ``` Even if the port works in Windows (e.g. in Device Manager or in [app.meshcore.nz](https://app.meshcore.nz)), you must **pass the USB device from Windows into WSL** so the container can use it. **1. Install the USB bridge** Open **PowerShell as Administrator** and run: ```powershell winget install --id Microsoft.usbipd-win ``` Restart your computer if prompted. **2. Identify and share the radio** With the radio plugged in, in PowerShell: - **Find the device**: Run `usbipd list`. Note the **BUSID** for your radio (e.g. `2-3`). - **Bind it**: Run `usbipd bind --busid `. - **Attach to WSL**: Run `usbipd attach --wsl --busid `. **Important:** Close any app that is using the serial port (e.g. the [app.meshcore.nz](https://app.meshcore.nz) browser tab) before binding. Only one process can own the port at a time. **3. Use the Linux device name in Docker** After attaching, the device in WSL is no longer `COM3`. It will typically appear as `/dev/ttyUSB0`. To confirm, inside WSL run: ```bash ls /dev/tty* ``` **4. Update Docker and config** In `docker-compose.yml`, add (or adjust) the device mapping: ```yaml devices: - "/dev/ttyUSB0:/dev/ttyUSB0" ``` In `config.ini`, set the serial port to the Linux device: ```ini [Connection] connection_type = serial serial_port = /dev/ttyUSB0 ``` **Notes:** - Bind/attach is **not persistent**. After a reboot or unplugging the radio, run `usbipd bind` and `usbipd attach --wsl` again (or use a script). - To attach to the Docker Desktop distro specifically: `usbipd attach --wsl --busid --distribution docker-desktop` (Use `usbipd --help` to see your exact distribution name.) ## Additional Resources - [Docker Documentation](https://docs.docker.com/) - [Docker Compose Documentation](https://docs.docker.com/compose/) - [Main README](https://github.com/agessaman/meshcore-bot/blob/main/README.md) for general bot configuration.