# Docker
<subtitle>A sandbox with Docker or Docker Compose installed for running containers. </subtitle>

## Docker

### Template

Use the official installation script from [get.docker.com](https://get.docker.com). Run the `hello-world` container to verify the installation.

```python
# template.py
from ucloud_sandbox import Template

template = (
    Template()
    .from_ubuntu_image("24.04")
    .run_cmd("curl -fsSL https://get.docker.com | sudo sh")
    .run_cmd("sudo docker run --rm hello-world")
)
```

### Build

We recommend at least 2 CPUs and 2 GB of memory to run Docker containers. **When memory is low, your sandbox may run out of memory. **

```python
# build.py
from ucloud_sandbox import Template, default_build_logger
from .template import template as dockerTemplate

Template.build(dockerTemplate, 'docker',
    cpu_count=2,
    memory_mb=2048,
    on_build_logs=default_build_logger(),
)
```

### Run

Run an Alpine container that prints a hello message.

```python
# sandbox.py
from ucloud_sandbox import Sandbox

sbx = Sandbox.create('docker')

result = sbx.commands.run('sudo docker run --rm alpine echo "Hello from Alpine!"')
print(result.stdout)

sbx.kill()
```

## Docker Compose

This example installs Docker and Docker Compose, then verifies the setup with a Compose version check and a sample Compose run.

### Template

Create a new file named `template_compose.py`.

```python
# template_compose.py
from ucloud_sandbox import Template

compose_template = (
    Template()
    .from_ubuntu_image("24.04")
    .run_cmd(
        [
            "set -euxo pipefail",
            "sudo apt-get update",
            "sudo DEBIAN_FRONTEND=noninteractive apt-get install -y docker.io",
            "sudo usermod -aG docker user",
            "sudo DEBIAN_FRONTEND=noninteractive apt-get install -y docker-compose-plugin || true",
            "sudo DEBIAN_FRONTEND=noninteractive apt-get install -y docker-compose-v2 || true",
            "sudo DEBIAN_FRONTEND=noninteractive apt-get install -y docker-compose || true",
            "sudo docker compose version || sudo docker-compose --version",
        ]
    )
)
```

Expected results: You now have a local `template_compose.py` file.

### Build

```python
# build_compose.py
from ucloud_sandbox import Template, default_build_logger
from template_compose import compose_template

Template.build(compose_template, "docker-compose",
    cpu_count=2,
    memory_mb=2048,
    on_build_logs=default_build_logger(),
)
```

Expected output (example):

```text
BuildInfo(... name='docker-compose', alias='docker-compose', tags=['default'])
```

### Run

```python
# sandbox_compose.py
from ucloud_sandbox import Sandbox

sbx = Sandbox.create("docker-compose")

sbx.commands.run("mkdir -p /tmp/docker-compose-test")
sbx.files.write(
    "/tmp/docker-compose-test/compose.yaml",
    """
services:
  hello:
    image: busybox:1.36
    command: ["sh", "-lc", "echo docker-compose-ok"]
""",
)

result = sbx.commands.run(
    """
set -euxo pipefail
cd /tmp/docker-compose-test

if docker compose version >/dev/null 2>&1; then
  docker compose up --abort-on-container-exit --remove-orphans
  docker compose down --remove-orphans -v
  echo "Docker Compose ran successfully"
elif docker-compose --version >/dev/null 2>&1; then
  docker-compose up --abort-on-container-exit --remove-orphans
  docker-compose down --remove-orphans -v
  echo "Docker Compose ran successfully"
else
  echo "No compose command available"
  exit 127
fi
    """,
)

print(result.stdout)
sbx.kill()
```

Expected output (example):

```text
hello_1  | docker-compose-ok
Docker Compose ran successfully
```
