psql access

This commit is contained in:
2026-04-11 11:37:48 -04:00
parent af13b07dee
commit d6f238f82e
4 changed files with 99 additions and 12 deletions

View File

@ -17,6 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libffi-dev \
libyaml-dev \
libpq-dev \
socat \
&& rm -rf /var/lib/apt/lists/*
# --- rbenv (installed into home volume on first run, via entrypoint) ---

View File

@ -56,7 +56,7 @@ claude doctor # diagnose installation issues
## Volumes
| Volume | Purpose |
|---|---|
| --------------------- | --------------------------------------------------------- |
| `claude-home` (named) | Persists Claude Code binary, config, and auth credentials |
| `$PROJECT_DIR` (bind) | Your project code — swap freely between sessions |
@ -68,9 +68,84 @@ docker compose down -v # removes the claude-home volume
## Security notes
- Runs as a non-root user (`coder`, uid 1000)
- All Linux capabilities are dropped (`cap_drop: ALL`)
- Runs as a non-root user (`coder`, uid 1001)
- All Linux capabilities are dropped except `NET_BIND_SERVICE`
- Privilege escalation is disabled (`no-new-privileges`)
- The container has no network restrictions beyond what Docker provides —
add a custom network or `--network none` with `--add-host` if you want
to lock that down further
## Connecting to a host PostgreSQL database
The container can reach a PostgreSQL server running on the host, but
`127.0.0.1` inside the container refers to the container itself, not the
host. The solution is to connect via the Docker bridge gateway IP instead,
which both the host and the container can see.
### 1. Find the gateway IP
```bash
docker network inspect bridge | grep Gateway
```
This is typically `172.17.0.1`. Use the value specific to your machine
in all steps below.
### 2. Configure PostgreSQL on the host
Edit `/etc/postgresql/<version>/main/postgresql.conf`:
```
listen_addresses = 'localhost,172.17.0.1'
```
Edit `/etc/postgresql/<version>/main/pg_hba.conf` and add:
```
host all all 172.17.0.0/16 scram-sha-256
```
Restart PostgreSQL:
```bash
sudo systemctl restart postgresql
```
### 3. Configure your app
Use the gateway IP as the database host. Since it is reachable from both
the host and the container, a single `DATABASE_URL` works in both contexts:
```
DATABASE_URL=postgresql://user:password@172.17.0.1:5432/mydb
```
Set this in your `.env` file or shell profile on the host, and pass it
through in `docker-compose.yml`:
```yaml
environment:
- DATABASE_URL=${DATABASE_URL}
```
### Collation version warning
If you see a warning like:
```
WARNING: database "mydb" has a collation version mismatch
DETAIL: The database was created using collation version 2.41, but the
operating system provides version 2.42.
```
This is caused by the container's glibc version differing from the host's.
It is a warning only and will not break anything. To silence it, run once
on the host:
```bash
psql -d mydb -c "ALTER DATABASE mydb REFRESH COLLATION VERSION;"
```
Note: the warning will reappear inside the container because its glibc
version differs from the host. The long-term fix is to rebase the Docker
image on the same Ubuntu release as the host so glibc versions match.

View File

@ -4,11 +4,6 @@ services:
image: claude-code:local
container_name: claude-code
# Pass your Anthropic API key in from the host environment,
# or drop it into a .env file alongside this compose file.
# environment:
# - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:?Set ANTHROPIC_API_KEY in your environment or .env file}
volumes:
# Fixed home volume — persists Claude Code install, config, and credentials
# across container restarts and image rebuilds.
@ -18,13 +13,21 @@ services:
# PROJECT_DIR=/path/to/myproject docker compose run --rm claude-code
- ${PROJECT_DIR:-./code}:/code
# Drop all Linux capabilities and disable privilege escalation —
# Claude Code doesn't need any of them.
# Drop all Linux capabilities except NET_BIND_SERVICE, which socat needs
# to proxy port 5432 on 127.0.0.1 inside the container.
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
security_opt:
- no-new-privileges:true
# Allow the container to reach the host's network (e.g. a local postgres).
# On Linux, host.docker.internal isn't automatic — this creates it.
# On Mac/Windows Docker Desktop it's already available but this is harmless.
extra_hosts:
- "host.docker.internal:host-gateway"
# Interactive terminal so `claude` works properly
stdin_open: true
tty: true

View File

@ -39,4 +39,12 @@ else
echo "Claude Code $(claude --version 2>/dev/null || echo '(version unknown)') ready."
fi
# Proxy host postgres to 127.0.0.1:5432 inside the container so the app can
# use the same DATABASE_URL whether running inside or outside Docker.
if ! ss -tlnp 2>/dev/null | grep -q ':5432'; then
echo "Starting postgres proxy 127.0.0.1:5432 -> host.docker.internal:5432"
socat TCP-LISTEN:5432,bind=127.0.0.1,fork,reuseaddr \
TCP:host.docker.internal:5432 &
fi
exec "$@"