> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sailresearch.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Docker and systemd

> Run containers and start services at boot

Use the devbox image to get Docker, Compose, and Buildx already installed.
Docker starts when the Sailbox boots.

```bash CLI theme={null}
sail box devbox up docker-demo
sail box shell <id>
```

```python Python theme={null}
import sail

app = sail.App.find(name="my-app", mint_if_missing=True)
sb = sail.Sailbox.create(
    app=app, name="docker-demo", image=sail.Image.devbox("amd64")
)
print(sb.run("docker version").stdout)
```

```typescript TypeScript theme={null}
import { App, Image, Sailbox } from "@sailresearch/sdk";

const app = await App.find("my-app", { mintIfMissing: true });
const sb = await Sailbox.create({
  app,
  name: "docker-demo",
  image: Image.devbox("amd64"),
});
console.log((await sb.run("docker version")).stdout);
```

## Run a container

Inside the Sailbox:

```bash theme={null}
docker run --rm hello-world
docker run -d --name web --restart unless-stopped -p 8080:80 nginx:alpine
```

From your machine, expose the published port:

```bash theme={null}
sail box expose <id> 8080
sail box address <id> 8080
```

Publishing a Docker port makes it available inside the Sailbox. Exposing it
through Sail gives it a public endpoint. See [Networking](https://docs.sailresearch.com/sailboxes-networking.md).

## Use Compose

Copy your project into the Sailbox, then start it there:

```bash theme={null}
sail box cp --recursive ./app <id>:/root/app
sail box exec <id> -- sh -lc 'cd /root/app && docker compose up -d'
```

To build the whole Sailbox from a Dockerfile or Compose project instead,
see [Custom images](https://docs.sailresearch.com/sailboxes-images).

## systemd

Devbox images already run systemd. For a custom image, call `with_systemd`
and enable your service during the image build.

### Define a service

Create `worker.service` next to your application:

```ini worker.service theme={null}
[Unit]
Description=Application worker
After=network-online.target

[Service]
WorkingDirectory=/opt/app
ExecStart=/usr/bin/python3 /opt/app/worker.py
Restart=always

[Install]
WantedBy=multi-user.target
```

### Build the image

```python Python theme={null}
import sail

image = (
    sail.Image.debian_amd64
    .with_systemd()
    .add_local_dir("./app", "/opt/app")
    .add_local_file("./worker.service", "/etc/systemd/system/worker.service")
    .run_commands("systemctl enable worker.service")
)
app = sail.App.find(name="my-app", mint_if_missing=True)
sb = sail.Sailbox.create(app=app, name="worker", image=image)
```

```typescript TypeScript theme={null}
import { App, Image, Sailbox } from "@sailresearch/sdk";

const image = Image.debian("amd64")
  .withSystemd()
  .addLocalDir("./app", "/opt/app")
  .addLocalFile("./worker.service", "/etc/systemd/system/worker.service")
  .runCommand("systemctl enable worker.service");
const app = await App.find("my-app", { mintIfMissing: true });
const sb = await Sailbox.create({ app, name: "worker", image });
```

The service starts when the Sailbox boots. It may still be starting when
`create` returns; check the application's readiness before sending work.

### Inspect and restart

Inside the Sailbox:

```bash theme={null}
systemctl status worker
journalctl -u worker -f
systemctl restart worker
```

`with_systemd` works with the Debian base, registry images, and Dockerfile
images. Compose images cannot use it. See the
[image reference](https://docs.sailresearch.com/sailbox-sdk-images.md#with_systemd) for timers and reboot behavior.
