Local MySQL in Docker (or Laravel Herd’s database services) is perfect until your GUI cannot connect and the terminal somehow can. This walkthrough shows how to connect a MySQL GUI to Docker cleanly: host, port, user, socket traps, and the differences between containers and tools like Herd.
The 30-second mental model
Your GUI does not talk to “the container.” It talks to a host + port (or a Unix socket) on your machine that Docker published.
Typical Compose snippet:
services:
mysql:
image: mysql:8.4
ports:
- "3307:3306"
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: app
Inside the container MySQL listens on 3306. On your Mac/PC you connect to 127.0.0.1:3307.
That host-port remapping is the number one source of “GUI failed, CLI worked” confusion.
Connection settings that usually work
| Field | Docker example | Notes |
|---|---|---|
| Host | 127.0.0.1 |
Prefer this over localhost on Mac/Linux |
| Port | 3307 (example) |
The left side of 3307:3306 |
| User | root or app user |
Must match container env/init |
| Password | from Compose/MYSQL_ROOT_PASSWORD |
Quotes/spaces in .env cause silent mismatches |
| Database | app or empty |
Empty lets you see all schemas you may access |
Why 127.0.0.1 beats localhost
On many Mac/Linux setups, localhost can mean “try a Unix socket first.” Your Docker MySQL is on TCP. GUIs that follow socket semantics then fail in ways that look like auth bugs. Use 127.0.0.1 unless you intentionally configured a socket.
Step-by-step in a desktop client
- Start the stack (
docker compose up -d) - Confirm the published port:
docker compose psordocker port ... - Create a new connection in your MySQL GUI
- Set host
127.0.0.1, the published port, user, password - Click Test connection before saving
- Open a table or run
SELECT VERSION();
TabulaSQL follows that flow: save encrypted connections, test first, then browse schemas like any remote server.
Laravel Herd / local PHP stacks
Herd users often run MySQL via Herd’s services or a project container. Rules of thumb:
- Herd’s MySQL is usually on
127.0.0.1:3306unless you changed it - a project Compose file may still publish
3307or another port; do not assume 3306 - create separate GUI connections named
Herd MySQLandProject Dockerso you never edit the wrong server
If you also clone GUI tools into Herd for browser use, keep database connections pointed at the DB service, not at the site vhost.
Auth plugin surprises (MySQL 8+)
MySQL 8 defaults can produce “plugin” or auth errors with older clients. Fixes that work in practice:
- upgrade the GUI/client
- create a user with an auth plugin your toolchain expects
- connect with a dedicated app user instead of root when possible
CREATE USER 'app'@'%' IDENTIFIED BY 'secret';
GRANT ALL ON app.* TO 'app'@'%';
FLUSH PRIVILEGES;
Lock % down for anything beyond local Docker.
Troubleshooting matrix
Connection refused
- container not running
- wrong published port
- binding only on an internal Docker network without
ports:
Access denied
- wrong password (check
.envvs Compose) - user not allowed from your client host (
user@%vs[email protected]) - connecting to Herd’s MySQL while using Docker credentials (or the reverse)
Empty schema list
- connected to the wrong port/instance
- user lacks privileges
- you restricted the connection to a database name that does not exist yet
Works in TablePlus/CLI, fails in another GUI
Compare host (localhost vs 127.0.0.1), port, SSL off for local, and SSH accidentally enabled for a local container.
Soft habits that prevent pain
- name connections after the environment (
docker-app,herd-local,staging-ssh) - store passwords encrypted in the client
- keep a read-only user for shared staging even if local root is fine
- document the published port in the project README
Recommendation
Treat Docker MySQL like any TCP server: 127.0.0.1, published port, explicit user. Once that clicks, every GUI behaves. If you want a free MySQL/MariaDB desktop client for that daily local loop, try TabulaSQL.