> ## Documentation Index
> Fetch the complete documentation index at: https://microsanbox-staging-toks-cloud-snapshot-contracts.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Run Docker Compose integration tests

> Run a Compose stack without exposing the host Docker socket

Run Docker Compose inside a microVM when a test needs several containers. The inner daemon uses the sandbox's flat root disk and never receives the host's `/var/run/docker.sock`.

This example assumes `./my-project` contains `compose.yaml` and a test service named `test`.

## Run the integration tests

<Steps>
  <Step title="Start Docker">
    <Tooltip tip="Flat root disks are not yet available on microsandbox cloud."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

    <CodeGroup>
      ```sh macOS & Linux theme={null}
      msb run -d --name compose-ci --replace \
        --memory 2G --root-disk flat:10G --max-duration 10m \
        docker:27.5.1-dind
      ```

      ```powershell Windows theme={null}
      msb run -d --name compose-ci --replace `
        --memory 2G --root-disk flat:10G --max-duration 10m `
        docker:27.5.1-dind
      ```
    </CodeGroup>

    The flat root gives Docker a direct ext4 filesystem for its own overlay storage, avoiding an overlay-on-overlay stack. Its 10 GiB capacity covers the image, project, build cache, and containers.

    Copy the project into the running sandbox. This happens after creation because flat roots do not currently accept create-time rootfs patches such as `--copy-dir`:

    ```sh theme={null}
    msb cp ./my-project/. compose-ci:/workspace
    ```

    The official `dind` image starts `dockerd`. Wait for it before sending Compose commands:

    <CodeGroup>
      ```sh macOS & Linux theme={null}
      for attempt in $(seq 1 60); do
        msb exec compose-ci -- docker info >/dev/null 2>&1 && break
        sleep 1
      done
      msb exec compose-ci -- docker info >/dev/null
      ```

      ```powershell Windows theme={null}
      for ($attempt = 1; $attempt -le 60; $attempt++) {
        msb exec compose-ci -- docker info *> $null
        if ($LASTEXITCODE -eq 0) { break }
        Start-Sleep -Seconds 1
      }
      msb exec compose-ci -- docker info *> $null
      if ($LASTEXITCODE -ne 0) { throw 'Docker did not become ready' }
      ```
    </CodeGroup>
  </Step>

  <Step title="Run the tests">
    <CodeGroup>
      ```sh macOS & Linux theme={null}
      msb exec --timeout 5m --workdir /workspace compose-ci -- \
        docker compose up --build \
          --abort-on-container-exit \
          --exit-code-from test
      ```

      ```powershell Windows theme={null}
      msb exec --timeout 5m --workdir /workspace compose-ci -- `
        docker compose up --build `
          --abort-on-container-exit `
          --exit-code-from test
      ```
    </CodeGroup>

    Replace `test` with the service whose exit code should decide the CI result. `msb exec` returns that code to the host.

    <Note>
      `msb cp` makes a guest copy. Use a clean project directory, and do not copy credentials or unrelated files into the sandbox.
    </Note>
  </Step>

  <Step title="Clean up">
    Stop the Compose stack inside the sandbox:

    ```sh theme={null}
    msb exec --workdir /workspace compose-ci -- docker compose down --volumes
    ```

    Remove the sandbox:

    ```sh theme={null}
    msb rm -f compose-ci
    ```

    Removing the sandbox also removes Docker's image and build cache. Keep the sandbox between trusted runs if you want to reuse that cache; do not carry a writable cache across repositories or trust boundaries.
  </Step>
</Steps>

<Warning>
  Never mount the host Docker socket into the sandbox. Control of that socket is normally control of the host Docker daemon and defeats the microVM boundary.
</Warning>
