If your PostgreSQL lives inside a Docker container on a remote server — not exposed to the internet — SSH tunneling is the cleanest way to reach it from your laptop. No firewall rules, no open ports, no VPN. Just SSH.
This guide walks through the exact steps with commands you can copy and adapt.
Why bother with an SSH tunnel?
Opening port 5432 to the public internet is a bad idea. With an SSH tunnel, the connection stays private:
- Your database port never touches the public internet
- Access is gated by your existing SSH credentials (or better, SSH keys)
- Local tools like psql, DBeaver, TablePlus, and Prisma Studio work exactly as if the database were on your own machine
The traffic path looks like this:
local machine → SSH server → PostgreSQL container
What you'll need
Before starting, make sure you have:
- SSH access to the remote host
- Docker running on that host with a PostgreSQL container
- The container name (or ID)
- The PostgreSQL port inside the container (usually
5432) - A free local port to bind to (this guide uses
5433)
SSH key authentication is strongly recommended over password login — it's more secure and saves you from typing a password every session.
Step 1: Find the container's internal IP
Docker's bridge network gives each container its own IP that the host machine can reach. Grab it with:
ssh root@<remote_host> "docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container_name>"
You should get back something like 172.18.0.5.
If nothing comes back, double-check the container name first:
ssh root@<remote_host> "docker ps --format '{{.Names}}'"
Step 2: Open the tunnel
ssh -N -L <local_port>:<container_ip>:<container_port> root@<remote_host>
A concrete example:
ssh -N -L 5433:172.18.0.5:5432 root@example.com
The -N flag tells SSH not to run a remote command — just forward the port. Keep this terminal open for as long as you need the connection.
Step 3: Connect with your local tools
With the tunnel running, connect to 127.0.0.1 on your chosen local port using the same credentials as the remote database:
- Host:
127.0.0.1 - Port:
5433(or whatever local port you picked) - User / password / database: same as on the remote PostgreSQL instance
With psql:
psql -h 127.0.0.1 -p 5433 -U <db_user> -d <db_name>
Any GUI client (DBeaver, TablePlus, DataGrip) works the same way — just point it at localhost and your tunnel port.
Running the tunnel in the background
If you need the tunnel open without occupying a terminal, add -f:
ssh -f -N -L 5433:172.18.0.5:5432 root@example.com
To close it later:
ps aux | grep "ssh -f -N -L 5433"
kill <pid>
For something more permanent — like a dev server you tunnel into every day — look at autossh, which keeps the tunnel alive and reconnects automatically if it drops.
A few security pointers
- Don't expose port 5432 publicly. The whole point of this setup is that you don't have to.
- Use SSH keys. They're harder to brute-force than passwords and easier to manage once set up.
- Avoid root when you can. If your server allows a limited-privilege user with SSH access, prefer that over root for day-to-day tunneling.
Common questions
Can I use this with Prisma?
Yes. Set DATABASE_URL to postgresql://<user>:<password>@127.0.0.1:<local_port>/<db_name> while the tunnel is active. Prisma doesn't know or care that it's going through a tunnel.
What if PostgreSQL is on the host network, not inside a container?
Skip the container IP lookup and use 127.0.0.1 as the target in the tunnel command:
ssh -N -L 5433:127.0.0.1:5432 root@example.com
Do I need autossh?
Not for occasional use. For tunnels you want always running without babysitting, autossh is worth the five-minute setup.