Only one mysqld can own the data files. 'Unable to lock ibdata1' means another instance (often a stray container or unclean shutdown remnant) holds them. Find it, don't delete anything.
docker ps -a | grep mysql shows the older container still running or restarting. ps aux | grep mysqld on the host finds stray processes.
If no process holds the files (lsof /var/lib/mysql shows nothing), an unclean stop left lock remnants — mysqld normally clears these; force-clearing needs a clean start attempt first.
docker ps -a --filter name=mysql; sudo lsof +D /var/lib/mysql 2>/dev/null | head
docker stop <old-container> # or: sudo systemctl stop mysql — clean stop lets the next instance acquire locks
docker logs -f <container> # expect 'InnoDB: ... started' after redo replay; loop-restarts = look for disk errors
# distinct data dirs AND ports; compose networks so only one claims 3306
Never delete ibdata1 to 'fix' the lock — that's your data. Every legit fix is about process ownership. Same-named compose projects are a common source: 'docker compose up' in two checkouts creates two containers over one volume.
There is no separate lock file to delete — mysqld locks the data files themselves (flock). If lsof shows no holder, it's a stale-file situation that a clean start usually resolves; deleting ibdata1 destroys your data.
Usually stale compose projects or an 'always restart' policy surviving a docker kill. docker ps -a for all names + volumes, and pin project names to avoid collisions.
Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.
Browse the template store →One-time. Yours to modify. Instant download from the NinjaOps template store.