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

Advertisement

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.

Advertisement

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.