# Docker API Service Detection

- **URL:** https://hackindex.io/services/docker-api/enumeration/docker-api-service-detection
- **Path:** Docker API > Enumeration
- **Up:** [Enumeration](https://hackindex.io/services/docker-api/enumeration.md)
- **Published:** 2026-04-04
- **Updated:** 2026-04-04

The Docker daemon exposes a REST API on port 2375 (plaintext) and port 2376 (TLS). When either port is reachable without authentication, any client has full control over the Docker engine: running containers, images, volumes, and the host filesystem via container mounts. Unauthenticated Docker API exposure is a critical misconfiguration that leads directly to host compromise. Port 2375 is the most dangerous: it requires no credentials and no TLS. Port 2376 should require a valid client certificate but is often misconfigured to accept any connection.

- Port Detection
- Confirm API Access: Version Endpoint
- Enumerate Running Containers
- List All Images
- Use Docker Client Directly

## Port Detection

```bash
nmap -sV -p 2375,2376 $TARGET_IP
# 2375/tcp open  docker  Docker 20.10.21
# 2376/tcp open  docker  Docker 20.10.21 (TLS)
```

## Confirm API Access: Version Endpoint

The `/version` endpoint requires no authentication and immediately confirms whether the API is reachable:

```bash
curl -sk http://$TARGET_IP:2375/version | python3 -m json.tool
# {
#   "Version": "20.10.21",
#   "ApiVersion": "1.41",
#   "Os": "linux",
#   "Arch": "amd64",
#   "KernelVersion": "5.15.0-91-generic",
#   "GoVersion": "go1.18.1"
# }
```

A JSON response confirms the API is accessible without credentials. The kernel version is immediately useful for local privilege escalation research if you land in a container. Check TLS port the same way:

```bash
curl -sk https://$TARGET_IP:2376/version | python3 -m json.tool
```

## Enumerate Running Containers

```bash
curl -sk http://$TARGET_IP:2375/containers/json | python3 -m json.tool | grep -iE '"Id"|"Names"|"Image"|"Status"|"Ports"'
# "Id": "a1b2c3d4e5f6...",
# "Names": ["/webapp"],
# "Image": "nginx:latest",
# "Status": "Up 3 days",
# "Id": "b2c3d4e5f6a7...",
# "Names": ["/db"],
# "Image": "mysql:8.0",
# "Status": "Up 3 days"
```

```bash
# List all containers including stopped ones
curl -sk 'http://$TARGET_IP:2375/containers/json?all=true' | python3 -m json.tool | grep -iE '"Names"|"Image"|"Status"'
```

## List All Images

```bash
curl -sk http://$TARGET_IP:2375/images/json | python3 -m json.tool | grep -iE '"RepoTags"|"Size"'
# "RepoTags": ["nginx:latest"],
# "RepoTags": ["mysql:8.0"],
# "RepoTags": ["webapp:production"]
```

## Use Docker Client Directly

Setting `DOCKER_HOST` lets you use the standard docker CLI against the remote API: much faster than crafting curl requests:

```bash
export DOCKER_HOST=tcp://$TARGET_IP:2375
docker version
docker ps
docker images
# Server: Docker Engine
#  CONTAINER ID   IMAGE          STATUS
#  a1b2c3d4e5f6   nginx:latest   Up 3 days
#  b2c3d4e5f6a7   mysql:8.0      Up 3 days
```

The docker CLI now communicates with the remote daemon. All docker commands run against the target. Move to [unauthenticated access assessment](https://hackindex.io/services/docker-api/vulnerability-discovery/docker-api-unauthenticated-access) to confirm the full attack surface, then to [container escape](https://hackindex.io/services/docker-api/exploitation/docker-api-container-escape) for host compromise.

## References

- [Docker Engine API](https://docs.docker.com/engine/api/) - Full REST API reference including /version, /containers, and /images endpoints
