Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: CI

on:
push:
branches: [ main, v1.52 ]
pull_request:
branches: [ main, v1.52 ]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flask pytest
- name: Run tests
run: pytest -q

smoke-termux:
# This job is intended to run on a self-hosted Termux runner (Android device)
runs-on: [self-hosted, termux-android]
steps:
- uses: actions/checkout@v4
- name: Make smoke script executable
run: chmod +x tests/integration/smoke_termux.sh
- name: Run Termux smoke test (self-hosted)
run: |
./tests/integration/smoke_termux.sh

smoke-ubuntu:
# Best-effort smoke test on ubuntu-latest. This tries to install udocker and run the same smoke script.
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install udocker (best-effort)
run: |
python -m pip install --upgrade pip
pip install udocker || true
udocker --version || true
- name: Make smoke script executable
run: chmod +x tests/integration/smoke_termux.sh
- name: Run smoke test (best-effort)
run: |
./tests/integration/smoke_termux.sh
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Changelog

## [v1.52] - 2025-12-21

### Added
- Added `/v1.52` route aliases for all existing endpoints to maintain backward compatibility while exposing new API behaviors.
- Improved container `inspect` response: normalized `Config.Env` to standard list of `KEY=VALUE` strings.
- Implemented logs streaming with support for `follow=1`, `timestamps=1`, `since`, and `idle_timeout` parameters.
- Implemented simple Docker-style multiplexing on logs when `stdout`/`stderr` selection implies multiplexing.
- Added stats streaming via `GET /containers/{id}/stats?stream=1` (finite sample stream for test determinism).
- Added unit tests for v1.52 endpoints, streaming behavior, and error cases.
- Added CI workflow to run tests on push/PR and ensure Flask is installed in CI.

### Changed
- Updated version metadata to report `ApiVersion: 1.52` in `/version` endpoint.
- Updated documentation and examples in `README.md`, `QUICKSTART.md`, `IMPLEMENTATION.md`, and `DOWNLOAD-INDEX.md` to reflect v1.52 compatibility.

### Fixed
- More tolerant parsing of `HostConfig.PortBindings` when creating containers and flexible insertion into `port_bindings` table.
- `db.get_logs()` supports timestamp prefixes and filtering via `since`.

### Notes
- Some features are still stubbed due to Udocker limitations (advanced networking, real resource stats). These are documented in `README.md` under Limitations.
25 changes: 18 additions & 7 deletions QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ chmod +x start_dashboard.sh
Output should show:
```
============================================================
🐳 Complete Udocker Docker API Shim (v1.43)
🐳 Complete Udocker Docker API Shim (v1.52)
📍 Listening on http://0.0.0.0:2375
✅ Features: Containers, Images, Networks, Volumes, Exec, Stats
============================================================
Expand All @@ -40,7 +40,7 @@ curl http://localhost:2375/_ping

### 5. List Containers
```bash
curl http://localhost:2375/v1.43/containers/json | jq
curl http://localhost:2375/v1.52/containers/json | jq
```

---
Expand All @@ -49,27 +49,27 @@ curl http://localhost:2375/v1.43/containers/json | jq

### List containers (with details)
```bash
curl http://localhost:2375/v1.43/containers/json?all=true | jq
curl http://localhost:2375/v1.52/containers/json?all=true | jq
```

### Get logs from a container
```bash
curl http://localhost:2375/v1.43/containers/CONTAINER_ID/logs
curl http://localhost:2375/v1.52/containers/CONTAINER_ID/logs
```

### Delete a container
```bash
curl -X DELETE http://localhost:2375/v1.43/containers/CONTAINER_ID
curl -X DELETE http://localhost:2375/v1.52/containers/CONTAINER_ID
```

### Get system info
```bash
curl http://localhost:2375/v1.43/info | jq
curl http://localhost:2375/v1.52/info | jq
```

### List images
```bash
curl http://localhost:2375/v1.43/images/json | jq
curl http://localhost:2375/v1.52/images/json | jq
```

---
Expand Down Expand Up @@ -120,6 +120,17 @@ sqlite3 udocker_state.db

---

## CI smoke test (optional)

You can run an integration smoke test on an Android Termux device by registering it as a self-hosted runner (label it `termux-android`) and running the `smoke-termux` job in CI, or run it locally:

```bash
chmod +x tests/integration/smoke_termux.sh
./tests/integration/smoke_termux.sh
```

---

## ✨ Features

✅ **40+ Docker API endpoints**
Expand Down
49 changes: 39 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Udocker Docker API Server (Complete Implementation)

A **production-ready Docker Engine API (v1.43) compatible server** that runs on Android Termux using Udocker. This allows you to manage Udocker containers as if they were Docker containers, compatible with Portainer, Docker CLI, and other Docker-compatible tools.
A **production-ready Docker Engine API (v1.52) compatible server** that runs on Android Termux using Udocker. This allows you to manage Udocker containers as if they were Docker containers, compatible with Portainer, Docker CLI, and other Docker-compatible tools.

## Files Included

- **`db.py`** - SQLite database layer for persistent container/image state tracking
- **`container_manager.py`** - High-level container lifecycle management with background monitoring
- **`dashboard.py`** - Full Docker API v1.43 server implementation (complete all endpoints)
- **`dashboard.py`** - Full Docker API v1.52 server implementation (complete all endpoints)
- **`start_dashboard.sh`** - Launcher script with environment setup
- **`portainer.sh`** - Example: Portainer container script (from previous setup)
- **`udocker_state.db`** - Auto-generated SQLite database (DO NOT EDIT)
Expand Down Expand Up @@ -100,12 +100,12 @@ curl http://localhost:2375/_ping

### List All Containers
```bash
curl http://localhost:2375/v1.43/containers/json | jq
curl http://localhost:2375/v1.52/containers/json | jq
```

### Launch a Script-Based Container
```bash
curl -X POST http://localhost:2375/v1.43/containers/create \
curl -X POST http://localhost:2375/v1.52/containers/create \
-H "Content-Type: application/json" \
-d '{
"Image": "portainer/portainer-ce:alpine",
Expand All @@ -121,14 +121,25 @@ curl -X POST http://localhost:2375/v1.43/containers/create \

### Get Container Logs
```bash
curl http://localhost:2375/v1.43/containers/CONTAINER_ID/logs
curl http://localhost:2375/v1.52/containers/CONTAINER_ID/logs
```

Options: `tail`, `since` (unix seconds), `timestamps=1`, `follow=1` (stream), `multiplex=1|0` (force multiplex), `heartbeat` (seconds, keepalive), `idle_timeout` (seconds to close follow when idle).

Examples:
```bash
# Stream logs with timestamps and follow
curl -N "http://localhost:2375/v1.52/containers/CONTAINER_ID/logs?follow=1&timestamps=1"

# Get logs since timestamp
curl "http://localhost:2375/v1.52/containers/CONTAINER_ID/logs?since=1710000000"
```

### Stop and Delete a Container
```bash
curl -X POST http://localhost:2375/v1.43/containers/CONTAINER_ID/stop
curl -X POST http://localhost:2375/v1.52/containers/CONTAINER_ID/stop

curl -X DELETE http://localhost:2375/v1.43/containers/CONTAINER_ID
curl -X DELETE http://localhost:2375/v1.52/containers/CONTAINER_ID
```

## Database
Expand Down Expand Up @@ -254,10 +265,10 @@ ssh -L 2375:localhost:2375 user@phone-ip

## API Versioning

This implementation supports Docker API v1.43 (current as of 2024).
This implementation supports Docker API v1.52.

Routes support both:
- `/v1.43/containers/json` (versioned)
- `/v1.52/containers/json` (versioned)
- `/containers/json` (default)

## Support
Expand All @@ -268,8 +279,26 @@ For issues:
3. Check database: `sqlite3 udocker_state.db`
4. Test endpoint: `curl http://localhost:2375/_ping`

## CI Self-hosted Termux Runner (smoke tests)

If you want CI to run a smoke-test on an Android device running Termux, register that device as a **self-hosted runner** in your repository and add the label `termux-android` to it. The workflow includes a `smoke-termux` job which will execute `tests/integration/smoke_termux.sh` on that runner.

Steps:

1. On GitHub, go to your repository > Settings > Actions > Runners > Add runner and follow the registration steps for your Android device (Termux supports the runner binary via `chmod +x` and running the provided script).
2. When registering the runner, add the label `termux-android` (so the job matches `runs-on: [self-hosted, termux-android]`).
3. Ensure `udocker` is installed on the device and available in PATH.
4. Run the `smoke-termux` job from a PR or workflow run; it will start the dashboard (if not running), exercise container create/start/logs/stop/delete, and report success or failure.

You can also run the test locally on the device:

```bash
chmod +x tests/integration/smoke_termux.sh
./tests/integration/smoke_termux.sh
```

---

**Created**: 2025-12-21
**Version**: 1.0 (Complete Docker API v1.43)
**Version**: 1.0 (Complete Docker API v1.52)
**Tested On**: Android Termux with Udocker
21 changes: 21 additions & 0 deletions RUNNER_STATUS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Runner Registration Status

Repository: xeniosrahi/Termux-Udocker-API
Branch: v1.52

Runner Registered: false
Runner Label: termux-android
Runner Name: termux-android-1 (suggested)

Notes:
- Use this file to mark whether a Termux self-hosted runner has been registered for CI smoke tests.
- To register the runner, follow the instructions in `README.md` > "CI Self-hosted Termux Runner (smoke tests)" or the `docs/SDK-vs-shim.md` runner section.
- After successful registration and a green smoke run, update `Runner Registered: true` and optionally record the runner name & timestamp.

Example record after registration:

Runner Registered: true
Registered At: 2025-12-21T12:34:56Z
Runner URL: https://github.com/xeniosrahi/Termux-Udocker-API/actions/runners
Runner Notes: udocker installed; tested smoke-termux job

12 changes: 6 additions & 6 deletions core/DOWNLOAD-INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Must download all 4 to your `~/Termux-Udocker/` directory:
- Required by: dashboard.py

3. **`dashboard.py`** ⭐
- Docker API v1.43 server (Flask)
- Docker API v1.52 server (Flask)
- 40+ REST endpoints
- Depends on: container_manager.py, db.py

Expand Down Expand Up @@ -170,7 +170,7 @@ udocker_state.db (auto-created)
- Real-time log retrieval

### ✅ API Compatibility
- Docker Engine API v1.43
- Docker Engine API v1.52
- Portainer integration
- Docker CLI compatibility

Expand Down Expand Up @@ -203,9 +203,9 @@ udocker start <container>
### After (Docker API Server)
```bash
# REST API compatible
curl http://localhost:2375/v1.43/containers/json
curl http://localhost:2375/v1.43/containers/{id}/logs
curl -X POST http://localhost:2375/v1.43/containers/{id}/start
curl http://localhost:2375/v1.52/containers/json
curl http://localhost:2375/v1.52/containers/{id}/logs
curl -X POST http://localhost:2375/v1.52/containers/{id}/start

# Portainer compatible
# Docker CLI compatible
Expand Down Expand Up @@ -280,7 +280,7 @@ Once you have the 4 core files in place, you're ready to:

## 📝 Version Info

- **Implementation**: Docker API v1.43
- **Implementation**: Docker API v1.52
- **Date**: December 21, 2025
- **Status**: ✅ Complete & Production-Ready
- **Platform**: Android Termux with Udocker
Expand Down
18 changes: 9 additions & 9 deletions core/IMPLEMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
- Integration with udocker commands

### 3. **dashboard.py** (Docker API Server)
- **Purpose**: Flask REST API server compatible with Docker Engine v1.43
- **Purpose**: Flask REST API server compatible with Docker Engine v1.52
- **Size**: ~45 KB
- **Endpoints Implemented**: 40+
- **Features**:
Expand Down Expand Up @@ -58,7 +58,7 @@
┌─────────────────────────────────────────────────┐
│ Flask Server (dashboard.py) │
│ - 40+ Docker API v1.43 endpoints │
│ - 40+ Docker API v1.52 endpoints │
│ - JSON response formatting │
│ - Error handling & validation │
└────────────────┬────────────────────────────────┘
Expand Down Expand Up @@ -109,9 +109,9 @@
- Detects crashed containers
- Logs state changes

### ✅ **Docker API v1.43 Compatible**
### ✅ **Docker API v1.52 Compatible**
- 40+ endpoints implemented
- Supports both `/v1.43/` and shorthand routes
- Supports both `/v1.52/` and shorthand routes
- Proper HTTP status codes
- JSON response formatting
- Error messages
Expand Down Expand Up @@ -161,27 +161,27 @@ curl http://localhost:2375/_ping

### List Containers
```bash
curl http://localhost:2375/v1.43/containers/json
curl http://localhost:2375/v1.52/containers/json
```

### Start Container
```bash
curl -X POST http://localhost:2375/v1.43/containers/{id}/start
curl -X POST http://localhost:2375/v1.52/containers/{id}/start
```

### Get Logs
```bash
curl http://localhost:2375/v1.43/containers/{id}/logs
curl http://localhost:2375/v1.52/containers/{id}/logs
```

### Delete Container
```bash
curl -X DELETE http://localhost:2375/v1.43/containers/{id}
curl -X DELETE http://localhost:2375/v1.52/containers/{id}
```

### Get System Info
```bash
curl http://localhost:2375/v1.43/info
curl http://localhost:2375/v1.52/info
```

---
Expand Down
Binary file added core/__pycache__/dashboard.cpython-312.pyc
Binary file not shown.
Binary file added core/__pycache__/models.cpython-312.pyc
Binary file not shown.
4 changes: 3 additions & 1 deletion core/container_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import threading
from datetime import datetime
from db import ContainerDB
import json
import models

db = ContainerDB()

Expand Down Expand Up @@ -125,7 +127,7 @@ def inspect_container(cid):
"Created": datetime.fromtimestamp(db_info['created_at']).isoformat() + "Z",
"PortBindings": ports,
"RestartCount": db_info['restart_count'],
"Env": json.loads(db_info['env_vars'] or '{}')
"Env": models.normalize_env(json.loads(db_info['env_vars'] or '[]'))
}

@staticmethod
Expand Down
Loading
Loading