Install
$ agentstack add mcp-jeffqiu1989-icontainu ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
IcontainU
A native macOS GUI for Apple's container.
I — Apple's lowercase‑i lineage (iOS, iPhone) · contain — container · U — UI
Built with SwiftUI. No Electron, no daemon of its own — it just drives the container you already have.
English | [中文](README_zh.md)
Highlights
Two things make IcontainU worth your dock:
| ⚡ Smart Create | 🧩 One‑click Compose | | --- | --- | | | | | Drop in an image, the form fills itself. Ports, mounts, and the env vars the entrypoint actually needs (like MYSQL_ROOT_PASSWORD) are read from the image and pre‑filled. No more copying docker run snippets. | Bring a whole stack up in one click. Import a compose.yaml and Up the project in dependency order, with healthcheck gating. Projects persist across down and restarts — and it works around Apple container's broken container‑to‑container DNS so service names just resolve. |
More features
- 🐧 Machines that just work — presets pointing at official init‑ready images (Alpine, Rocky UBI‑init), so machines actually boot. CPU, memory, and home‑mount are all settable.
- 📦 Smart image pull — pulls only your host architecture, and is registry‑mirror aware with a one‑click DaoCloud preset (9 registries, individually toggleable) that leaves no trace on local images.
- 🔨 Image building - build container images from a Dockerfile via the shared BuildKit builder, with no-cache toggle, live build log, and per-config build history.
- 🃏 Everything on a card — Start / Stop / Shell / Logs / Delete per container, plus a live stats tab and streaming logs.
- ✨ Friction removers — tap to copy an IP or
ip:port, tap a mount to open it in Finder, local‑image autocomplete, and Docker‑style auto‑naming. - 🚀 Frictionless setup — first launch auto‑installs the kernel and monitors
containerhealth for you. - 🤖 MCP server - a built-in Model Context Protocol server exposes every container, image, machine, volume, network, and Compose operation as a tool, so Claude Code, OpenCode, or any MCP client can drive IcontainU remotely over HTTP with a Bearer API key. See [docs/mcpserver.md](docs/mcp_server.md) for the full 25-tool API.
Screenshots
| Containers | Create a container | | --- | --- | | | |
| Create a machine | Images | | --- | --- | | | |
| Registry mirrors | Built-in MCP server | | --- | --- | | | |
Requirements
- Apple silicon Mac (M‑series), macOS 26 or newer
- Apple
container≥ 1.0.0 installed
Start the system once from the CLI so it installs the kernels (faster than the in‑app download):
container system start
container system status # should report: running
Without a running container system the app still opens, but the sidebar stays empty.
Download & install
Download IcontainU-v0.5.0.zip from [Releases](../../releases), unzip, and move IcontainU.app to Applications.
Not notarized — on first launch, right‑click → Open, or run:
xattr -d com.apple.quarantine /Applications/IcontainU.app
Build from source
Requires the Swift 6.2 toolchain (Xcode 26).
swift build && swift run IcontainU
# package a signed .app:
./scripts/package-app.sh
Status & known limitations
0.5.0 — early, but useful day to day.
Shellopens Terminal.app — no embedded terminal yet.- System configuration is view‑only in the app; edit it via the CLI.
- Menu bar support is under development.
- Compose does not support
build:- use the standalone Build feature to build images, then reference them by tag inimage:.
Compose reference
IcontainU supports a practical subset of the Compose spec. Anything unsupported is surfaced as a warning banner at import — never silently dropped.
Supported fields & what's not
| Field | Notes | | --- | --- | | image | — | | command | string or array form | | ports | numeric and host:container/proto | | environment | list ["K=V"] and map {K: V} | | volumes | named (vol:/data) and bind (/host:/data[:ro], incl. relative ./) | | networks | per‑service and top‑level | | depends_on | start order and condition: service_healthy | | healthcheck | test, interval, timeout, retries, start_period | | container_name, user | — | | top‑level networks: / volumes: | — |
Plus ${VAR} / .env interpolation at parse time.
Not supported:
| Field | Notes | | --- | --- | | build: | — | | restart: | — | | deploy.replicas / scale | — | | env_file | — | | profiles | — | | secrets | — | | configs | — | | extends | — | | YAML anchors | — | | advanced driver_opts | — |
Project isolation & multi‑network
- Every project is namespaced. Containers, volumes and networks are prefixed with the project name, so two projects that each declare a
dbservice run side by side. Pinning the samecontainer_name:in two projects fails loudly instead of hijacking. - Multi‑network is fully supported. A service on several networks resolves each peer on a network the two containers actually share.
Healthcheck gating — how service_healthy is honored
Apple container 1.0.0 has no native healthcheck, so IcontainU runs the probe via container exec during Up to gate depends_on: { condition: service_healthy }. There is no always‑on healthy/unhealthy badge.
- If a gated dependency never becomes healthy, Up fails but the dependency is left running so its logs explain why — fix the compose file and re‑Up.
- A
service_healthydependency with no healthcheck warns and is treated as start‑order only.
Runtime constraints — Apple container on macOS 26 (not IcontainU bugs)
- Container‑to‑container DNS is broken on macOS 26 — IcontainU works around it by injecting
→ real IPinto each container's/etc/hostsafter Up. - Database data dirs on bind mounts — the chown problem and how to fix it.
On macOS, the bind-mount root is owned by the host user and refuses chown. Images that chown their data directory at startup fail with "Operation not permitted" when the data directory is the mount-point root:
``` # MySQL / MariaDB chown: changing ownership of '/var/lib/mysql/': Operation not permitted
# PostgreSQL ≤17 chmod: changing permissions of '/var/lib/postgresql/data': Operation not permitted chown: changing ownership of '/var/lib/postgresql/data': Operation not permitted ```
Affected versions:
- PostgreSQL 17 and below —
PGDATAdefaults to/var/lib/postgresql/data, which is the mount-point root → fails. - PostgreSQL 18+ —
PGDATAdefaults to a subdirectory (/var/lib/postgresql/18/docker) → no issue, works out of the box. - MySQL / MariaDB — all versions are affected.
Fix: point the data directory at a subdirectory of the mount instead. The image-specific setting that controls this differs per image:
| Image | Fix | Example compose snippet | | --- | --- | --- | | PostgreSQL ≤17 | Set PGDATA to a subdirectory | environment: PGDATA: /var/lib/postgresql/data/pgdata | | MySQL / MariaDB | Pass --datadir pointing to a subdirectory | command: ["--datadir", "/var/lib/mysql/data"] |
Ready-to-use templates with the fix pre-applied are in [samples/](samples/):
- [
template-postgres-17.yaml](samples/template-postgres-17.yaml) — PostgreSQL 17 with bind-mounted data dir - [
template-mysql.yaml](samples/template-mysql.yaml) — MySQL 8 with bind-mounted data dir
Import via Compose → New Project, edit the password and host path, then Up.
- Non‑root images need
user: "0"on a named volume, otherwise they can't write their data dir.
Samples
The [samples/](samples/) directory ships Compose templates you can import via Compose → New Project and Up directly. Each one is verified to run on IcontainU.
| Stack | Services | Notes | |---|---|---| | [postgresql-pgadmin](samples/postgresql-pgadmin/) | PostgreSQL + pgAdmin | ${VAR} placeholder template — edit passwords before import | | [gitea-postgres](samples/gitea-postgres/) | Gitea + PostgreSQL | Named volumes, restart: always | | [nextcloud-postgres](samples/nextcloud-postgres/) | Nextcloud + PostgreSQL | | | [nextcloud-redis-mariadb](samples/nextcloud-redis-mariadb/) | Nextcloud + Redis + MariaDB | Multi-network demo (separate dbnet / redisnet) | | [wordpress-mysql](samples/wordpress-mysql/) | WordPress + MariaDB | | | [elasticsearch-logstash-kibana](samples/elasticsearch-logstash-kibana/) | ELK stack (ES 8 + Logstash + Kibana) | Full healthcheck + depends_on: condition: service_healthy | | [prometheus-grafana](samples/prometheus-grafana/) | Prometheus + Grafana | user: "0" for named-volume write; bind mounts for config | | [postgres-healthcheck](samples/postgres-healthcheck/) | PostgreSQL + Alpine | Minimal healthcheck / service_healthy demo | | [kafka-cluster-kraft](samples/kafka-cluster-kraft/) | Kafka 4.3.1 KRaft (3 controllers + 3 brokers) | Advertised listeners on hostnames; depends_on startup | | [redis-cluster](samples/redis-cluster/) | Redis 7 cluster | 3-master / 3-replica with auto-failover; cluster-announce-hostname + /etc/hosts DNS workaround | | [redis-cluster-envoy-proxy](samples/redis-cluster-envoy-proxy/) | Redis cluster + Envoy proxy | Slot-aware Envoy proxy at host:6379 — plain redis-cli, no -c flag needed | | [template-mysql.yaml](samples/template-mysql.yaml) | MySQL 8 (single) | Standalone template; bind-mount data dir with --datadir subdirectory (macOS chown fix) | | [template-postgres-17.yaml](samples/template-postgres-17.yaml) | PostgreSQL 17 (single) | Standalone template; PGDATA subdirectory bind-mount (macOS chown fix) |
> macOS bind-mount note: some samples use bind-mounted data directories. On macOS the mount root is owned by the host user and can't be chown'd. Images that need chown on their data dir (MySQL, PostgreSQL ≤ 17) are pointed at a subdirectory via --datadir / PGDATA — the templates already handle this. See the [Compose reference](#compose-reference) for details.
MCP server
IcontainU ships an embedded Model Context Protocol server, so an AI client can operate containers, images, machines, volumes, networks, and Compose projects on your behalf - useful for "bring this stack up and verify it's healthy" workflows driven from Claude Code, OpenCode, or any MCP-compatible client.
- Transport: MCP over Streamable HTTP at
/mcp(swift-nio server, default port3000). - Auth: Bearer API key, generated and managed in the in-app MCP panel. Constant-time comparison; no key, no access.
- Bind:
127.0.0.1(localhost only) by default; switch to0.0.0.0in the panel to reach it from the LAN.
25 tools across 6 resource groups:
| Resource | Tools | | --- | --- | | Container | list, create, start, stop, delete, exec, logs, inspect | | Image | list, pull, delete | | Machine | list, boot, stop, delete | | Volume | list, create, delete | | Network | list, create, delete | | Compose | list, up, down, status |
Full tool schemas, parameters, and examples: [docs/mcpserver.md](docs/mcpserver.md).
Quick start from a client config (.mcp.json):
{
"mcpServers": {
"containers": {
"url": "http://127.0.0.1:3000/mcp",
"headers": { "Authorization": "Bearer " }
}
}
}
License & acknowledgements
Licensed under the Apache License 2.0 — see [LICENSE](LICENSE). Built on Apple's container and containerization; see [NOTICE](NOTICE) for attribution.
Developed with the assistance of vibe coding (AI-assisted development).
Thanks to the LINUX DO community for providing a platform for communication and learning.
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: jeffqiu1989
- Source: jeffqiu1989/IcontainU
- License: Apache-2.0
- Homepage: https://jeffqiu1989.github.io/IcontainU/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.