How to Run MySQL 8 with Docker and Docker Compose (Step-by-Step)

Run MySQL 8 in Docker with docker run or Docker Compose. Persistent data volumes, MYSQL_ROOT_PASSWORD, MYSQL_USER, MYSQL_DATABASE, connect on port 3306. Includes docker-compose.yaml example for MySQL 8.

MySQL 8 is a widely used open source relational database. Running MySQL in Docker (or with Docker Compose) lets you use it locally without installing it on the host, run multiple versions side by side, and keep data in a host volume so it survives container restarts. This guide shows how to run MySQL 8 with Docker using both docker run and a docker-compose.yaml with environment variables for root password, user, and database.

In this guide you’ll:

  • Run the official mysql:8 image with docker run, mapping port 3306 and mounting a data volume
  • Set up MYSQL_ROOT_PASSWORD, MYSQL_USER, MYSQL_PASSWORD, and MYSQL_DATABASE via environment variables
  • Run the same setup with Docker Compose using a docker-compose.yaml
  • Connect to MySQL inside the container and verify the version

Related database-in-Docker guides:

Prerequisites

To follow along, ensure you have the following:

  • Docker installed locally and permissions to use it to launch containers
  • Docker compose is installed locally
  • Basic knowledge of the command line

Using the docker run command

We’ll use the docker run command with the official MySQL image. We use mysql:8 here (MySQL 8.x); you can pin a specific version (e.g. mysql:8.0.32) for production.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ docker run -d \
    --name my-mysql \
    -p 3306:3306 \
    -v ~/apps/mysql:/var/lib/mysql \
    --user 1000:1000 \
    -e MYSQL_ROOT_PASSWORD=S3cret \
    -e MYSQL_PASSWORD=An0thrS3crt \
    -e MYSQL_USER=citizix_user \
    -e MYSQL_DATABASE=citizix_db \
    mysql:8

Unable to find image 'mysql:8' locally
8: Pulling from library/mysql
b380bbd43752: Pull complete
f23cbf2ecc5d: Pull complete
30cfc6c29c0a: Pull complete
b38609286cbe: Pull complete
8211d9e66cd6: Pull complete
2313f9eeca4a: Pull complete
7eb487d00da0: Pull complete
4d7421c8152e: Pull complete
77f3d8811a28: Pull complete
cce755338cba: Pull complete
69b753046b9f: Pull complete
b2e64b0ab53c: Pull complete
Digest: sha256:6d7d4524463fe6e2b893ffc2b89543c81dec7ef82fb2020a1b27606666464d87
Status: Downloaded newer image for mysql:8
38dc3037177eab4a56366b14a4acfdbb6ae98770e03d509046e05aa2a1ce21d0

In the above command:

  • The -d instructs docker container to run as a detached process. It run container in background and print container ID
  • -p is for port mapping. We are instructing the container to expose the container port externally. Container port 3306 is mapped to host port 3306. That means the service can be accessed through localhost:3306
  • The -v directive is used to mount volumes. In our case we are mounting the container volume /var/lib/mysql to host path ~/apps/mysql. Containers are ephemeral devices that will contain its data for the time it is running. Once a container is stopped, its data is lost. Mounting volumes ensures that the data is added to a host path that can be reused when the container is restarted.
  • The --user argument is used to run the container with an arbitrary user (non root user). This happens if you need to run mysqld with a specific UID/GID.
  • The -e argument sets environment variables. The official MySQL image uses them to create the root password, a database, and an optional user (MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE).

To check that our container is running as expected, use the docker ps command:

1
2
3
4
$ docker ps

CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                                  NAMES
a1d77a05bd18   mysql:8   "docker-entrypoint.sh"   30 seconds ago   Up 29 seconds   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   my-mysql

The container is running with the name my-mysql. To open a shell inside it and connect to MySQL with the user we created, use docker exec and then run mysql with the credentials you set via environment variables:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ docker exec -it my-mysql /bin/bash

citizix@a1d77a05bd18:/$ mysql -u citizix_user -pAn0thrS3crt
mysql: Warning Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.27 MySQL Community Server - GPL

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.27    |
+-----------+
1 row in set (0.00 sec)

mysql>

If you need to clean up the container when not in use, you can stop and remove the container using this command:

1
2
3
4
5
6
7
$ docker stop my-mysql

my-mysql

$ docker rm my-mysql

my-mysql

Using Docker Compose

You can run the same MySQL 8 setup with Docker Compose: define the service in a YAML file (image, ports, volumes, environment) and start it with docker compose up -d or docker-compose up -d.

Save the following as docker-compose.yaml in a directory (e.g. where you use ~/apps/mysql for data):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
services:
  mysql:
    image: mysql:8
    ports:
      - 3306:3306
    volumes:
      - ~/apps/mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=S3cret
      - MYSQL_PASSWORD=An0thrS3crt
      - MYSQL_USER=citizix_user
      - MYSQL_DATABASE=citizix_db

From that directory, start MySQL:

1
2
3
4
docker compose up -d
# or: docker-compose up -d

Creating tmp_mysql_1 ... done

The commands:

  • up brings up the container
  • -d in a detached mode

Check that the container is running:

1
2
3
4
5
6
7
docker compose ps
# or: docker-compose ps

   Name                 Command             State                         Ports
-----------------------------------------------------------------------------------------------------
tmp_mysql_1   docker-entrypoint.sh mysqld   Up      0.0.0.0:3306->3306/tcp,:::3306->3306/tcp,
                                                    33060/tcp

To open a shell in the container and connect to MySQL:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
docker compose exec mysql /bin/bash
# or: docker-compose exec mysql /bin/bash

root@25c2472a190d:/# mysql -u citizix_user -pAn0thrS3crt
mysql: [1 Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.27 MySQL Community Server - GPL

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.27    |
+-----------+
1 row in set (0.00 sec)

mysql>

Frequently Asked Questions (FAQ)

What is MySQL 8?

MySQL 8 is the current major version of MySQL, the open source relational database from Oracle. It includes improved performance, JSON support, window functions, and better security. The official MySQL Docker image supports MySQL 8 and 9.

What port does MySQL use in Docker?

MySQL listens on TCP port 3306 inside the container (and optionally 33060 for X Protocol). Map it to the host with -p 3306:3306 (or in Compose: ports: - "3306:3306") so you can connect from the host or other containers via localhost:3306.

How do I persist MySQL data in Docker?

Mount a host directory or named volume to /var/lib/mysql inside the container. For example: -v ~/apps/mysql:/var/lib/mysql with docker run, or in Compose: volumes: - mysql_data:/var/lib/mysql with a named volume. Without a volume, data is lost when the container is removed.

Can I use the same volume for docker run and Docker Compose?

Yes. If you created data with docker run using -v ~/apps/mysql:/var/lib/mysql, use the same host path in your Compose file so the Compose stack uses that existing data. Ensure only one container is using the volume at a time.

MySQL 8 vs MariaDB in Docker?

Both use the same client protocol and similar environment variables (MYSQL_ROOT_PASSWORD, MYSQL_USER, MYSQL_DATABASE). For a MySQL-compatible alternative in Docker, see how to run MariaDB with Docker and Docker Compose.

Conclusion

You ran MySQL 8 in Docker using both docker run (with port 3306, volume, and environment variables) and Docker Compose with a docker-compose.yaml. Data is stored on the host so it survives restarts. For other databases in Docker, see MariaDB, PostgreSQL 14, or Redis 6.

comments powered by Disqus
Citizix Ltd
Built with Hugo
Theme Stack designed by Jimmy