Takip et

Node.js Uygulamasını Docker Compose ile Geliştirme Ortamı İçin Konteynerleştirme

Node.js Uygulamasını Docker Compose ile Geliştirme Ortamı İçin Konteynerleştirme Modern yazılım geliştirme süreçlerinde tutarlılık, i

Node.js Uygulamasını Docker Compose ile Geliştirme Ortamı İçin Konteynerleştirme

Modern yazılım geliştirme süreçlerinde tutarlılık, izolasyon ve kolay kurulum büyük önem taşır. Node.js uygulamaları için bu gereksinimleri karşılamanın en etkili yollarından biri de Docker ve Docker Compose kullanarak uygulamayı konteynerleştirmektir. Bu rehberde, Node.js uygulamanızı Docker Compose ile geliştirme ortamınız için nasıl konteynerleştireceğinizi adım adım öğreneceksiniz.

Giriş: Konteynerleştirme ve Neden Önemli?

Konteynerleştirme, bir uygulamayı ve tüm bağımlılıklarını (kütüphaneler, ayarlar vb.) izole edilmiş bir ortamda paketleme sürecidir. Bu, uygulamanın farklı ortamlarda (geliştirme, test, üretim) tutarlı bir şekilde çalışmasını sağlar. Docker, bu konteynerleri oluşturmak ve yönetmek için kullanılan popüler bir platformdur.

Node.js geliştiricileri için konteynerleştirmenin başlıca faydaları şunlardır:

* Ortam Tutarlılığı: “Benim makinemde çalışıyordu!” sorununu ortadan kaldırır. Her geliştirici aynı, izole edilmiş ortamda çalışır.
* Bağımlılık İzolasyonu: Uygulamanızın bağımlılıkları, ana sisteminizdeki diğer uygulamalarla çakışmaz.
* Kolay Kurulum: Yeni bir geliştirici ekibe katıldığında veya yeni bir proje üzerinde çalışmaya başladığınızda, tüm geliştirme ortamını saniyeler içinde ayağa kaldırabilirsiniz.
* Ölçeklenebilirlik ve Taşınabilirlik: Konteynerler, bulut ortamlarına veya farklı sunuculara kolayca taşınabilir ve ölçeklenebilir.

Docker Compose ise birden fazla Docker konteynerini (örneğin, bir Node.js uygulaması ve bir veritabanı) tanımlamanıza ve tek bir komutla yönetmenize olanak tanıyan bir araçtır. Geliştirme ortamları genellikle uygulama, veritabanı, önbellek gibi birden fazla servisten oluştuğu için Docker Compose vazgeçilmezdir.

Gereksinimler ve Ön Hazırlık

Bu rehbere başlamadan önce aşağıdaki gereksinimlere sahip olmanız gerekmektedir:

1. Docker Desktop Kurulumu: Windows veya macOS kullanıyorsanız, Docker Desktop’ı yüklemiş olmanız gerekir. Linux kullanıyorsanız, Docker Engine ve Docker Compose’u kurmalısınız. Kurulum talimatları için Docker’ın resmi web sitesini ziyaret edebilirsiniz.
2. Temel Node.js Uygulaması: Konteynerleştireceğimiz basit bir Node.js uygulamasına ihtiyacımız var. Eğer yoksa, projenizin ana dizininde package.json ve index.js dosyaları bulunan basit bir Express uygulaması oluşturabilirsiniz.

Örnek bir index.js dosyası:

// index.js
    const express = require('express');
    const app = express();
    const port = 3000;

    app.get('/', (req, res) => {
      res.send('Merhaba Docker! Node.js uygulamam konteynerde çalışıyor.');
    });

    app.listen(port, () => {
      console.log(Uygulama http://localhost:${port} adresinde çalışıyor.);
    });

Ve package.json dosyası:

// package.json
    {
      "name": "my-node-app",
      "version": "1.0.0",
      "description": "A simple Node.js app for Docker demo",
      "main": "index.js",
      "scripts": {
        "start": "node index.js",
        "dev": "nodemon index.js"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "dependencies": {
        "express": "^4.18.2"
      },
      "devDependencies": {
        "nodemon": "^3.0.1"
      }
    }

Uygulamanızın kök dizininde npm install komutunu çalıştırarak bağımlılıkları yüklediğinizden emin olun.

Adım 1: Node.js Uygulaması İçin Dockerfile Oluşturma

Dockerfile, Docker’ın bir konteyner imajını nasıl oluşturacağını anlatan talimatlar listesidir. Projenizin kök dizininde Dockerfile adında bir dosya oluşturun ve içeriğini aşağıdaki gibi doldurun:

# Dockerfile

1. Temel İmajı Belirle: Node.js'nin belirli bir sürümünü ve Alpine Linux'u kullanıyoruz.

Alpine, daha küçük boyutlu imajlar oluşturmak için idealdir.

FROM node:lts-alpine

2. Çalışma Dizinini Belirle: Konteyner içinde çalışacağımız dizin.

Tüm sonraki komutlar bu dizin içinde çalışır.

WORKDIR /app

3. Bağımlılıkları Kopyala ve Kur:

package.json ve package-lock.json dosyalarını WORKDIR'a kopyalarız.

Bu adım, bağımlılıklar değişmediği sürece Docker'ın bu katmanı önbelleğe almasını sağlar,

böylece daha hızlı imaj oluşturulur.

COPY package*.json ./

npm install komutu ile tüm bağımlılıkları kurarız.

--only=production bayrağını kullanmıyoruz çünkü geliştirme ortamı için devDependencies'e de ihtiyacımız olabilir (örn. nodemon).

RUN npm install

4. Uygulama Kodunu Kopyala:

Mevcut dizindeki tüm dosyaları (uygulama kodu) konteyner içindeki /app dizinine kopyalarız.

COPY . .

5. Portu Açığa Çıkar:

Uygulamanın konteyner içinde hangi portta çalıştığını Docker'a bildirir.

Bu, dışarıdan erişim için bir ipucu sağlar ancak doğrudan bir port eşleştirmesi yapmaz.

EXPOSE 3000

6. Uygulamayı Başlatma Komutu:

Konteyner başlatıldığında çalışacak varsayılan komut.

Geliştirme ortamı için nodemon kullanmak, kod değişikliklerinde otomatik yeniden başlatma sağlar.

Eğer nodemon'u devDependencies'e eklediyseniz, npm run dev komutunu kullanabilirsiniz.

CMD ["npm", "run", "dev"]

Veya nodemon kullanmıyorsanız:

CMD ["node", "index.js"]

Açıklamalar:

* FROM node:lts-alpine: Node.js’nin uzun süreli destek (LTS) sürümünü ve hafif Alpine Linux tabanlı bir imajı kullanırız. Bu, daha küçük imaj boyutları sağlar.
* WORKDIR /app: Konteyner içinde /app adında bir çalışma dizini oluşturur ve tüm sonraki komutların bu dizinde çalışmasını sağlar.
COPY package.json ./: package.json ve package-lock.json dosyalarını çalışma dizinine kopyalar. Bu, npm install komutunun doğru bağımlılıkları yüklemesini sağlar.
* RUN npm install: Uygulamanın tüm bağımlılıklarını yükler.
* COPY . .: Projenin geri kalan tüm dosyalarını (kaynak kodunuzu) çalışma dizinine kopyalar.
* EXPOSE 3000: Uygulamanın 3000 numaralı portta dinleyeceğini belirtir. Bu sadece belgeleme amaçlıdır; portu dışarıya açmak için Docker Compose’da port eşleştirmesi yapmamız gerekecek.
* CMD ["npm", "run", "dev"]: Konteyner başlatıldığında çalışacak varsayılan komutu tanımlar. nodemon kullanmak, geliştirme sırasında kod değişikliklerinde uygulamanızın otomatik olarak yeniden başlatılmasını sağlar. package.json dosyanızdaki scripts bölümüne dev: "nodemon index.js" eklemeniz gerekebilir.

Adım 2: Geliştirme Ortamı İçin docker-compose.yml Yapılandırması

docker-compose.yml dosyası, uygulamanızın farklı servislerini (Node.js uygulaması, veritabanı vb.) tanımlar ve bunların nasıl bir araya geleceğini belirtir. Projenizin kök dizininde docker-compose.yml adında bir dosya oluşturun ve içeriğini aşağıdaki gibi doldurun:

# docker-compose.yml

Docker Compose dosyasının sürümünü belirtir. '3.8' en yaygın kullanılan sürümlerden biridir.

version: '3.8'

Tanımlayacağımız tüm servisleri içerir.

services: # Node.js uygulamamız için servis tanımı app: # Dockerfile'ın bulunduğu dizini belirtir. '.' mevcut dizin anlamına gelir. build: . # Konteyner içindeki 3000 portunu host makinesindeki 3000 portuna eşler. # Böylece uygulamaya tarayıcıdan localhost:3000 üzerinden erişebiliriz. ports: - "3000:3000" # Geliştirme için kritik olan volume eşleştirmesi. # Host makinesindeki mevcut dizini (.), konteyner içindeki /app dizinine eşler. # Bu sayede host makinesinde yaptığınız kod değişiklikleri anında konteyner içinde de görünür olur. # nodemon gibi araçlarla birlikte kullanıldığında hot-reloading (canlı yeniden yükleme) sağlar. volumes: - .:/app # node_modules'in host makinesinde kalmasını engellemek için bir isimsiz volume. # Bu, node_modules'in konteyner içinde kalmasını ve performans artışı sağlar. - /app/node_modules # Konteyner için ortam değişkenleri tanımlar. environment: NODE_ENV: development # MONGO_URI: mongodb://db:27017/my-database # Eğer veritabanı kullanıyorsanız # Bu servisin başlatılmadan önce hangi servislerin hazır olmasını beklediğini belirtir. # db servisini eklediğimizde kullanışlıdır. # depends_on: # - db # Örnek bir MongoDB veritabanı servisi (isteğe bağlı) # db: # # MongoDB'nin resmi Docker imajını kullanır. # image: mongo:latest # # Konteyner içindeki 27017 portunu host makinesindeki 27017 portuna eşler. # ports: # - "27017:27017" # # Veritabanı verilerinin kalıcı olması için volume eşleştirmesi. # # db-data adında bir volume oluşturur ve konteyner içindeki /data/db dizinine bağlar. # volumes: # - db-data:/data/db

Tanımlanan tüm named volume'leri içerir.

volumes:

db-data: # Veritabanı verileri için kalıcı depolama

Açıklamalar:

* version: '3.8': Docker Compose dosyasının sürümünü belirtir.
* services: Uygulamanızın farklı bileşenlerini (servislerini) tanımladığınız ana bölümdür.
* app: Node.js uygulamanız için bir servis tanımlar.
* build: .: Bu servisin imajının mevcut dizindeki Dockerfile kullanılarak oluşturulacağını belirtir.
* ports: - "3000:3000": Host makinesindeki 3000 portunu, app konteyneri içindeki 3000 portuna eşler. Bu sayede tarayıcınızdan http://localhost:3000 adresine giderek uygulamanıza erişebilirsiniz.
* volumes: - .:/app: Bu, geliştirme ortamı için en önemli kısımlardan biridir. Host makinesindeki mevcut dizini (.), konteyner içindeki /app dizinine bağlar. Bu sayede, host makinenizde kodunuzda yaptığınız herhangi bir değişiklik anında konteyner içinde de görünür olur. nodemon gibi araçlarla birleştiğinde, kodunuzu kaydettiğiniz anda uygulamanız otomatik olarak yeniden başlar.
* - /app/node_modules: Bu, bir “anonymous volume” (isimsiz volume) olarak adlandırılır. Amacı, host makinesindeki node_modules klasörünün, volume eşleştirmesi nedeniyle konteyner içindeki node_modules klasörünü ezmesini engellemektir. Böylece node_modules bağımlılıkları konteyner içinde kalır ve platformlar arası uyumluluk sorunları yaşanmaz.
* environment: - NODE_ENV=development: Konteyner içinde kullanılabilecek ortam değişkenlerini tanımlar.
* depends_on: Eğer uygulamanızın bir veritabanı gibi başka bir servise ihtiyacı varsa, bu servisin başlamadan önce hangi servislerin hazır olmasını bekleyeceğini belirtir.
* db (yorum satırı içinde): İsteğe bağlı olarak ekleyebileceğiniz bir MongoDB veritabanı servisidir. image: mongo:latest ile MongoDB’nin resmi imajını kullanırız. volumes: - db-data:/data/db ile veritabanı verilerinin kalıcı olmasını sağlarız; yani konteyner silinse bile verileriniz kaybolmaz.
* volumes: db-data gibi adlandırılmış volume’leri tanımladığınız yerdir.

Adım 3: Uygulamayı Çalıştırma ve Yönetme

Dockerfile ve docker-compose.yml dosyalarını oluşturduktan sonra, uygulamanızı Docker Compose ile çalıştırmaya hazırsınız. Projenizin kök dizininde (bu iki dosyanın bulunduğu yerde) terminali açın ve aşağıdaki komutları kullanın:

Uygulamayı Başlatma

docker-compose up --build -d

* docker-compose up: docker-compose.yml dosyasında tanımlanan tüm servisleri başlatır.
* --build: Eğer Dockerfile‘da veya uygulama kodunuzda bir değişiklik yaptıysanız, bu bayrak Docker’a imajı yeniden oluşturmasını söyler. İlk çalıştırmada mutlaka kullanmalısınız.
* -d (detached mode): Servisleri arka planda çalıştırır ve terminali serbest bırakır.

Komutu çalıştırdıktan sonra, tarayıcınızı açıp http://localhost:3000 adresine giderek Node.js uygulamanızın çalıştığını görebilirsiniz.

Konteyner Loglarını Görüntüleme

Uygulamanızın çıktılarını veya hata mesajlarını görmek için aşağıdaki komutu kullanabilirsiniz:

docker-compose logs -f app

* logs: Servislerin loglarını gösterir.
* -f (follow): Logları gerçek zamanlı olarak takip eder.
* app: Hangi servisin loglarını görmek istediğinizi belirtir. (Örn: db servisi için docker-compose logs -f db)

Konteyner İçine Erişim

Bazen konteyner içinde bir komut çalıştırmanız veya dosya sistemini incelemeniz gerekebilir. Bunun için exec komutunu kullanabilirsiniz:

docker-compose exec app bash

Bu komut, app servisi konteynerinin içine bir bash kabuğu açar. İçeride ls, npm gibi komutları çalıştırabilirsiniz. Çıkmak için exit yazın.

Uygulamayı Durdurma ve Silme

Geliştirme işiniz bittiğinde veya konteynerleri yeniden başlatmak istediğinizde:

docker-compose down

Bu komut, docker-compose.yml dosyasında tanımlanan tüm servisleri durdurur ve ilgili konteynerleri siler.
Eğer veritabanı gibi kalıcı verileri de silmek isterseniz (volume’leri de kaldırmak için):

docker-compose down -v

* -v: Servislerle ilişkilendirilmiş tüm volume’leri de (örneğin db-data volume’ü) siler. Dikkatli kullanın, bu işlem verilerinizi kalıcı olarak silebilir.

Geliştirme Süreci ve Faydaları

Docker Compose ile Node.js geliştirme ortamınızı kurmanın sunduğu başlıca faydalar ve geliştirme sürecine etkileri şunlardır:

* Canlı Yeniden Yükleme (Hot-Reloading): volumes: - .:/app eşleştirmesi ve nodemon kullanımı sayesinde, host makinenizde kodunuzu kaydettiğiniz anda Node.js uygulamanız konteyner içinde otomatik olarak yeniden başlar. Bu, geliştirme hızınızı önemli ölçüde artırır.
* Bağımlılık Yönetimi: Tüm bağımlılıklar konteyner içinde izole edildiği için, farklı projeler arasında bağımlılık çakışmaları yaşamazsınız. Her proje kendi ortamında, kendi bağımlılık setine sahip olur.
* Kolay Onboarding: Yeni bir geliştirici ekibinize katıldığında, sadece Docker Desktop’ı kurması ve projenin kök dizininde docker-compose up --build -d komutunu çalıştırması yeterli olur. Tüm geliştirme ortamı saniyeler içinde hazır hale gelir.
* Veritabanı Entegrasyonu: docker-compose.yml dosyasına ekleyeceğiniz bir db servisi ile uygulamanızın veritabanı ihtiyacını kolayca karşılayabilirsiniz. Node.js uygulamanız, db servisine mongodb://db:27017/my-database gibi bir URL ile bağlanabilir. Docker Compose, servisler arasında otomatik ağ iletişimi sağlar, bu yüzden db servisine ismiyle erişebilirsiniz.
* Ortam Tutarlılığı: Herkesin aynı ortamda çalışması, “benim makinemde çalışıyor” gibi sorunları ortadan kaldırır. Bu, hataların daha kolay tespit edilmesini ve çözülmesini sağlar.

Sonuç ve Sıkça Sorulan Sorular (SSS)

Bu rehberde, Node.js uygulamanızı Docker Compose kullanarak geliştirme ortamı için nasıl konteynerleştireceğinizi adım adım öğrendiniz. Dockerfile ile uygulamanız için bir imaj oluşturmayı, docker-compose.yml ile servislerinizi tanımlamayı ve bu servisleri nasıl çalıştırıp yöneteceğinizi gördünüz. Bu yaklaşım, geliştirme sürecinizi büyük ölçüde basitleştirerek daha verimli ve tutarlı bir deneyim sunar.

Sıkça Sorulan Sorular (SSS)

S: docker-compose down ile docker-compose down -v arasındaki fark nedir?
C: docker-compose down sadece servisleri durdurur ve konteynerleri siler. Volume’leri (kalıcı depolama alanlarını) silmez. docker-compose down -v ise servisleri durdurur, konteynerleri siler ve ayrıca servislerle ilişkilendirilmiş tüm volume’leri de siler. Veritabanı verileri gibi kalıcı verilerinizi silmek istemiyorsanız -v bayrağını dikkatli kullanmalısınız.

S: Neden node:lts-alpine imajını kullanıyoruz?
C: alpine tabanlı imajlar, standart Debian tabanlı imajlara göre çok daha küçüktür. Bu, daha az disk alanı kaplar, daha hızlı indirilir ve daha hızlı konteyner oluşturulmasını sağlar. Geliştirme ve üretim ortamları için genellikle tercih edilen bir seçimdir.

S: Ortam değişkenlerini nasıl ekleyebilirim?
C: docker-compose.yml dosyasındaki bir servisin altına environment: bölümünü ekleyerek ortam değişkenlerini tanımlayabilirsiniz:

services:
  app:
    environment:
      NODE_ENV: development
      API_KEY: your_secret_key

Veya .env dosyası kullanarak da ortam değişkenlerini yönetebilirsiniz. Docker Compose, docker-compose.yml dosyasının bulunduğu dizindeki .env dosyasını otomatik olarak yükler.

S: Kod değişikliklerim konteynerde neden görünmüyor?
C: Büyük olasılıkla docker-compose.yml dosyanızdaki volumes: eşleştirmesi doğru yapılmamıştır veya eksiktir. volumes: - .:/app satırının doğru olduğundan ve Node.js uygulamanızın (nodemon gibi bir araçla) dosya değişikliklerini dinleyecek şekilde yapılandırıldığından emin olun. npm run dev komutunun nodemon‘u çalıştırması gerekir.

S: Konteyner içindeki uygulamamda nasıl hata ayıklayabilirim (debug)?
C: VS Code gibi modern IDE’ler, Docker konteynerlerine uzaktan bağlanmak için eklentilere sahiptir (örn. Remote – Containers eklentisi). Ayrıca, Node.js uygulamanızı --inspect bayrağı ile başlatıp, host makinenizden bir Chrome tarayıcı veya IDE’niz ile bağlanarak hata ayıklayabilirsiniz. Dockerfile‘daki CMD komutunu CMD ["node", "--inspect=0.0.0.0:9229", "index.js"] olarak değiştirip, docker-compose.yml dosyanızda 9229 portunu da eşlemeniz gerekebilir (- "9229:9229").

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.