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:
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}}'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.