Backing Up Dockerized MySQL Without Root Access

Running a database backup tool against a MySQL instance inside Docker presents a subtle challenge: the database port is only accessible within the container's private network, and the host-side backup tool has no way to reach it. Here's how we solved it cleanly, without root access and without modifying the application container.

The setup

Each application runs in its own Docker Compose stack with a MySQL service that has no port binding to the host — intentionally, for security. The backup tool runs as an unprivileged user on the host, outside any container.

The problem

The backup CLI calls mysqldump as a subprocess. With MySQL locked inside a Docker network, there's nothing to connect to from the host. The obvious fix — installing the MySQL client on the host — requires root, which we didn't want to depend on.

The solution: two small changes

First, expose MySQL on a localhost-only port in the Compose file:

mysql:
ports:
- "127.0.0.1:33061:3306"

The 127.0.0.1 binding is critical — it makes the port reachable from the host but not from outside the machine. Restarting just the MySQL service (docker compose up -d mysql) applies the change in seconds with no application downtime.

Second, since mysqldump wasn't installed on the host, we created a thin wrapper script at ~/.local/bin/mysqldump:

#!/bin/bash
exec docker run --rm --network host mysql:8.0 mysqldump "$@"

The --network host flag lets the container reach 127.0.0.1:33061 as if it were running directly on the host. All arguments pass through transparently, so the backup tool never needs to know anything changed.

Finally, make sure the wrapper's directory is on PATH in cron:

PATH=/home/user/.local/bin:/usr/local/bin:/usr/bin:/bin

Result

The backup tool connects to MySQL through the localhost port, mysqldump silently routes through Docker, and the entire setup requires zero root privileges and zero changes to application images or containers.