Digital Cosmonot | Node Express API'yi Docker ile Dağıtmak

Node Express API'yi Docker ile Dağıtmak


 

 

 

Docker Nedir ?

 

Docker, Container teknolojisini kullanarak uygulamaların dağıtımını kolaylaştıran açık kaynak kodlu bir projedir. Aynı sistem üzerinde birden çok kapsayıcının birbirinden izole ve bağımsız bir şekilde güvenli çalışabilmesine olanak sağlar. DevOps ekosisteminde CI/CD süreçlerine destek olarak uygulamalar oluşturma, dağıtma, paketleme ve gönderme süreçlerini basitleştirir. Verimlilik ve hızlı dağıtım sağlayarak yazılımların Sürekli Entegrasyon/Sürekli Teslimat döngüsüne katkı sağlar.

 

VM ve Docker

 

Sanal makineler, her iş yükü için bir işletim sistemi gereksinimine ihtiyaç duyar. Ancak Konteyner teknolojisi birden çok iş yükünü tek bir işletim sistemi ile çalıştırabilir. Sanal makineler daha fazla bellek gereksinimine sahiptir fakat Docker Konteyner'ları daha az yer kaplar bu yüzden docker konteyner'ları sanal makinelere göre daha iyi çalışmaktadır, sanal makinelere göre daha hızlı önyükleme ve verimlilik sağlarlar.

 

Docker ve DevOps

 

DevOps; kurumların yazılım geliştirme süreçlerini basitleştiren, otomatize eden, daha verimli, güvenilir ve sürekli geliştirme, sürekli entegrasyon sağlayan bir ekosistemdir. DevOps hızlı ve sürekli yazılım testinin yanında, sorunların daha hızlı çözülmesine ve yönetimin kolaylaştırılmasına katkı sağlar. DevOps ekosisteminde çalışan kurumlar daha mutlu, üretken ve işbirlikçi ekipleriyle yaratıcılık ve üretkenlik için daha fazla zaman ayırarak daha fazla büyüme fırsatı yaratırlar.

Docker, DevOps yazılım yaşam döngüsü içersinde yer alan çeştli ekipler arasındaki iş birliğini destekler. Docker Konteyner'ları üzerinde çalışan uygulamalar istenildiği durumlarda bir önceki versiyona geçişi ve test süreçlerini hızlandırır. Docker, üzerinde çalışan konteyner uygulamalarının farklı bir sistemde de sorunsuz şekilde çalışacağını garanti eder. DevOps ekositemi; geliştirme, entegrasyon, test, prod ortamına taşıma olmak üzere çeşitli aşamalardan oluşur.
Docker, DevOps ekosisteminin Sürekli Dağıtım aşamasında kullanılır ve hayati bir rol oynar. Yazılım döngüsüne getirdiği güvenlik, ölçeklenebilirlik ve basitlik ile Docker, herhangi bir DevOps ortamında mutlaka kullanılmalıdır.

 

Makalenin bu bölümünde SQLite veritabanı kullanan ve kullanıcı verilerini REST API olarak sunan bir servis geliştirip bu servisi Docker Konteyner'ı olarak çalıştırdıktan sonra farklı ortamlara dağıtacağız.

 

 

1 - Express ile API Oluşturma

 

Docker Konteyner olarak çalıştırılacak olan API'nin Nodejs Express uygulaması olarak oluşturulabilmesi için ilk olarak uygulama klasörüne npm init -y komutu ile package.json dosyasını oluşturuyoruz.

 

start komutu ekleyip uygulamanın npm start komutu ile çalıştırılabilir halde olmasını sağlıyoruz.

 

  "name": "express-docker",
  "version": "1.0.0",
  "description": "Nodejs Express API",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.2",
    "sqlite3": "^5.0.2"
  }
}

 

 

npm install --save express ve npm install --save sqlite3  komutları ile express ve sqlite paketlerini projemize dahil ediyoruz. Main olarak app.js dosyasını ekledik. Proje kodlarını app.js dosyasına yazacağız, app.js dosyasını oluşturuyoruz ve içine gerekli paketlerin tanımlamasını yapıyoruz.

 

app.js:

 

const express = require("express")
const app = express()
const https = require("https")
const http = require("http")
const sqlite3 = require('sqlite3').verbose()
const bodyParser = require("body-parser")

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

const HOST = '0.0.0.0'
const PORT = 8080

app.get("/", (req, res, next) => {
    res.sendStatus(200)
});

app.use(function(req, res){
    res.sendStatus(404);
})

app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);

 

Daha sonra kullanıcıdan alınacak olan POST request body'sini parse edebilmek için bodyParser'ı da projemize dahil ettik ve API'nin yayınlanacağı PORT ve HOST tanımlamalarını da yaptık. / kök adresi için kullanıcıya servisin ayakta olduğuna dair bir http 200 OK durum kodu sağlıyoruz. Belirtilen endpointlerin dışında bir adrese gidilmesi halinde kullanıcıya 404 durum kodunu döndürüyoruz.

 

Uygulama başladığında bir SQLite Veritabanı oluşturabilmek ve içine rastgele oluşturulmuş test verilerini ekleyebilmek için users adında bir tablo oluşturuyoruz ve id, name, surname ve email olmak üzere alanlar tanımlıyoruz. id primary key olarak tanımlandı ve email bir kayıttan yalnızca bir kez olabilmesi adına UNIQUE olarak ayarlandı.

 

database.js:

 

const sqlite3 = require('sqlite3').verbose()
const databaseSource = "db.sqlite"

let db = new sqlite3.Database(databaseSource, (err) => {
    if (err) {
      console.error(err.message)
      throw err
    }
    else{
        console.log('Connected to Database')
        db.run(`CREATE TABLE users (
              id INTEGER PRIMARY KEY AUTOINCREMENT,
              name text NOT NULL,
              surname text NOT NULL,
              email text NOT NULL UNIQUE
            )`,
        (err) => {
            if (err) {
                console.error(err.message)
            }
            else{
                var insert = 'INSERT INTO users (name, surname, email) VALUES (?,?,?)'
                db.run(insert, ["Alex","Smith","alexsmith@hprsa.com"])
                db.run(insert, ["Latonya","Anderson","landerson@tradup.com"])
                db.run(insert, ["Eric","Vega","ericvega@rhyta.com"])
                db.run(insert, ["Marilyn","Duprey","marilynduprey@jourrapide.com"])
                db.run(insert, ["Elizabeth","Fortenberry","elizabethfortenberry@dayrep.com"])
            }
        });  
    }
});

module.exports = db

 

database.js dosyasını oluşturduktan sonra yeniden app.js dosyasına dönüyoruz ve database.js dosyasını burada tanımlayarak GET, POST, PATCH, DELETE için /api/users endpointlerini yapılandırıyoruz son durumda proje kodumuz:

 

const express = require("express")
const app = express()
const https = require("https")
const http = require("http")
const sqlite3 = require('sqlite3').verbose()
const db = require("./database.js")
const bodyParser = require("body-parser")

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

const HOST = '0.0.0.0'
const PORT = 8080

app.get("/", (req, res, next) => {
    res.sendStatus(200)
});


app.get("/api/users", (req, res, next) => {
    var sql = "select * from users"
    var params = []
    db.all(sql, params, (err, rows) => {
        if (err) {
          res.status(400).json({"error":err.message});
          return;
        }
        res.json({
            "users":rows
        })
      });
});


app.get("/api/users/:id", (req, res, next) => {
    var sql = "select * from users where id = ?"
    var params = [req.params.id]
    db.get(sql, params, (err, row) => {
        if (err) {
          res.sendStatus(400).json({"error":err.message});
          return;
        }
        res.json({
            "users":row
        })
      });
});


app.post("/api/users/", (req, res, next) => {
    var errors=[]
    if (!req.body.name){
        errors.push("No password specified");
    }
    if (!req.body.surname){
        errors.push("No email specified");
    }
    if (!req.body.email){
        errors.push("No email specified");
    }
    if (errors.length){
        res.status(400).json({"error":errors.join(",")});
        return;
    }
    var data = {
        name: req.body.name,
        surname: req.body.surname,
        email : req.body.email

    }
    var sql ='INSERT INTO users (name, surname, email) VALUES (?,?,?)'
    var params =[data.name, data.surname, data.email]
    db.run(sql, params, function (err, result) {
        if (err){
            res.status(400).json({"error": err.message})
            return;
        }
        res.json({
            "users": data,
            "id" : this.lastID
        })
    });
})


app.patch("/api/users/:id", (req, res, next) => {
    var data = {
        name: req.body.name,
        surname: req.body.surname,
        email : req.body.email
    }
    db.run(
        `UPDATE users set
           name = COALESCE(?,name),
           surname = COALESCE(?,surname),
           email = COALESCE(?,email)
           WHERE id = ?`,
        [data.name, data.surname, data.email, req.params.id],
        function (err, result) {
            if (err){
                res.status(400).json({"error": res.message})
                return;
            }
            res.json({
                users: data
            })
    });
})


app.delete("/api/users/:id", (req, res, next) => {
    db.run(
        'DELETE FROM users WHERE id = ?',
        req.params.id,
        function (err, result) {
            if (err){
                res.status(400).json({"error": res.message})
                return;
            }
            res.json({"message":"The user has been deleted"})
    });
})

app.use(function(req, res){
    res.sendStatus(404);
})

app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);

 

 

içine fake datalar ekledik, email alanının UNIQUE ve diğer alanların post request'lerinde boş geçilememesi gibi kurallar tanımladık, projemizi çalıştırıp tanımlanan endpointlere istek atabiliriz.

 

GET

 

 

GET ID

 

 

POST

 

 

PATCH

 

 

 

DELETE

 

 

Projenin Docker İmajının Alınması

 

Nodejs Express ile geliştirilen API'nin bir Docker Konteyner'ı olarak çalıştırılabilir halde olması için öncelikle imajının oluşturulması gerekiyor. Proje klasörümüze bir Dockerfile dosyası oluşturup içine Docker build ederken kullanacağımız ayarları tanımlıyoruz.

Dockerfile dosyasının içeriği:

 

FROM node:14
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD [ "node", "app.js" ]

 

Uygulama imajını tanımlamadan önce bir de .dockerignore dosyasına ihtiyacımız var. Çalışma mantığı oalrak docker ignore dosyası .gitignore dosyasına benzemekte.

 

.dockerignore dosyası

 

 

node_modules
npm-debug.log

 

 

Her şey hazır olduğunda docker kurulu Windows makinemden

docker build -t mehmetdy/dockerize-express-user-api . komutunu çalıştırarak uygulamanın build edilmesini bekliyorum.

 

 

 

Build işlemi tamamlandıktan sonra docker images komutu ile docker imajının başarılı bir şekilde oluşturulduğunu görüyoruz. artık bu imajı bir Konteyner'da ayağa kaldırarak Nodejs Express API'mi Docker üzerinde çalıştırabilirim. docker run -p 8080:8080 c6127b4e4164 yazarak bir Konteyner oluşturup uygulamamı 8080 portunda çalıştırmasını bekliyorum. Docker run komutundan sonra ilgili imaj adı yazılabilir..

 

 

 

 

Her şey tamamlandı ve artık Docker Konteyner'ında çalışan bir Express API'miz var. docker ps -a komutu ile çalışan konteyner'ları görüntülenebilir. Aynı endpint ve port üzerinden API'ye istek attığımda tüm kullanıcıları sorunsuz bir şekilde görüntüleyebiliyorum. 

 

Docker Projesini Docker Hub'a Pushlama

 

Express API Projesi Docker Konteyner'ında çalışıyor. Projemizi Docker Hub'a gönderip daha sonra farklı bir makineden yeniden pull ederek Linux ortamında da test edeceğiz. Kendi Docker Hub Repository'me ilgili projeyi public bir şekilde göndereceğim. docker push mehmetdy/express-user-api komutunu çalıştırıyorum. mehmetdy docker hub kullanıcı adım.

 

 

 

 

Docker Hub'dan Projeyi Pull ile Yeniden İndirme

 

Bu noktaya kadar Windows ortamında geliştirilen projenin Docker imajını oluşturup Docker Hub repository'mize gönderdik. Linux işletim sistemi üzerinden projemizi pull ederek çalıştıracağız. Docker kurulu Linux Kernel'ine sahip İşletim sistemimde docker pull mehmetdy/dockerize-express-user-api:latest komutunu çalıştırarak docker projemi buraya çekiyorum işlem tamamlandıktan sonra docker images komutu ile kontrolünü yapıyorum ve indirdiğini gördükten sonra yine run komutu ile konteyner'ı ayağa kaldııyorum.

 

 

 

 

Uygulama Konteyner olarak sorunsuz bir şekilde ayağa kalktı ve çalışır durumda. GET İsteği yollayarak tüm kullanıcıları getirmesini sağlıyorum.

 

 

 

Her şey tamam ve Finalde Windows Ortamında geliştirdiğimiz bir Express uygulamasını Linux Ortamına saniyeler içinde taşıyarak sorunsuz bir şekilde çalışmasını sağladık. 

 

Proje Docker Hub => docker pull mehmetdy/dockerize-express-user-api:latest

Mehmet Duygu

Digital Cosmonot Bilişim Danışmanlık Eğitim LTD. ŞTİ.

YORUMLAR

Yorum Ekle