- DevOps
Docker Nedir? Frontend Geliştiriciler İçin Uygulamalı Docker Rehberi
Docker ile geliştirme ortamlarını standartlaştırmayı, React ve Next.js projelerini container içine almayı ve uygulamaları daha tutarlı şekilde çalıştırmayı öğrenin.
Zeynep Baş7 dk okuma
1. Docker Nedir?
Bir uygulamanın her ortamda tutarlı çalışmasını sağlamak
Bir frontend projesi geliştirirken uygulamanın kendi bilgisayarımızda sorunsuz çalışmasına rağmen başka bir bilgisayarda veya sunucuda hata verdiği durumlarla karşılaşabiliriz. Farklı Node.js sürümleri, eksik bağımlılıklar ve ortam değişkenleri bu problemlerin nedenleri arasında yer alabilir.
Docker, uygulamaları ve çalışmaları için gereken bağımlılıkları container adı verilen izole ortamlarda çalıştırmamızı sağlayan bir platformdur. Böylece geliştirme, test ve dağıtım süreçlerinde daha tutarlı bir ortam oluşturabiliriz.
Örneğin React veya Next.js projen belirli bir Node.js sürümüne ihtiyaç duyuyorsa bu sürümü Docker image içerisinde tanımlayabilirsin. Uygulama, uyumlu bir Docker ortamında çalıştırıldığında host makinedeki Node.js kurulumuna olan bağımlılık azalır.
Docker kullanmak uygulamanın her ortamda kesinlikle hatasız çalışacağı anlamına gelmez. İşletim sistemi uyumluluğu, mimari farklılıkları, ağ ayarları ve ortam değişkenleri gibi konular yine doğru yapılandırılmalıdır.
2. Docker'ın Temel Kavramları
Image, container, Dockerfile ve registry arasındaki farklar
Docker kullanırken sık karşılaşacağın bazı temel kavramları birbirinden ayırmak önemlidir.
Docker Image: Uygulamayı çalıştırmak için gereken dosyaları, bağımlılıkları ve yapılandırmaları içeren salt okunur şablondur. Container oluşturmak için kullanılır.
Container: Bir image üzerinden oluşturulan, çalışan veya durdurulmuş uygulama örneğidir. Bir image üzerinden birden fazla container oluşturabilirsin.
Dockerfile: Bir image oluşturmak için kullanılacak adımları tanımlayan dosyadır. Örneğin Node.js sürümünü seçmek, bağımlılıkları yüklemek ve uygulamayı build etmek bu dosyada tanımlanabilir.
Docker Compose: Birden fazla servisi ve bunların ilişkilerini tek bir YAML dosyasıyla tanımlayıp yönetmeyi kolaylaştırır. Frontend, backend ve veritabanı içeren projelerde özellikle kullanışlıdır.
Registry: Docker image'larının saklandığı ve paylaşıldığı depodur. Docker Hub bunun bilinen örneklerinden biridir.
Bu kavramları basitçe şöyle düşünebilirsin: Dockerfile tarif, image tariften oluşturulmuş paket, container ise bu paketten başlatılan çalışma örneğidir.
3. Docker Kurulumu ve İlk Komutlar
Terminal üzerinden Docker ile çalışmaya başlamak
Docker Desktop, macOS ve Windows üzerinde Docker ile çalışmayı kolaylaştıran bir uygulamadır. Linux üzerinde ise Docker Engine ve gerekli bileşenler kullanılabilir. Kurulum sonrasında terminalden Docker'ın çalıştığını kontrol edebilirsin.
Docker sürümünü kontrol etmek için şu komutu kullan:
Docker Engine'in çalışıp çalışmadığını ve ortam bilgilerini kontrol etmek için:
İlk container'ını çalıştırmak için Docker'ın test image'ını kullanabilirsin:
Docker gerekli image'ı yerel ortamda bulamazsa registry üzerinden indirmeyi dener. Ardından container oluşturulur ve test işlemi gerçekleştirilir.
Çalışan container'ları listelemek için docker ps, çalışan ve durmuş olanları listelemek için docker ps -a komutunu kullanabilirsin.
4. React Projesini Docker ile Çalıştırmak
Dockerfile oluşturarak frontend uygulamasını container içine almak
Şimdi basit bir React projesini Docker ile çalıştıralım. Örneğimizde Vite kullanarak oluşturulmuş ve npm run build komutuyla üretim dosyaları dist klasörüne çıkan bir proje olduğunu varsayıyoruz.
İlk olarak projenin kök dizininde Dockerfile adında bir dosya oluştur. Bu örnek, uygulamanın üretim dosyalarını Nginx üzerinden sunar.
Buradaki FROM komutu temel image'ı belirler. WORKDIR çalışma dizinini oluşturur veya seçer. COPY dosyaları image içine kopyalar, RUN build aşamasında komut çalıştırır. Son aşamada Nginx image'ı kullanılarak yalnızca üretilmiş statik dosyalar sunulur.
Bu yapı multi-stage build olarak adlandırılır. Build için kullanılan Node.js bağımlılıklarının tamamı son image'a taşınmaz. Bu sayede üretim image'ı gereksiz dosyalardan arındırılabilir.
Projenin kök dizininde .dockerignore dosyası da oluştur. Böylece yerel bağımlılıkları ve hassas dosyaları build context içine göndermekten kaçınabilirsin.
.env dosyalarının image'a kopyalanmaması önemlidir. Ancak .dockerignore tek başına bütün gizli bilgileri koruyan bir güvenlik mekanizması değildir. Hassas değerleri Dockerfile içine yazmamalı veya build sırasında image katmanlarına dahil etmemelisin.
Image oluşturmak için:
Container'ı başlatmak için:
Artık uygulamaya http://localhost:8080 adresinden erişebilirsin. Buradaki -p 8080:80 parametresi, bilgisayarındaki 8080 portunu container içindeki 80 portuna yönlendirir.
Not: Bu Dockerfile, Vite tabanlı ve statik olarak sunulabilen React projeleri içindir. Next.js gibi sunucu tarafı çalışma gerektiren uygulamalar farklı bir üretim yapılandırmasına ihtiyaç duyar.
5. Next.js Projelerinde Docker Kullanımı
Sunucu tarafında çalışan frontend uygulamaları için üretim image'ı
Next.js projelerinde yalnızca statik dosyaları kopyalamak her zaman yeterli değildir. Server-side rendering, API route'ları veya dinamik sayfa üretimi kullanılıyorsa uygulamanın Node.js sunucusuyla çalışması gerekebilir.
Next.js'in standalone çıktısı, üretim için gerekli sunucu dosyalarını daha küçük bir çalışma image'ına taşımayı kolaylaştırır. Öncelikle next.config.js dosyasında standalone çıktıyı etkinleştir.
Projendeki yapılandırma dosyası ESM formatındaysa aynı ayarı mevcut export default yapısına göre eklemelisin. Mevcut ayarlarını silmek yerine output: 'standalone' seçeneğini eklemen yeterlidir.
Ardından aşağıdaki Dockerfile örneğini kullanabilirsin. Bu örnek, Next.js projesinin package.json dosyasında build ve start script'lerinin bulunduğunu ve uygulamanın standart .next dizinini kullandığını varsayar.
Bu örnekte build ve çalışma aşamaları ayrıdır. Son aşamada uygulama root kullanıcısı yerine nextjs kullanıcısıyla çalıştırılır. Böylece gereksiz build bağımlılıklarını son image'a taşımadan daha kontrollü bir üretim ortamı elde edebilirsin.
Uygulamayı oluşturup çalıştırmak için:
Ardından http://localhost:3000 adresini ziyaret edebilirsin. Projende public klasörü bulunmuyorsa ilgili COPY adımını kaldırmalısın. Ayrıca native bağımlılıklar, özel Next.js yapılandırmaları ve monorepo kullanımı ek düzenlemeler gerektirebilir.
6. Docker Compose Nedir?
Frontend, backend ve veritabanını birlikte yönetmek
Gerçek projelerde yalnızca frontend uygulamasını çalıştırmak yeterli olmayabilir. Backend API'si ve veritabanı gibi servisler de bulunabilir. Her container'ı ayrı komutlarla başlatmak yerine Docker Compose kullanarak servisleri tek bir yapılandırma dosyasında tanımlayabilirsin.
Örneğin React frontend'i ve Node.js backend'i bulunan bir projede aşağıdaki gibi bir compose.yaml dosyası oluşturabilirsin. Örnekte backend klasörünün Dockerfile içerdiği varsayılır.
Servisleri başlatmak için:
Servisleri arka planda başlatmak için docker compose up -d komutunu kullanabilirsin. Durdurmak ve Compose tarafından oluşturulan varsayılan kaynakları kaldırmak için docker compose down komutu kullanılabilir.
Önemli bir ayrıntı: Container içindeki frontend, backend servisine istek atarken backend:3001 gibi bir servis adı kullanabilir; ancak tarayıcıda çalışan JavaScript açısından bu isim genellikle çözümlenemez. Browser'ın erişeceği API adresi ayrıca yapılandırılmalıdır. Production ortamında reverse proxy veya uygun bir public API URL'si kullanmak bu problemi çözmeye yardımcı olur.
Veritabanı eklediğinde kalıcı veri için volume yapılandırmasını, servisler arası erişimi ve gizli bilgilerin yönetimini de ayrıca planlamalısın.
7. Docker Kullanırken Sık Yapılan Hatalar
Geliştirme sürecinde karşılaşabileceğin problemler ve çözümleri
Port çakışması: Bilgisayarındaki bir port başka bir uygulama tarafından kullanılıyorsa container başlatılamayabilir. Farklı bir host portu seçebilirsin; örneğin -p 8081:80.
Eski image ile çalışmak: Kaynak kodunu değiştirmek her zaman mevcut image'ı güncellemez. Gerekli olduğunda docker build --no-cache -t my-react-app . komutuyla yeniden build alabilirsin. Bu seçenek önbelleği kullanmadan build yapar ve daha uzun sürebilir.
node_modules uyumsuzluğu: Host makinedeki node_modules klasörünü container içine taşımak, işletim sistemi veya native bağımlılık farklılıkları nedeniyle sorun çıkarabilir. Bağımlılıkları hedef container ortamında yüklemek daha güvenlidir.
Yanlış API adresi: localhost, istek yapan ortamı ifade eder. Browser'daki localhost kullanıcının bilgisayarını, container içindeki localhost ise ilgili container'ı ifade eder. Bu nedenle API URL'sini uygulamanın nereden çalıştığına göre yapılandırmalısın.
Ortam değişkenleri: Frontend build sırasında kullanılan bazı değişkenler derlenmiş JavaScript dosyalarına dahil edilebilir. Vite'ta VITE_ ve Next.js'te NEXT_PUBLIC_ önekli değişkenler gizli bilgi olarak değerlendirilmemelidir. API anahtarları, veritabanı şifreleri ve diğer secret değerler browser'a gönderilmemelidir.
Container loglarını kontrol etmemek: Uygulamanın neden başlamadığını anlamak için docker logs komutu kullanılabilir. Compose projelerinde docker compose logs -f komutu servislerin loglarını takip etmeyi kolaylaştırır.
8. Temel Docker Komutları
Günlük geliştirme sürecinde işine yarayacak komutlar
Aşağıdaki komutlar Docker ile çalışırken en sık ihtiyaç duyacağın işlemleri kapsar.
Container'ı kaldırmak ile image'ı kaldırmak farklı işlemlerdir. Bir container'ı durdurduğunda image otomatik olarak silinmez. Benzer şekilde container kaldırıldığında, volume yapılandırmasına bağlı olarak kalıcı veriler korunabilir.
Komutları kullanırken üretim ortamındaki container'ları veya verileri silmediğinden emin ol. Özellikle docker system prune ve volume silme işlemleri öncesinde hangi kaynakların etkileneceğini kontrol et.
9. Docker Öğrenmek Frontend Geliştiricisine Ne Kazandırır?
Deployment, ekip çalışması ve üretim ortamına hazırlık
Frontend geliştiricisinin Docker öğrenmesi yalnızca terminalden container başlatabilmesi anlamına gelmez. Aynı zamanda uygulamanın hangi Node.js sürümünde çalıştığını, üretim dosyalarının nasıl oluşturulduğunu ve deployment ortamının nasıl yapılandırıldığını daha iyi anlamasını sağlar.
Ekip çalışmasında ortak bir çalışma ortamı oluşturulmasına yardımcı olabilir. Yeni bir geliştirici projeye katıldığında gerekli servisleri ve bağımlılıkları daha öngörülebilir bir biçimde çalıştırabilir.
CI/CD süreçlerinde Docker image'ları build edilebilir, test edilebilir ve registry üzerinden dağıtılabilir. Böylece uygulamanın paketlenmesi ve deployment süreci otomasyonun bir parçası haline gelebilir.
Bununla birlikte Docker her proje için zorunlu değildir. Bazı statik frontend projeleri CDN veya platformların yerleşik build sistemleriyle daha basit şekilde yayınlanabilir. Docker kullanımı, projenin mimarisine ve dağıtım ihtiyaçlarına göre değerlendirilmelidir.
10. Sonuç: Docker Bir Araçtan Fazlasıdır
Uygulamanın nasıl çalıştığını ve nasıl dağıtıldığını anlamak
Docker, uygulamaları container içinde çalıştırarak geliştirme ve dağıtım ortamlarını standartlaştırmaya yardımcı olur. Image, container, Dockerfile ve Docker Compose kavramlarını anlamak, frontend projelerinde de daha kontrollü bir geliştirme süreci sağlar.
Öğrenmeye yeni başlıyorsan önce hello-world container'ını çalıştırabilir, ardından basit bir React projesi için Dockerfile oluşturabilir ve sonrasında Next.js uygulamanı multi-stage build ile paketleyebilirsin. Bir sonraki aşamada backend ve veritabanını Docker Compose ile bir araya getirebilirsin.
Frontend geliştirirken yalnızca uygulamanın ekranda nasıl göründüğünü değil, hangi ortamda çalıştığını, bağımlılıklarının nasıl yönetildiğini ve üretime nasıl taşındığını da anlamak teknik gelişimine katkı sağlar.