Getting Started with Docker & MySQL: My First Real Setup
This is my first real hands-on project with Docker. I’d read about containers before, but reading about something and actually running one that refuses to cooperate are two very different experiences. This post is part journal, part tutorial, written mostly so future me has something to come back to when I inevitably forget how any of this works.
The Problem I Ran Into First
I already had MySQL installed natively on my Mac, running quietly on its default port. So the moment I tried to spin up a MySQL container, Docker and my local machine got into an argument over port 3306.
Before touching anything else, the first thing to do in a situation like this is see what’s actually running:
docker ps
This lists every running container along with the ports it’s using. If you want to see containers that exist but aren’t currently running too, add -a:
docker ps -a
If something looks stuck or broken, checking its logs tells you what actually went wrong instead of guessing:
docker logs <container_name>
I was watching for errors like Access denied, Cannot connect, or Port already allocated: that last one was exactly my problem.
To confirm what was hogging port 3306 outside of Docker entirely:
lsof -i :3306
This showed my native mysqld process sitting on that port. I could have killed it with:
kill -9 <PID>
But instead of fighting my existing MySQL installation, I chose the simpler route: give the container a different port and let both versions of MySQL live side by side.
Creating My First MySQL Container
Here’s the command that actually got things running:
docker run --name mysql \
-e MYSQL_ROOT_PASSWORD=root1234 \
-p 3307:3306 \
-d mysql:latest
Breaking this down piece by piece, since I know I’ll forget the flags later:
| Flag | What it does |
|---|---|
--name mysql |
Names the container mysql so I can refer to it easily |
-e MYSQL_ROOT_PASSWORD=root1234 |
Sets the root password via an environment variable during setup |
-p 3307:3306 |
Maps port 3307 on my Mac to port 3306 inside the container |
-d |
Runs the container in detached mode (in the background) |
mysql:latest |
The image to use: Docker pulls this from Docker Hub if it isn’t already downloaded |
That -p 3307:3306 flag was the actual fix for my port conflict. My native MySQL kept 3306. The container’s internal MySQL still runs on 3306 too, but from outside the container, on my actual Mac, I now reach it through 3307.
My Mac Docker Container
localhost:3307 ───────► MySQL running on :3306
To confirm it was up and healthy:
docker ps
Looking for something like:
STATUS
Up ... (healthy)
0.0.0.0:3307->3306/tcp
Connecting Through MySQL Workbench
With the container running, I opened MySQL Workbench and created a new connection with:
Host: localhost
Port: 3307
User: root
Password: root1234
This connects Workbench to the Docker container’s MySQL, not the one installed directly on my Mac (an important distinction I almost missed). Same tool, same interface, completely different database underneath.
Practicing Basic SQL
Once connected, I ran through the basics to make sure everything actually worked end to end.
Create a database:
CREATE DATABASE testdb;
Select it so future commands apply here:
USE testdb;
Create a table:
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100)
);
Insert some data:
INSERT INTO users (name, email)
VALUES
('Niraj', 'niraj@example.com'),
('John', 'john@example.com');
Query it back:
SELECT * FROM users;
Output:
+----+-------+-------------------+
| id | name | email |
+----+-------+-------------------+
| 1 | Niraj | niraj@example.com |
| 2 | John | john@example.com |
+----+-------+-------------------+
Seeing that table populate for the first time, inside a container I’d built myself, was a genuinely satisfying moment.
Working Directly From the Terminal
Workbench is nice, but I also learned I could skip the GUI entirely and talk to MySQL straight from inside the container:
docker exec -it mysql bash
Then, once inside the container’s shell:
mysql -u root -p
Enter the password (root1234), and I’m inside MySQL itself, able to run:
SHOW DATABASES;
CREATE DATABASE practice;
USE practice;
Useful Docker Commands I Now Keep Handy
# See running containers
docker ps
# Stop the MySQL container
docker stop mysql
# Start it again
docker start mysql
# Remove it entirely (careful: this doesn't remove data unless volumes are involved)
docker rm mysql
# Full restart via Docker Compose, if using one
docker compose down
docker compose up --build
What I Actually Learned About Docker Here
The biggest shift in understanding for me was realizing what “image” vs. “container” actually means in practice:
- An image (like
mysql:latest) is a template: Docker downloads it once from Docker Hub. - A container is a running instance built from that image, my own isolated little MySQL server, separate from anything installed natively on my Mac.
Before Docker, my machine looked like this:
My Mac
└── MySQL (installed directly) → port 3306
After Docker:
My Mac
├── MySQL (installed directly) → port 3306
└── Docker
└── MySQL container → port 3307 (Mac) → 3306 (inside container)
The analogy that finally made it click for me: think of my Mac as an apartment building. My native MySQL install is one apartment using room number 3306. Docker let me build a new apartment inside the same building (the MySQL container) and just gave it a different door number (3307) so the two don’t collide. Both exist independently, and neither interferes with the other.
This is exactly why developers reach for Docker in the first place: you can run completely different, isolated database setups side by side without them ever fighting over the same resources:
Project A → MySQL 8.0 container
Project B → MySQL 5.7 container
Project C → PostgreSQL container
My Connection Details for Future Projects
For any Django, Node, or other backend project I connect to this container going forward:
HOST = 127.0.0.1
PORT = 3307
USER = root
PASSWORD = root1234
DATABASE = your_database_name
Example Django settings.py config:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": "testdb",
"USER": "root",
"PASSWORD": "root1234",
"HOST": "127.0.0.1",
"PORT": "3307",
}
}
What’s Next
The one thing I know I still need to fix: right now, if I delete this container, my data disappears with it. Containers are disposable by design (that’s actually the point of them), but that also means my testdb and users table only exist as long as this specific container does.
The next thing on my list to learn is Docker volumes, which make MySQL data persistent even if the container itself gets removed or rebuilt. Until then, I’m treating this container carefully.
This is my first checkpoint with Docker and databases. Revisiting this later, if something’s confusing, it probably confused me too, the first time. That’s the whole reason this file exists.
