Docker'daki MySQL container'ı için özel my.cnf
Selamlar, bu yazımda Docker üzerinde çalışan MySQL container'ına nasıl özel bir my.cnf bağlayacağımıza bakacağız. Konu basit gibi görünür ama production'da ilk MySQL container'ını ayağa kaldırdığında varsayılanların ne kadar muhafazakar olduğunu görüyorsun. 1G RAM'i olan bir makinede innodb_buffer_pool_size hâlâ 128M ile geliyor, sonra 'neden yavaş?' diye soruyoruz. Hadi bu işi düzgün yapalım.
MySQL Docker imajı yapılandırmayı nasıl okuyor?
Resmi MySQL imajı, /etc/mysql/my.cnf dosyasını ve /etc/mysql/conf.d/*.cnf ile eşleşen her şeyi okur. Yani sıfırdan bir my.cnf yazıp ana dosyanın üzerine yazmak yerine, küçük bir dosya hazırlayıp conf.d/ altına bağlamak çok daha temiz. Böylece base yapılandırmayı bozmuyoruz, sadece üzerine ekleme yapıyoruz. Bence bu yaklaşım her zaman tercih edilmeli; tüm my.cnf'i replace etmek ileride yeni MySQL sürümünde gelen iyileştirmeleri kaçırmana neden oluyor.
Özel yapılandırma dosyası
Host tarafında ./mysql/my.cnf adıyla şöyle bir dosya açalım:
[mysqld]
# Bellek ayarlari
innodb_buffer_pool_size = 1G
innodb_buffer_pool_instances = 2
innodb_log_file_size = 256M
# Baglanti ayarlari
max_connections = 200
wait_timeout = 600
interactive_timeout = 600
# Yavas sorgu loglama
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
# Karakter seti
character_set_server = utf8mb4
collation_server = utf8mb4_unicode_ci
# Ag
bind_address = 0.0.0.0
Burada innodb_buffer_pool_size muhtemelen en kritik ayar. Sunucunun belleğinin yaklaşık %50-70'ini buraya verirsen InnoDB sayfaları diskten değil RAM'den okur, fark uçurum gibi. slow_query_log ile long_query_time = 1 kombinasyonu da geliştirme sırasında çok işine yarar; 1 saniyeden uzun süren her sorgu loga düşer, sonra EXPLAIN ile bakarsın.
docker run ile bağlama
docker run -d \
--name mysql \
-e MYSQL_ROOT_PASSWORD=root_secret \
-v $(pwd)/mysql/my.cnf:/etc/mysql/conf.d/custom.cnf:ro \
-v mysql_data:/var/lib/mysql \
-p 3306:3306 \
mysql:8.0
:ro bayrağı dosyayı container içinde salt okunur olarak bağlar. MySQL ayar dosyasına yazmaya çalışmaz zaten, ama disiplin olsun diye ro koymak iyi alışkanlık.
Docker Compose ile
Tek container'ı docker run ile değil, compose ile yönetiyorsanız aynı şeyin yaml karşılığı:
version: '3.9'
services:
mysql:
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: root_secret
MYSQL_DATABASE: myapp
volumes:
- mysql_data:/var/lib/mysql
- ./mysql/my.cnf:/etc/mysql/conf.d/custom.cnf:ro
ports:
- '3306:3306'
volumes:
mysql_data:
Ayarların gerçekten geçtiğini doğrulama
Container ayağa kalktıktan sonra ayarların gerçekten uygulandığını mutlaka kontrol edin. Insanın 'eh elbette uygulanmıştır' diyesi geliyor ama MySQL bazen hatalı satırı sessizce atlar:
docker exec -it mysql mysql -u root -proot_secret \
-e 'SELECT @@innodb_buffer_pool_size, @@max_connections, @@character_set_server;'
Belirli bir grup değişkene bakmak için:
docker exec -it mysql mysql -u root -proot_secret \
-e "SHOW VARIABLES LIKE 'slow_query_log%';"
Komut satırı argümanı yöntemi
İki üç değişken için dosya bağlamak abartı geliyorsa imaj adından sonra --variable=value şeklinde de geçebilirsin:
docker run -d \
--name mysql \
-e MYSQL_ROOT_PASSWORD=root_secret \
mysql:8.0 \
--innodb-buffer-pool-size=1073741824 \
--max-connections=200
Şahsi kanaatim, üçten fazla ayar varsa bu yöntemi bırakıp my.cnf'e geçin; yoksa docker run satırı okunmaz hâle geliyor.
Sık karşılaşılan hatalar
- Bilinmeyen değişken: Değişken adını yanlış yazmışsınızdır ya da o sürümde yok.
docker logs mysqlilk bakacağınız yer. - İzin reddi: Dosya root'a ait olduğundan MySQL süreci okuyamaz.
chmod 644 ./mysql/my.cnfçoğu durumda çözer. - Yanlış bölüme yazmak:
[mysqld]yerine[client]altına yazılmış ayar sessizce yok sayılır. Bunu fark etmek bazen saatler alıyor.
Kapanış
Bu yazıda Docker üzerindeki MySQL container'ına nasıl özel bir my.cnf bağlayacağımızı, hangi ayarların gerçekten fark yarattığını ve ayarların geçtiğini nasıl doğrulayacağımızı gördük. Bana sorarsanız conf.d/ altına bağlama yöntemi neredeyse her zaman doğru tercih; base yapılandırmayı bozmuyor, küçük dosyada sadece kendi farkını yazıyorsun. Umarım faydalı olur, bir sonraki yazıda görüşmek üzere.
