Debugging with exec

Debugging a Container with docker exec

A process started by docker exec (docker exec) shares the suspect's filesystem, environment, network, DNS resolver and limits, so it sees exactly what the application sees. Question the hardened API from inside, then from the host:

Asking the API's own container, then entering only its network namespaceShell
A=l3-booknest-prod-api-1
docker exec $A sh -c 'id -un; env | grep ^PGPASS'
docker exec $A node -e \
  'fetch("http://localhost:3000/ready").then(r => r.text()).then(console.log)'
docker exec $A touch /app/probe
sudo nsenter -t "$(docker inspect -f '{{.State.Pid}}' $A)" -n ss -tn | head -3
Output
node
PGPASSWORD_FILE=/run/secrets/db_password
{"status":"ready"}
touch: cannot touch '/app/probe': Read-only file system
State Recv-Q Send-Q Local Address:Port  Peer Address:Port
ESTAB 0      0         172.19.0.3:48116   172.19.0.2:5432
ESTAB 0      0         172.19.0.3:48122   172.19.0.2:5432

The password arrives as a secret file, not a variable; /ready proves the API reaches PostgreSQL 1,289 from where it runs; the read-only root filesystem of AppArmor and Read-Only FS holds. The last command needs no tool in the container at all: nsenter joins only the network namespace (-n) of the container's main process and runs the host's ss there, listing the API's pooled connections to PostgreSQL (-m, -p and -u enter the mount, PID and UTS namespaces). Never repair production by editing files in a container: the next deployment replaces it.