Merhaba,

 

Bu yazıda MEVN Stack için Docker kullanımından bahsedeceğim. MEVN Stack; MongoDB, Express.js, Vue.js ve Node.js'in birleşiminden oluşmaktadır. Docker ile ilgili detaylı bilgiye de buradan ulaşabilirsiniz.

 

Yapacağımız örnek proje ile amacımız,  MEVN Stack için geliştirme ortamını bir Docker container'ı üzerinde ayağa kaldırmak olacaktır.

 

İlk olarak istediğimiz bir dizine gidip mevn-stack-docker adında bir klasör oluşturuyoruz (elbette siz farklı isimde oluşturabilirsiniz):

mkdir mevn-stack-docker

 

Sonrasında bu klasörün içine gidip backend ve frontend adında iki klasör daha oluşturuyoruz:

cd mevn-stack-docker
mkdir backend
mkdir frontend

 

Backend

 

Şimdi de backend klasörü içine giderek Express.js projemizi oluşturuyoruz:

cd backend
express .

 

Gerekli bağımlılıkları kuruyoruz:

npm install

 

MongoDB bağlantısı için gerekli paketi kuruyoruz:

npm install mongoose --save

 

app.js dosyasını açarak MongoDB bağlantısı için gerekli kodları ekliyoruz:

var mongoose = require('mongoose');

var mongoUrl = 'mongodb://database/db';
mongoose.connect(mongoUrl, function(err){
  if (err)
    console.log('mongodb connection error');
  else
    console.log('mongodb connected');
});

 

Projemizi ayağa kaldırıyoruz:

npm start

 

Şimdi backend projemiz için Docker image'ini oluşturalım. backend dizinindeyken Dockerfile dosyasını oluşturuyoruz:

touch Dockerfile

 

Node.js projesi için Dockerfile dosyasının nasıl olması gerektiğine dair bilgilere şuradan ulaşabilirsiniz. Biz de bu bilgileri kullanıp üzerinde ufak değişiklikler yapacağız. Dockerfile dosyamız şu şekilde olacak;

FROM node:14

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "start"]

Buradaki kodlar bize şunu ifade ediyor;

  • FROM node:14 => Image'i Docker Hub üzerindeki node'un 14 versiyonunu temel alarak oluştur
  • WORKDIR /usr/src/app => Projenin bulunacağı ve komutların çalıştırılacağı dizin olarak (çalışma dizini) /usr/src/app dizinini seç
  • COPY package*.json ./ => Local'de bulunan package.json ve package-lock.json dosyalarını projenin çalışma dizinine kopyala (./ şeklinde yazılan dizin çalışma dizinini ifade ediyor, yani burada tekrar /usr/src/app yazmamıza gerek yok)
  • RUN npm install => Çalışma dizininde npm install komutunu çalıştır
  • COPY . . => Local'de bulunan tüm proje dosyalarını çalışma dizinine kopyala
  • EXPOSE 3000 => Projenin çalışacağı port olarak 3000'i belirle
  • CMD ["npm", "start"] => Çalışma dizininde npm start komutunu çalıştır (RUN kısmından farklı olarak CMD kısmında yazılan komut Container ayakta olduğu sürece çalışmaya devam eder)

 

Local'de bulunan node_modules klasörünün Docker image'ine gitmesini istemediğimiz için .dockerignore şeklinde bir dosya oluşturuyoruz:

touch .dockerignore

 

.dockerignore dosyamızın içeriği;

node_modules

 

Artık backend tarafı için Docker image'ini oluşturabiliriz:

docker build -t backend-for-mevn-stack .

 

Frontend

 

Şimdi de frontend klasörü içine giderek Vue.js projemizi oluşturuyoruz:

cd ../frontend
vue create .

 

Gerekli bağımlılıkları kuruyoruz:

npm install

 

Projemizi ayağa kaldırıyoruz:

npm run serve

Şimdi frontend projemiz için Docker image'ini oluşturalım. frontend dizinindeyken Dockerfile dosyasını oluşturuyoruz:

touch Dockerfile

 

Vue.js projesi için Dockerfile dosyasının nasıl olması gerektiğine dair bilgilere şuradan ulaşabilirsiniz. Biz de bu bilgileri kullanıp üzerinde ufak değişiklikler yapacağız. Dockerfile dosyamız şu şekilde olacak (backend tarafında yaptıklarımıza çok benzer);

FROM node:14

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 8080

CMD ["npm", "run", "serve"]

Buradaki kodlar bize şunu ifade ediyor;

  • FROM node:14 => Image'i Docker Hub üzerindeki node'un 14 versiyonunu temel alarak oluştur
  • WORKDIR /usr/src/app => Projenin bulunacağı ve komutların çalıştırılacağı dizin olarak (çalışma dizini) /usr/src/app dizinini seç
  • COPY package*.json ./ => Local'de bulunan package.json ve package-lock.json dosyalarını projenin çalışma dizinine kopyala (./ şeklinde yazılan dizin çalışma dizinini ifade ediyor, yani burada tekrar /usr/src/app yazmamıza gerek yok)
  • RUN npm install => Çalışma dizininde npm install komutunu çalıştır
  • COPY . . => Local'de bulunan tüm proje dosyalarını çalışma dizinine kopyala
  • EXPOSE 8080 => Projenin çalışacağı port olarak 8080'i belirle
  • CMD ["npm", "run", "serve"] => Çalışma dizininde npm run serve komutunu çalıştır (RUN kısmından farklı olarak CMD kısmında yazılan komut Container ayakta olduğu sürece çalışmaya devam eder)

 

Local'de bulunan node_modules klasörünün Docker image'ine gitmesini istemediğimiz için .dockerignore şeklinde bir dosya oluşturuyoruz:

touch .dockerignore

 

.dockerignore dosyamızın içeriği;

node_modules

 

Artık frontend tarafı için de Docker image'ini oluşturabiliriz:

docker build -t frontend-for-mevn-stack .

 

Final

 

Sıra geldi en önemli kısma. Oluşturduğumuz Docker image'lerini birlikte çalışır hale getirip tek bir komutla ayağa kaldıracağız. Bunun için ana dizinimize gidiyoruz ve docker-compose.yml dosyamızı oluşturuyoruz:

cd ..
touch docker-compose.yml

 

docker-compose.yml dosyamızın içeriği şu şekilde;

version: '2'

services:
  backend:
    image: backend-for-mevn-stack
    ports:
      - "3000:3000"
    volumes:
      - ./backend/:/usr/src/app
    links:
      - database

  database:
    image: mongo
    ports:
      - "27017:27017"

  frontend:
    image: frontend-for-mevn-stack
    ports:
      - "8080:8080"
    volumes:
      - ./frontend/:/usr/src/app      

Bu kodlar da bize şunu ifade ediyor;

  • backend, database ve frontend adında container'lar oluştur
  • backend container'ı için backend-for-mevn-stack image'ini kullan. Çalışacağı port olarak 3000'i belirle (Burada "3000:3000" yazmamızın sebebi şu; soldaki 3000 ile projeye local ortamımızda hangi porttan erişmek istediğimizi, sağdaki 3000 ile projeye Docker üzerinde hangi porttan erişildiğini belirtiyoruz.
  • volumes kısmında Local'de bulunan backend dizini ile Docker üzerinde bulunan /usr/src/app dizinini birbirine eşitliyoruz. Böylece yaptığımız değişiklikler Docker'a da yansımış oluyor.
  • links kısmında backend container'ının database container'ına bağlı olduğunu belirtiyoruz.
  • database container'ı için Docker Hub üzerinde bulunan mongo image'ini kullan. Çalışacağı port olarak 27017'yi belirle
  • frontend container'ı için frontend-for-mevn-stack image'ini kullan. Çalışacağı port olarak 8080'i belirle. Yine aynı şekilde volumes kısmında dizinler için eşitlemeyi yaptık.

 

Son olarak gerekli komutu yazıp container'larımızı ayağa kaldırıyoruz:

docker-compose up

 

Konsola düşen yazılardan gördüğümüz üzere backend, database ve frontend container'larımız çalışıyor:

Docker Desktop programı üzerinden de container'ların çalışıp çalışmadığını kontrol edebiliriz:

Tarayıcıdan da aynı şekilde çıktılarımıza bakıyoruz:

 

Projenin Github reposuna buradan ulaşabilirsiniz.

 

Umarım yararlı olmuştur.

 

İyi çalışmalar.