DevOps 4 min read

MySQL with Docker Compose: Complete Setup Guide

Learn how to set up MySQL using Docker Compose for local development. Includes configuration, volumes, networking, and common commands.

MR

Moshiour Rahman

· Updated May 9, 2026

Overview

Docker makes it easy to run MySQL for local development without installing it directly on your machine. In this tutorial, we’ll create a Docker Compose configuration for MySQL that you can reuse across projects.

Prerequisites

What is Docker?

Docker allows you to package applications with their dependencies into containers. Key benefits:

  • Consistency - Same environment everywhere
  • Isolation - No conflicts between projects
  • Lightweight - Shares the host OS kernel (unlike VMs)
  • Portable - Run anywhere Docker is installed

The Docker Compose File

Create a file named docker-compose.yml:

version: "3.8"
services:
  mysql:
    image: mysql:8.0
    container_name: mysql-dev
    hostname: mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: myapp
      MYSQL_USER: developer
      MYSQL_PASSWORD: devpassword
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
    command: >
      --default-authentication-plugin=mysql_native_password
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_unicode_ci

volumes:
  mysql-data:

Understanding Each Section

Version

version: "3.8"

Specifies the Docker Compose file format version. Version 3.8 is compatible with Docker Engine 19.03.0+.

Services

Services define the containers to run. A typical application might have:

services:
  frontend:
    image: node:18-alpine
    # ...
  backend:
    image: openjdk:17-slim
    # ...
  database:
    image: mysql:8.0
    # ...

Image

image: mysql:8.0

The Docker image to use. Options:

  • mysql:latest - Always the newest (may cause breaking changes)
  • mysql:8.0 - Latest MySQL 8.x (recommended)
  • mysql:8.0.35 - Specific version (most stable)

Environment Variables

environment:
  MYSQL_ROOT_PASSWORD: rootpassword  # Required
  MYSQL_DATABASE: myapp              # Optional - creates database
  MYSQL_USER: developer              # Optional - creates user
  MYSQL_PASSWORD: devpassword        # Optional - sets user password
VariableRequiredDescription
MYSQL_ROOT_PASSWORDYesRoot user password
MYSQL_DATABASENoDatabase to create on startup
MYSQL_USERNoAdditional user to create
MYSQL_PASSWORDNoPassword for additional user

Ports

ports:
  - "3306:3306"

Format: HOST_PORT:CONTAINER_PORT

Maps port 3306 on your machine to port 3306 in the container.

Volumes

volumes:
  - mysql-data:/var/lib/mysql

Persists data between container restarts. Without volumes, data is lost when the container stops.

Types of volumes:

  • Named volumes (recommended): mysql-data:/var/lib/mysql
  • Bind mounts: ./data:/var/lib/mysql

Networks (Optional)

For multi-container setups:

services:
  mysql:
    networks:
      - backend-network

  api:
    networks:
      - backend-network

networks:
  backend-network:
    driver: bridge

Containers in the same network can communicate using service names as hostnames.

Common Commands

Start the Container

# Start in foreground (see logs)
docker-compose up

# Start in background
docker-compose up -d

# Specify file (if not docker-compose.yml)
docker-compose -f mysql.yml up -d

Stop the Container

# Stop containers
docker-compose down

# Stop and remove volumes (WARNING: deletes data!)
docker-compose down -v

View Logs

docker-compose logs mysql

# Follow logs
docker-compose logs -f mysql

Connect to MySQL

# Using docker exec
docker exec -it mysql-dev mysql -u root -p

# Using mysql client (if installed locally)
mysql -h 127.0.0.1 -u root -p

Check Container Status

docker-compose ps

Production-Ready Configuration

For a more robust setup:

version: "3.8"
services:
  mysql:
    image: mysql:8.0
    container_name: mysql-prod
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password
      MYSQL_DATABASE: production_db
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
      - ./init:/docker-entrypoint-initdb.d  # Init scripts
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 30s
      timeout: 10s
      retries: 5
    command: >
      --default-authentication-plugin=mysql_native_password
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_unicode_ci
      --innodb-buffer-pool-size=256M
    secrets:
      - mysql_root_password

volumes:
  mysql-data:

secrets:
  mysql_root_password:
    file: ./secrets/mysql_root_password.txt

Features Added

  1. Secrets - Passwords stored in files, not environment variables
  2. Health checks - Docker monitors if MySQL is healthy
  3. Init scripts - Run SQL files on first startup
  4. Performance tuning - Custom MySQL configuration

Connecting from Applications

Spring Boot (application.properties)

spring.datasource.url=jdbc:mysql://localhost:3306/myapp
spring.datasource.username=developer
spring.datasource.password=devpassword
spring.jpa.hibernate.ddl-auto=update

Node.js

const mysql = require('mysql2');

const connection = mysql.createConnection({
  host: 'localhost',
  port: 3306,
  user: 'developer',
  password: 'devpassword',
  database: 'myapp'
});

Python

import mysql.connector

connection = mysql.connector.connect(
    host="localhost",
    port=3306,
    user="developer",
    password="devpassword",
    database="myapp"
)

Troubleshooting

Port Already in Use

# Find what's using port 3306
lsof -i :3306

# Use a different port
ports:
  - "3307:3306"  # Access via localhost:3307

Permission Denied on Volume

# Fix permissions
sudo chown -R 999:999 ./mysql-data

Container Keeps Restarting

# Check logs for errors
docker-compose logs mysql

Conclusion

Docker Compose makes it easy to:

  • Run MySQL without installation
  • Maintain consistent development environments
  • Share configurations with your team

Key Takeaways:

  • Always use named volumes for data persistence
  • Pin MySQL versions for stability
  • Use secrets for sensitive data in production
  • Include health checks for reliability

In future posts, we’ll use this MySQL setup as a foundation for building full-stack applications.

MR

Moshiour Rahman

Software Architect & AI Engineer

Share:
MR

Moshiour Rahman

Software Architect & AI Engineer

Enterprise software architect with deep expertise in financial systems, distributed architecture, and AI-powered applications. Building large-scale systems at Fortune 500 companies. Specializing in LLM orchestration, multi-agent systems, and cloud-native solutions. I share battle-tested patterns from real enterprise projects.

Related Articles

Comments

Comments are powered by GitHub Discussions.

Configure Giscus at giscus.app to enable comments.