---
title: PostgreSQL
description: Run a persistent PostgreSQL service with a localhost-only forwarded port
icon: "database"
---

<Tooltip tip="This example depends on a disk-kind named volume and a published client-host port, which are not available on microsandbox cloud."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

This example runs PostgreSQL 17 in a microVM, stores the database on a disk-backed named volume, and publishes the service only to host loopback.

<Note>
  The current `postgres:17-alpine` image contains tab characters in `DOCKER_PG_LLVM_DEPS`. Passing `-e DOCKER_PG_LLVM_DEPS=` is a temporary compatibility workaround for microsandbox's guest environment validation.
</Note>

## Run PostgreSQL

<Steps>
<Step title="Start PostgreSQL">

Set a demo password in the host shell:

<CodeGroup>
```sh macOS & Linux
export POSTGRES_PASSWORD="$(openssl rand -hex 24)"
```

```powershell Windows
$bytes = New-Object byte[] 24
$rng = [Security.Cryptography.RandomNumberGenerator]::Create()
$rng.GetBytes($bytes)
$rng.Dispose()
$env:POSTGRES_PASSWORD = -join ($bytes | ForEach-Object { $_.ToString('x2') })
```
</CodeGroup>

Start the database:

<CodeGroup>
```sh macOS & Linux
msb run -d --name postgres-demo --replace \
  --cpus 1 --memory 1G --root-disk 2G \
  -p 127.0.0.1:55432:5432 \
  -e POSTGRES_PASSWORD="$POSTGRES_PASSWORD" \
  -e POSTGRES_DB=examples \
  -e DOCKER_PG_LLVM_DEPS= \
  --mount-named postgres-data:/var/lib/postgresql/data:kind=disk,size=5G \
  postgres:17-alpine
```

```powershell Windows
msb run -d --name postgres-demo --replace `
  --cpus 1 --memory 1G --root-disk 2G `
  -p 127.0.0.1:55432:5432 `
  -e "POSTGRES_PASSWORD=$env:POSTGRES_PASSWORD" `
  -e POSTGRES_DB=examples `
  -e DOCKER_PG_LLVM_DEPS= `
  --mount-named postgres-data:/var/lib/postgresql/data:kind=disk,size=5G `
  postgres:17-alpine
```
</CodeGroup>

With no command after the image, microsandbox runs the image's declared `docker-entrypoint.sh postgres` command in the background.

</Step>

<Step title="Wait for readiness">

```sh
msb exec postgres-demo -- sh -lc '
  until pg_isready -h 127.0.0.1 -d examples -U postgres; do sleep 1; done
'
```

</Step>

<Step title="Run a query">

<CodeGroup>
```sh macOS & Linux
msb exec -e PGPASSWORD="$POSTGRES_PASSWORD" postgres-demo -- \
  psql -h 127.0.0.1 -U postgres -d examples \
  -c "select current_database(), current_setting('server_version');"
```

```powershell Windows
msb exec -e "PGPASSWORD=$env:POSTGRES_PASSWORD" postgres-demo -- `
  psql -h 127.0.0.1 -U postgres -d examples `
  -c "select current_database(), current_setting('server_version');"
```
</CodeGroup>

The tested image returned database `examples` and PostgreSQL `17.10`.

Applications on the host can connect to `127.0.0.1:55432` with the same database, user, and password.

<Warning>
  Environment variables and command arguments are appropriate for this local demo, not for production secrets. Use [secret injection](/sandboxes/secrets), retain the loopback bind, and configure PostgreSQL access controls before allowing remote clients.
</Warning>

</Step>

<Step title="Clean up or keep the data">

Remove the VM while keeping its database:

```sh
msb rm -f postgres-demo
```

Remove the database volume only when you no longer need its contents:

```sh
msb volume rm postgres-data
```

Clear the password from the host shell:

<CodeGroup>
```sh macOS & Linux
unset POSTGRES_PASSWORD
```

```powershell Windows
Remove-Item Env:POSTGRES_PASSWORD
```
</CodeGroup>

</Step>
</Steps>
