Running MySQL in Docker

A container is a disposable server of any version. The official mysql:9.7 image (Oracle Linux 9, amd64 and arm64) serves every example in this chapter that changes server settings. The system server holds port 3306, so this one publishes 3301, on loopback only:

A throwaway MySQL 9.7 server with its data in a named volumeShell
docker run -d --name mysql97 -e MYSQL_ROOT_PASSWORD=secret \
  -p 127.0.0.1:3301:3306 -v mysql97-data:/var/lib/mysql mysql:9.7
docker logs mysql97 2>&1 \
  | grep -E '\[Entrypoint\]: (Init|Starting temp|Stopping temp|MySQL init)' | cut -c12-
docker ps --filter name=mysql97 --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
Output
2d30291c4677ef62e9363371c8c5ced606b17a8f7675f8d4218d7d57069db6ac
07:07:32+00:00 [Note] [Entrypoint]: Initializing database files
07:07:42+00:00 [Note] [Entrypoint]: Starting temporary server
07:07:47+00:00 [Note] [Entrypoint]: Stopping temporary server
07:07:48+00:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up.
NAMES     STATUS          PORTS
mysql97   Up 11 minutes   33060/tcp, 127.0.0.1:3301->3306/tcp

On the first start, with an empty data directory, the entrypoint initializes the system tables, starts a temporary server on port 0 (no networking), creates root (for localhost and '%') plus any MYSQL_DATABASE, MYSQL_USER and MYSQL_PASSWORD you passed, runs the .sh and .sql files in /docker-entrypoint-initdb.d, and restarts for real. Later starts find data in the volume and skip all of it, so changing those variables afterwards does nothing.

Connect with docker exec -it mysql97 mysql -uroot -p, or through 127.0.0.1:3301. The volume outlives the container: after docker rm -f mysql97, a new container with the same -v finds every database. Option files go in /etc/mysql/conf.d (Option Files and Variables); A LAMP Stack in Docker Compose adds PHP.