Skip to content
Open
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
97 changes: 97 additions & 0 deletions docs/container-compose.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# container-compose

`container-compose` is a Python script that provides a `docker-compose`-compatible interface for Apple's `container` CLI. It reads a standard `docker-compose.yml` file and translates each subcommand into the equivalent `container` invocations, so you can bring up multi-container applications without rewriting your existing compose files.

## Why container-compose

The `container` CLI operates on individual containers. Many projects describe their services in a `docker-compose.yml` that coordinates several containers, their networks, and their volumes. `container-compose` bridges that gap: it parses the compose file, creates the required networks and volumes, respects `depends_on` ordering, and runs each service as a labelled `container run` invocation so they can later be queried and torn down as a group.

## Prerequisites

- Apple `container` installed and the system service started (`container system start`)
- Python 3.11 or later
- PyYAML: `pip3 install pyyaml --break-system-packages`

## Install

Copy the script to a directory on your `PATH`:

```bash
cp examples/compose-example/container-compose /usr/local/bin/container-compose
chmod +x /usr/local/bin/container-compose
```

## Quickstart

```bash
# Start all services defined in docker-compose.yml (detached by default)
container-compose up

# Check running services
container-compose ps

# Stream logs from all services
container-compose logs -f

# Stop and remove containers and networks
container-compose down
```

## Supported subcommands

| Subcommand | Description |
|------------|-------------|
| `up [-d] [--build] [service…]` | Create networks and volumes, then start services in dependency order |
| `down [-v]` | Stop and delete containers and networks; `-v` also removes named volumes |
| `ps` | List containers for the current project |
| `logs [-f] [--tail N] [service…]` | Print (or follow) container output |
| `exec <service> <cmd…>` | Run a command in a running service container |
| `build [--no-cache] [service…]` | Build images from `build:` definitions |
| `pull [service…]` | Pull service images |
| `start / stop / restart [service…]` | Start, stop, or restart existing containers |
| `rm [-f] [-s] [service…]` | Remove stopped containers; `-s` stops them first |
| `run [--rm] <service> [cmd…]` | Run a one-off command on a service |
| `config` | Print the parsed compose configuration |

## Supported compose keys

The following keys are translated to `container run` flags:

- `image`, `build` (context, dockerfile, args)
- `command`, `entrypoint`
- `environment`, `env_file`
- `ports`, `volumes` (bind mounts and named volumes), `tmpfs`
- `networks` (first network only — see limitations below)
- `depends_on` (list and `condition` dict form)
- `labels`, `container_name`
- `mem_limit`, `cpus`, `deploy.resources.limits`
- `cap_add`, `cap_drop`
- `working_dir`, `user`
- `tty`, `stdin_open`
- `dns`, `dns_search`
- `read_only`, `init`
- `shm_size`

## Project isolation

Every resource (container, network, volume) is tagged with the project name, which defaults to the current directory name. Override it with `-p` or the `COMPOSE_PROJECT_NAME` environment variable:

```bash
container-compose -p staging up
```

All `container-compose` commands scope their queries to the project label, so multiple projects can coexist on the same host.

## Known limitations

The following `docker-compose` features are not yet supported by the `container` CLI and are silently ignored or warned about:

| Feature | Notes |
|---------|-------|
| Multiple networks per service | `container` does not support `network connect` after run; only the first declared network is attached |
| `extra_hosts: host-gateway` | Docker-specific alias; use an explicit IP instead |
| `restart` policies | `container run` has no `--restart` flag yet |
| `healthcheck` | Not surfaced on `container inspect` output |
| Swarm / deploy keys beyond `resources.limits` | Ignored |

See [examples/compose-example](../examples/compose-example/) for a working walkthrough.
2 changes: 2 additions & 0 deletions examples/compose-example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
__pycache__/
*.pyc
148 changes: 148 additions & 0 deletions examples/compose-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# Example: Run multi-container applications with container-compose

This example shows you how to use `container-compose` to bring up a multi-service application defined in a standard `docker-compose.yml` file using Apple's `container` CLI.

## Prerequisites

Install and start before running the demo:

- Apple `container`, with the system service running (`container system start`)
- Python 3.11 or later
- PyYAML: `pip3 install pyyaml --break-system-packages`

## Install container-compose

Copy the script to a directory on your `PATH`:

```bash
cp container-compose /usr/local/bin/container-compose
chmod +x /usr/local/bin/container-compose
```

Verify the installation:

```console
% container-compose --help
usage: container-compose [-h] [-f FILE] [-p NAME] {up,down,ps,logs,exec,build,pull,stop,start,restart,rm,run,config} ...
```

## The example application

The `docker-compose.yml` in this directory describes three services:

- **redis** — a Redis cache with a named volume and resource limits
- **api** — a Node.js application that depends on `redis`, built from a local `Dockerfile`
- **web** — an nginx front-end that depends on both `redis` and `api`

```
web ──depends_on──► api ──depends_on──► redis
```

## Start the application

From this directory, start all services in dependency order:

```console
% container-compose up
+ container network create compose-example_frontend
+ container network create compose-example_backend
+ container volume create compose-example_redis-data
+ container run --name compose-example-redis-1 -d ... redis:alpine
+ container run --name compose-example-api-1 -d ... myapp/api:latest
+ container run --name compose-example-web-1 -d ... nginx:latest
```

`up` runs detached by default. To stream output to the terminal instead, use `--no-detach`.

## Check service status

```console
% container-compose ps
NAME SERVICE STATUS
compose-example-redis-1 redis running
compose-example-api-1 api running
compose-example-web-1 web running
```

## View logs

Print recent output from all services:

```bash
container-compose logs
```

Follow log output from a specific service:

```bash
container-compose logs -f web
```

Show only the last 20 lines:

```bash
container-compose logs --tail 20
```

## Run a command inside a service

Open a shell in the running `redis` container:

```bash
container-compose exec redis sh
```

Run a one-off command without affecting the running container:

```bash
container-compose run --rm api node --version
```

## Rebuild and restart a service

If you change the `api` source code:

```bash
container-compose build api
container-compose restart api
```

Or rebuild everything before starting:

```bash
container-compose up --build
```

## Stop and remove

Stop all services without removing them:

```bash
container-compose stop
```

Remove all containers and the project networks:

```bash
container-compose down
```

Also remove the named `redis-data` volume:

```bash
container-compose down -v
```

## Run with a custom project name

By default the project name is the current directory name (`compose-example`). Override it to run multiple isolated instances side by side:

```bash
container-compose -p staging up
container-compose -p production up
```

## See also

- [`docs/container-compose.md`](../../docs/container-compose.md) — full reference for supported keys and known limitations
- [`container-compose`](./container-compose) — the script itself
Loading