# Docker

Docker daemon on the VPS and apps as Compose projects: image, private registry, repo or Compose, with optional HTTPS.

Source: https://ardumaker.com/en/docs/docker/

- Category: Servers and infrastructure
- Status: Available
- Requirements: An active VPS with the `docker` feature available (Ubuntu 22.04 has it); At least 256 MB of free RAM and 1 GB of free disk, as measured; Being a member with access to the VPS to install; admin to uninstall
- MCP tools (Read only): `ver_catalogo_apps`, `ver_preflight_app`, `listar_apps_empresa`, `ver_app`, `ver_operacion_app`
- MCP tools (Write or modify): `instalar_app`, `controlar_app`, `reintentar_operacion_app`, `refrescar_apps`
- MCP tools (Destructive): `desinstalar_app`

## What can you do with it?

Docker on ArduMaker has two parts: the daemon, which is a capability of the VPS, and Docker apps, each one its own Compose project that the platform writes, starts, observes and removes.

- Install the daemon in one click (or let the first app that needs it install it).
- Deploy a public image, an image from a private registry with a token, or a GitHub repo with a Dockerfile.
- Deploy an advanced Compose (as a JSON object) with several services.
- Start, stop and restart the project, and publish it with HTTPS if it exposes a web port.
- From the VPS Docker tab: list containers, see their logs, stop, restart or delete them, and see images, volumes and networks.

## When should you use it?

- An application already packaged as an image (a dashboard, an internal tool, a third-party service).
- Several services started together with Compose.
- For your own GitHub code with a non-Docker process, [GitHub deploy](https://ardumaker.com/en/docs/github-deploy) is the better fit.

## How does it work in ArduMaker?

### The daemon

New VPS are born with the container permissions Docker needs, without being privileged. An older VPS that lacks them gets them when Docker is installed and needs a restart (the preflight warns with `requiere_reinicio_vps`). The daemon is installed with the `docker.io` package and `fuse-overlayfs`, with `userns-remap` enabled: container processes do not run as the VPS's real `root`.

### A Docker app

1. The configuration and the preflight are validated (system feature, Docker possible on the host, memory and disk).
2. If the daemon is missing it is installed; if another installation is in progress, the operation waits and is retried.
3. `/opt/ardumaker-apps/app<id>/docker-compose.yml` is written (keeping a copy of the previous one) and validated with `docker compose config`; if it does not validate, the previous one is restored.
4. `docker compose -p app<id> up -d --remove-orphans` runs as a long step, so a heavy pull does not time out.
5. If there is a `port`, it is published with HTTPS and the link is verified.

Every container carries the `ardumaker.app_id` label and the project is named `app<id>`: the name is not chosen by the user and the platform never touches anything outside it. Redeploying is idempotent: the same file and `up -d` do not recreate what did not change.

## What actually changes?

| What | Where |
| --- | --- |
| Compose file | `/opt/ardumaker-apps/app<id>/docker-compose.yml` |
| Cloned code (repo mode) | `/opt/ardumaker-apps/app<id>/src` |
| Data with relative path | `/opt/ardumaker-apps/app<id>/datos` |
| Named volumes | Owned by the project (`data<i>` in simple mode) |
| Private registry token | Encrypted on the platform; the VPS runs `docker login` with the token on stdin |

## Docker app configuration

| Mode | Keys |
| --- | --- |
| Image | `image`, `port`, `container_port`, `env` (hasta 50), `volumes`, `health_path`, `registry` |
| GitHub repo | `repo_id`, `branch`, `port`, `container_port`, `env`, `volumes`, `health_path` |
| Advanced Compose | `compose` (JSON object, not YAML) and optional `port` |

- `image`, `compose` and `repo_id` are mutually exclusive.
- `port` is the VPS port (from 1024 and never a protected one); with `port`, `container_port` is required. `"auto"` picks a free one.
- Ports are published only on `127.0.0.1`: a container is never directly open to the internet.
- `env` does not accept secret-like names (`*_PASSWORD`, `*_TOKEN`…): the configuration does not store secrets.

## What a Compose rejects

Each service accepts an allowlist of keys (`image`, `command`, `entrypoint`, `environment`, `ports`, `volumes`, `restart`, `depends_on`, `healthcheck`, `working_dir`, `user`, `expose`, `networks`, `mem_limit`, `cpus`, `labels`, `tmpfs`, `stop_grace_period`, `read_only`, `init`). Rejections come with a code per path (`compose.services.<service>.<key>`):

| Code | What triggers it |
| --- | --- |
| `privileged` | `privileged`, `devices`, `security_opt`, `userns_mode` |
| `network_mode_host` | `network_mode: host` |
| `pid_host` | Host `pid` or `ipc` |
| `cap_add` | Extra capabilities |
| `docker_socket` | Mounting `docker.sock`, `/run` or `/var/run` |
| `host_mount` | Absolute paths, `~` or `..` (only `./something` inside its own folder) |
| `puerto_publico` | Any port other than `127.0.0.1:H:C` |

`build`, `container_name`, `env_file`, `configs`, `secrets`, `extends` and `name` are not accepted either, nor `com.docker.*` or `ardumaker.*` labels.

## Uninstalling and data

Uninstalling runs `docker compose down --remove-orphans`, force-removes the containers labelled with the project and deletes the Compose file. Volumes and the `./datos` folder stay, unless data deletion is requested: then `down -v` runs and the project folder is deleted. Nothing outside `app<id>` is touched.

> **PELIGRO:** With `delete_data` the uninstall is irreversible: the project's volumes are lost.

## Diagram

**A published Docker app**

```text
Internet (HTTPS on `docker-<id>` or a custom domain)
  ↓
VPS nginx (domain server block)
  ↓
`127.0.0.1:<port>` (only port published by the container)
  ↓
Compose project `app<id>` (containers labelled `ardumaker.app_id`)
  ↓
Volumes (persist until data deletion is requested)
```

Without `port` there is no URL: the app is managed from the Docker tab.

## Expected result

The app shows in Apps with its observed state: `running` if all its containers run, `stopped` if all are stopped, `degraded` if mixed and `missing` if none is left. With `port`, the HTTPS URL appears only after the link answered without a 5xx error.

```bash
docker compose -p app<id> ps
docker ps --filter label=com.docker.compose.project=app<id>
```

## Errors and troubleshooting

| Error | Cause | Retry? |
| --- | --- | --- |
| `requiere_docker` | The host does not support Docker | No |
| `requiere_reinicio_vps` | Container permissions are missing and the VPS must restart | After restarting |
| `recursos_insuficientes` | Less than 256 MB RAM or 1 GB disk free | After freeing resources |
| `docker_instalandose` / `docker_no_instalado` | The daemon is being installed or could not start | Yes |
| `compose_no_disponible` / `despliegue_fallido` / `baja_fallida` | Compose could not be prepared, pull or start failed, or `down` did not finish | Yes (`up -d` and `down` are idempotent) |
| `compose_invalido` | `docker compose config` rejected the file; the previous one was restored | No, it must be fixed |
| `puerto_ocupado` | Another app on the VPS publishes or declares that port | With another port |
| `config_invalida` | Disallowed key or secret in `env`; `fields` says which | After fixing the request |

> **PRECAUCION:** The n8n stack containers (`n8n-main`, `n8n-postgres`, `n8n-redis`, workers and runners) are protected in the Docker tab: deleting them answers 409. They are operated from [n8n](https://ardumaker.com/en/docs/n8n).

## MCP access

Docker apps are operated over MCP with the Apps tools; the reference is at [/mcp/docs](https://ardumaker.com/en/mcp/docs) and [/mcp/servicios](https://ardumaker.com/en/mcp/servicios).

- Read: `ver_catalogo_apps`, `ver_preflight_app` (validates the exact `config` before installing), `listar_apps_empresa`, `ver_app`, `ver_operacion_app`.
- Modify: `instalar_app` with `app_type: docker` (requires `idempotency_key`), `controlar_app` (`start`, `stop`, `restart`), `reintentar_operacion_app`, `refrescar_apps`.
- Destructive: `desinstalar_app` (admins only, `confirm=true`; volumes are deleted only with `delete_data` and `confirm_delete_data`).

> **INFO:** There are no MCP tools for the Docker tab (loose containers, images, networks). Installing Docker or a container by hand with `ejecutar_comando_vps` leaves something the platform does not list, restart or back up.

## Related features

- [VPS servers](https://ardumaker.com/en/docs/vps/)
- [n8n](https://ardumaker.com/en/docs/n8n/)
- [GitHub deploy](https://ardumaker.com/en/docs/github-deploy/)
- [Nginx](https://ardumaker.com/en/docs/nginx/)
- [SSL certificates](https://ardumaker.com/en/docs/ssl/)
