Hocanın dökümantasyonu https://github.com/gkandemi/docker
Proses izolasyonu sağlar. Çalıştırılan programın ortamı, ortamın da uygulamayı etkilemesini engeller.
Container kendine ait prosesleri, servisleri ve ağı olan. Aymı işletim sistemi veya virtual machine (VM) üzerinde çalışan, diğer ortamlardan izole edilmiş ortamlardır.
Docker, container ile işletim sistemi kerneli arasında bağlantıyı sağlar.
Docker container işini kolaylaştırmak için bize birçok high level araç sunar.
Docker LXC container türü kullanır.
Windows üzerine docker yüklendiğinde Docker araya otomatik olarak linux VM yükler ve containerları kendisinin yüklediği linux VM üzerinden yönetir.
Container çalışan yapılardır. Kaynak kod image içinde.
image içinde birçok yapıyı barındırabilir. Containerin nasıl çalışacağını anlatır. image çalıştırıldığında container oluşturur. Bu image dosyaları genelde bulutta tutulur. Docker için genelde Docker Hub kullanılır. İmageı çalıştırdığımızda elde ettiğimiz proses containerdır. İmage çalışmayı durdurduğunda container ortadan kalkar.
DockerHub üzerinden ubuntu indirmek için docker pull ubuntu. docker imajından ubuntu çalıştırmak için docker run ubuntu bilgisayarda yoksa image dosyasını kendisi çeker ve çalıştırır.
docker.com adresinden indir ve kur.
dockerhub>"Explore" filtrelemede
Terminale
docker pull ubuntuyazdık. Dockerhub üzerinden ubuntuyu çekti
Terminale
docker pull mongoyazdık. Dockerhub üzerinden mongoyu çekti
docker imagesyazdığımızda indirmiş olduğumuz docker images listelenir
docker run redisyazdığımızda redis lokalde varsa çalışır. Yoksa image indirilir ve çalıştırılır. Çalıştığını terminalde görürüz.
docker run ubuntuile ubuntu çalışır ama hemen geri kapanır.
docker run ubuntu sleep 5ile ubuntu açılır 5 sn bekler ve kapanır.
docker run -it ubuntuile ubuntu açılır ve içinde işlem yapılabilir.
-it interaktif terminal anlamında.
docker psveya
docker conlainer lsayakta olan containerları gösterir.
docker ps -aveya
docker ps --allveya
docker conlainer ls -aayakta olan olmayan tüm containerları gösterir
docker run -it --name bash_ubuntu ubuntuolarak yazdığızda container bash_ubuntu adını alır ve isim altında ayarları da kaydedilir.
docker start bash_ubuntuyazarak ismini ve özelliklerini kaydettiğimiz container ayağa kaldırılır. Terminalde kaybolur. Arka planda çalışır.
docker stop bash_ubuntuile kapatılır.
docker stop <container-name> kısmında <container-name> yerine <container-id> nin baştan ilk 2 ve daha fazla karakteri girilerek de durdurma işlemi yapılabilir. container id lerin ilk kısmında çakışma olursa daha çok karakter girmek gerekir.
docker ps -aile listelediğimiz herhangi bir container bu yöntemle açılabilir ve kapatılabilir.
docker ps -aile listelenenleri silmek için
docker rm <container-name>yazarak tek tek silebiliriz.
docker start ve docker stop kodlarındaki gibi name yerine idnin başı yazılabilir. Id veya name boşluk bırakılarak birden fazla yazılabilir.
docker container rm $(docker container ls -aq)tüm idleri silme fonksiyonuna taşıyarak tüm containerları siler.
docker imagesile listelenenleri silmek için
docker rmi <image-name>yazarak tek tek silebiliriz.
sürüm?
docker run redis:5redisin 5. sürümünü indirir ve çalıştırır.
docker image tag <image name veya id> <new tag name>ile images name değiştirilir.
docker image tag ubuntu my_ubuntuile my_ubuntu adında bir ubuntu kopyası elde ederiz.
Detach mode: Çalıştırılan imageın oluşturduğu container arka planda çalışsın.
docker run -d redis
Attach mode: detach modda çalışan uygulamayı öne getirir
docker attach <container id veya name>
docker attach bold_meitnerile bold_meitner isimli container öne getirilir.
Log: detach modda çalışan uygulamanın verdiği logları görmek için kullanılır.
docker container logs <container id veya name>
kullanıcı girişli bir uygulamanız varsa kullanıcı girişini (interaktif terminal) açabilmek için -it flagi kulanılır.
docker run -it gkandemir/interactive-terminal-app
docker run -p Dış_port:iç_port image_name
docker run -d 27018:27017 mongodışarıdan biz bağlandığımızda 27018 portunu kullanır. docker içinde ise default portu olan 27017 kullanılır. mongoDBCompass
mongodb://localhost:27018 ile bu mongoya bağlanabilir.
docker run gkandemir/node-appyazdığımızda terminalde
Example app listening at http://localhost:3000yazar ancak biz buna web tarayıcımızdan erişemeyiz. Çünkü 3000 portu docker içi için geçerlidir.
docker run -p 3001:3000 gkandemir/node-appyazdığımızda dış portu olan 3001 portuna web tarayıcıya "http://localhost:3001/" yazarak ulaşabiliriz.
Birden fazla container birden fazla portta eş zamanlı çalıştırabiliriz.
Dockerhost üzerinde containerlar stateless olarak çalışır. Yani içindeki bilgileri kayıt etmez. Container durduğunda içindeki bilgiler silinir.
Kaydedilecek bilgiler için volume kullanılır. Bir containerı ayağa kaldırdığımızda kayıt edilecek klasörün adresini docker host üzerinden bildiririz.
docker run -v /opt/data:/data/db mongodata/db içinde değişiklik olduğunda host içinde opt/data içine kaydet. Çalışırken de buradaki datayı al.
hangi dosyanın veri tutuğunu ve kaydedilmesi gerektiğini dökümantasyondan bulabiliriz.
docker içinde datanın tutulduğu klasörün docker desktop tarafından bilinen ve izin verilmiş bir klasör olması gerekiyor. (windowsta buna gerek yok. Herhangi bir dizini kabul ediyor.)
docker run -v /myData/data:/data/db mongo
Bizim kullandığımız docker versiyonunda volume almaya gerek var mı emin değilim. Her container açtığımda zaten Docker Desktop üzerinde bir volume açılıyor gibi. Belki image her container haline getirilirken bu veriyi de alması için kullanılyor olabilir.
container hakkında bilgi almak için
docker inspect <container name veya id>yazıyoruz.
Gelen ekranda "HostConfig" > "Binds" kısmında array olarak volume alınacak dosyalar mevcut. "HostConfig" > "PortBindings" port yönlendirmesini verir.
"Config" > "ExposedPosts" docker içindeki portu verir. "NetworkSettings" > "Ports" iç ve dış portunu verir.
image hakkında bilgi almak için
docker inspect <image name veya id>yazıyoruz.
docker run -e MYSQL_ROOT_PASSWORD=test123 -d mysql-e den sonraki kısım environment variable
docker pull phpmyadmin/phpmyadminile phpmyadmin image indirildi. mysql ile bunu bağlayacağız.
Önce bağlanılacak olan çalıştırılır.
docker run --name mysql-server -p 3306:3306 -e MYSQL_ROOT_PASSWORD=test123 -d mysql
Sonra bağlanacak olan çalıştırılır.
docker run --name pmyadmin -p 8000:80 --link mysql-server:db -d phpmyadmin/phpmyadmin
--link ten sonra bağlanacağı container name ve : sonrası bağlanacağı alias(takma ad) yazılır. Bu kısım dökümantasyonda verilir.
Tarayıcıda http://localhost:8000/ yazıp phpmyadmin açılır. kullanıcı adı: root, pass: test123 yazılarak mysql databasee bağlanılır.
Önce bağlanılacak olan çalıştırılır.
docker run --name mysql-server -p 3306:3306 -v /opt/data:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=test123 -d mysql
Sonra bağlanacak olan çalıştırılır.
docker run --name pmyadmin -p 8000:80 --link mysql-server:db -d phpmyadmin/phpmyadmin
--link ten sonra bağlanacağı container name ve : sonrası bağlanacağı alias(takma ad) yazılır. Bu kısım dökümantasyonda verilir.
Tarayıcıda http://localhost:8000/ yazıp phpmyadmin açılır. kullanıcı adı: root, pass: test123 yazılarak mysql databasee bağlanılır.
Dockerda 3 tür default network var: bridge, none, host
bridge network: default olarak kaldırılan image ile aldığımız neteork. Containerlar birbirine bir gateaway üzerinden bağlanıyor.
none network: dışarıdan erişilememesi için tanımlanmış network. Örn: docker run mongo --network=none
host network: docker host üzerinden sadece port numarası eklenerek ulaşılan network Örn: docker run mongo --network=host
Kullanıcının kendisinin tanımladığı network örn: docker network create --driver bridge --subnet 182.18.0.0/16 --gateway 182.18.0.1 todo-app-network
docker network lsveya
docker network listile tüm network görüntülenebilir.
docker network rm <network-name veya id>ile network silinebilir.
Normalde mongoDB gibi bir databasei uygulamamıza bağlarken
...
await Mongoose.connect("mongodb://localhost:27017/todos")
...
daki gibi localhost veya sabit bir ip kullanılır. Docker içinde her çalışmada ip sabit kalmadığından biz bunun yerine container name kullanırız.
...
await Mongoose.connect("mongodb://mongo-server:27017/todos")
...
docker pull gkandemir/todo-appile hocanın bu iş için oluşturduğu uygulamayı çektik.
Önce networkü oluşturuyoruz:
docker network create --driver bridge --subnet 182.18.0.1/24 --gateway 182.18.0.1 custom-network
--driver ile türünü belirttik. --subnet ile çalışma aralığını --gateway ile gatewayini belirttik. En son custom-network ise bizim ona verdiğimiz adı belirtti.
docker inspect <id>ile oluşan networkü inceleyebiliriz.
docker run --name mongo-server --net custom-network -d mongo
--name mongo-server kısmı uygulamamızda kullanacağımız container name ile aynı olmalı. --net custom-network bağlanacağı networkü seçtik.
docker run --net custom-network -p 3000:3000 gkandemir/todo-app
--net custom-network ile ağa bağlandık. Dışarıdan da ulaşabilmek için -p 3000:3000 ile port mapping yaptık.
postman ile http://localhost:3000 üzerinden bağlanıp data gönderebiliyoruz.
Bu bağlantıyı link yöntemi ile yapsaydık kod içinde alias tanımlamak gerekecekti.
docker pull ubuntu:18.04ile ubuntu v18.04 çekildi.
docker run -it ubuntu:18.04ile ubuntu container içine girildi.
ubuntu içinde terminale
apt-get updateyazarak güncellemeler yapıldı.
apt-get install curl -yile curl kuruldu.
curl -sL https://deb.nodesource.com/setup_10.x | bashile node.js indirildi.
apt-get install nodejs -yile indirilen nodejs kuruldu.
cd opt
mkdir node-app
cd node-app
ile bir dosya oluşturuldu ve içine girildi.
echo 'console.log("nodejsapp from ubuntu ...");' > index.js ile index.js dosyası oluşturuldu ve içine console.log("nodejsapp from ubuntu ..."); yazıldı.
node index.jsyazdığımızda terminalde
nodejsapp from ubuntu ...yazısı belirdi. Bu da bize node.jsin ubuntuda düzgün çalıştığını gösterdi.
ubuntuda
historyyazınca o zamana kadar ubuntu terminalinde yaptıklarımızı listeler.
1 apt-get update
2 apt-get install curl -y
3 curl -sL https://deb.nodesource.com/setup_10.x | bash
4 apt-get install nodejs -y
5 ls
6 cd opt
7 ls
8 mkdir node-app
9 ls
10 cn note-app
11 cd note-app
12 ls
13 cd node-app
14 echo 'console.log("nodejsapp from ubuntu ...");' > index.js
15 ls
16 node index.js
17 history
Bir proje klasörü oluşturduk ve içinde index.js
console.log("Hello from ubuntu")
ve Dockerfile dosyası daha önce aldığımız historiye göre oluşturuldu.
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install curl -y
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash
RUN apt-get install nodejs -y
COPY . /opt/node-app/
# Yukarıdaki kısım imageden container oluşturmak için
# aşağıdaki kısım oluşan containerın çalışma anında çalışacak kısım.
# CMD [ "node", "/opt/node-app/index.js" ]
WORKDIR /opt/node-app/
CMD [ "node", "index.js" ]
oluşturuldu.
Dockerfile dosyasında önce containerın açılacağı image FROM ile belirlendi. Sonra bunun içindeki işlemler RUN ile oluşturuldu. COPY . /opt/node-app/ komutu ile bu dizindeki tüm dosyalar container içinde belirtilen yere eklendi. Bu kısım image -> container işlemi için gerekli.
WORKDIR ile bundan sonra çalışılacak dizin belirlendi. CMD [ "node", "index.js" ] ile container çalışmaya başladığında yapacağı iş tanımlandı.
Proje dosyasında terminal açıldı.
docker build .işlemi bende hata verdi.
docker system pruneile dockerı tamamen temizleyip tetkrar deneyince oldu :D
docker imagesyazınca bizim oluşturduğumuz image de listeleniyor.
isim vermek için
docker build . -t simple-node-app
Dockerfile içindeki her işlem adımı docker içerisinde layer olarak tutulur. Başka bir image için aynı şeye gerek olduğunda işlem oradan kopyalanır. Bu nedenle zaten dockerımızda olan bir işlem yapıldığında çok hızlı yapar.
index.js aşağıdaki gibi güncellendi.
console.log("Hello from ubuntu")
console.log("env =>", process.env.channel)
Dockerfile içine ENV olarak eklendi.
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install curl -y
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash
RUN apt-get install nodejs -y
COPY . /opt/node-app/
#
ENV channel=kablosuzkedi
# Yukarıdaki kısım imageden container oluşturmak için
# aşağıdaki kısım oluşan containerın çalışma anında çalışacak kısım.
# CMD [ "node", "/opt/node-app/index.js" ]
WORKDIR /opt/node-app/
CMD [ "node", "index.js" ]
docker build . -t simple-node-appile tekrar build alınır.
docker run simple-node-appile çalıştırıldı ve treminalde aşağıdaki çıktı alındı.
Hello from ubuntu
env => kablosuzkedi
Dockerfile doldururken en üstte muhakkak baseimage olmalı.
Yeni bir proje klasörü oluşturuldu ve index.js önceki projeden kopyalandı
Dockerfile
FROM node
WORKDIR /opt/node-app
COPY . .
ENV channel=kablosuzkedi
CMD [ "node", "index.js" ]
docker build . -t simple-node-app-2ile image oluşturulur.
image dosyası 1.1 GB. Bıyutu daha önce kendimizin ubuntu ile yaptığından daha büyük. Bu nedenle node versiyonunu 16-slim ile değiştirdik.
FROM node:16-slim
WORKDIR /opt/node-app
COPY . .
ENV channel=kablosuzkedi
CMD [ "node", "index.js" ]
Önceki image silindi
docker rmi simple-node-app-2ve yeniden image alındı
docker build . -t simple-node-app-2
İmage dosyamız şimdi 179MB :D
docker run simple-node-app-2yazdığımızda terminalde
Hello from ubuntu
env => kablosuzkedi
cevabı alındı.
Yeni bir proje klasörü oluşturuldu ve içine App.js eklendi.
const express = require("express");
const app = express();
const PORT = process.env.PORT || 3000;
app.get("/", (req, res) => {
res.send("hello world");
});
app.listen(PORT, () => {
console.log(`Example app listening at http://localhost:${PORT}`);
});
npm paketlerini kullanabilmek için terminale
npm init -yyazdık. Sonra express modülünü indirmek için
npm install --save expressyazıldı.
Bu hali ile çalıştırdığımızda server lokalde çalışıyor.
image alırken "node_modules" klasörünü da kopyalamamak için ".dockerignore" klasörü oluşturuldu ve içine
node_modules/yazıldı.
Dockerfile dosyası oluşturuldu.
FROM node:16-slim
WORKDIR /opt/node-server
COPY . .
RUN npm install
CMD ["node", "app.js"
docker run simple-node-serverile image container haline gelir ve çalıştırılır. Terminalde
Example app listening at http://localhost:3000çıktısı alınır.
docker run -p 3001:3000 simple-node-serverile dışarıya port açılır ve http://localhost:3001/ üzerinden görülebilir.
Yeni bir uygulama klasörü oluşturduk. İçinde index.php dosyası oluşturduk.
<?php
echo "PHP Uygulamasını Dockerize Etmek...";
?>
Dockerfile dosyası oluşturup içine:
FROM php:7-apache
COPY index.php /var/www/html/index.php
EXPOSE 80
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
yazıldı.
Proje klasöründe terminale
docker build . -t simple-php-appyazılarak image oluşturuldu.
docker run -p 8080:80 simple-php-appdiyerek uygulama up edilir. http://localhost:8080/ üzerinden de görüntülenebilir.
Yeni bir proje klasörü açtık ve hocanın hazır kodlarını kullandık.
App.js
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
const { TodoModel } = require("./TodoModel");
const Mongoose = require("mongoose");
const PORT = process.env.PORT || 3000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());
app.get("/", (req, res) => {
TodoModel.find({})
.then((todoList) => res.status(200).json(todoList))
.catch((e) => res.status(500).json(e));
});
app.post("/todo", (req, res) => {
const todo = new TodoModel({
...req.body,
created_at: new Date(),
});
todo
.save()
.then((savedTodo) => res.status(200).json(savedTodo))
.catch((e) => res.status(400).json(e));
});
app.listen(PORT, async () => {
console.log(`Sunucu çalışıyor... ${PORT} | MongoDB'ye bağlanılacak..`);
await Mongoose.connect("mongodb://mongo-alias:27017/todos", {
useNewUrlParser: true,
useUnifiedTopology: true,
});
console.log("MongoDB'ye bağlantı başarılı!");
});
TodoModel.js
const Mongoose = require("mongoose");
const todoSchema = new Mongoose.Schema({
title: String,
description: String,
completed: Boolean,
created_at: Date,
});
module.exports = {
TodoModel: Mongoose.model("todo", todoSchema),
};
package.json
{
"name": "node-mongo",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"mongoose": "^5.11.13"
},
"devDependencies": {
"nodemon": "^2.0.7"
}
}
Terminale
npm iyazıp bağımlılıkları indirdik.
.dockerignore dosyasına
node_modules/yazdık.
Dockerfile dosyasına
FROM node:16-slim
WORKDIR /opt/node-todo-app
COPY . .
ENV PORT=4000
EXPOSE 4000
RUN npm install
CMD ["node", "app.js"]
yazdık.
proje klasörünü terminalde açıp
docker build . -t todo-appyazarak image aldık.
docker run --name mongo-server -p 27017:27017 -d mongoile mongo server ayağa kaldırıldı.
docker run --link mongo-server:mongo-alias -p 4000:4000 todo-app
--link mongo-server:mongo-alias kısmında mongo-server adındaki containera bağlan, bu bağlantı senin kodunda mongo-alias olarak geçiyor dedik. app.js kodunu incelersek orada await Mongoose.connect("mongodb://mongo-alias:27017/todos"...) kullanımını görürüz.
CMD Container ayağa kalktığında çalışacak fonksiyon. CMD tam bir fonksiyondur. Container çalıştığında çalışır. CMD override edilebilir.
ENTERYPOINT sadece executable komut içerir. Komutun parametresini çalışma anında bizden bekler. Yoksa çalışmaz. Varsayılan değer atamak için Dockerfile içinde hemen altında CMD ile varsayılan değer belirtilebilir.
Container yapılacak bir işlem varsa açık kalır yoksa kapanır.
Yeni proje klasörü aç. Dockerfile dosyası
FROM ubuntu:18.04
CMD ["sleep", "4"]
# Bu yazım şeklinde 1. komut executable (çalıştırılabilir) olmalı. Devamında array olarak parametreler girilir.
# CMD sleep 4
# Bu yazımda direk çalıştırılacak kod yazılır.
Proje klasöründe
docker build -t ubuntu-sleeper .yazılarak image oluşturulur ve
docker run ubuntu-sleeperyazarsak cotainer 4 sn açık kalır. sonra kendini kapatır.
docker run ubuntu-sleeper sleep 10yazarsak 10 sn sonra container kapanır.
run komutunda container adından sonra girilen komut cmd ile girdiğimiz yere override olur (üzerine yazılır).
Dockerfile dosyası
FROM ubuntu:18.04
ENTRYPOINT [ "sleep" ]
terminalde docker build -t ubuntu-sleeper .yazılarak image oluşturulur ve
docker run ubuntu-sleeper 5yazarsak cotainer 5 sn açık kalır. sonra kendini kapatır.
docker run ubuntu-sleeperyazarsak terminal bize
sleep: missing operand
Try 'sleep --help' for more information.
döner.
ENTERYPOINT terminalden gelen veriyle çalışır. Buna defaut değer atamak için hemen altında CMD kullanılır.
FROM ubuntu:18.04
ENTRYPOINT [ "sleep" ]
CMD ["4"]
Terminale değer girilmezse default olarak 4 alır.
Birden fazla container ayağa kaldırıp birlikte kullanma işlemlerinde docker compose kullanılır.
Hoca docker compose a girmeden 2 Dockerfile örneği daha yapmak istiyor. Biz de öyle yaparız :D
Yeni bir proje klasörü içine hocanın hazırlamış olduğu src/server.py dosyasını
from flask import Flask
server = Flask(__name__)
@server.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
server.run(host='0.0.0.0')
ve dependencies.txt dosyasını
Flask==2.2.3
ekledik.
Dockerfile dosyasını
FROM python:3.8-slim
WORKDIR /server
COPY dependencies.txt .
RUN pip install -r dependencies.txt
COPY src/ .
CMD ["python", "./server.py"]
olarak yazdık.
Proje dosyasında terminale
docker build . -t python-appyazarak image oluşturduk.
docker run -p 3000:5000 python-appile uygulama ayağa kaldırıldı.
Hocanın hazırladığı örneği proje klasörümüze kopyaladık.
Dockerfile
FROM node:14-slim
WORKDIR /vue-app
COPY app/ .
RUN npm install
RUN npm install -g live-server
RUN npm run build
EXPOSE 8080
CMD [ "live-server", "dist" ]
Proje dosyasında terminale
docker build . -t vue-appyazarak image alındı.
docker run -p 9000:8080 vue-appile app ayağa kaldırıldı. http://localhost:9000/ ile uygulamaya ulaşılabiliyor.
docker contaşner prune ile tüm containerlar silinir.
docker images prune ile tüm images silinir. docker volume prune ile de tüm volume silinir. Bu kalıp diğer bileşenlerde de uygulanabilir.
Birden fazla container ayağa kaldırıp birlikte kullanma işlemlerinde docker compose kullanılır.
Docker compose için proje klasörümüzde docker-compose.yml adında bir dosya oluşturuyoruz. .yml YMAL file dosya uzantısıdır. Bilgi aktarımı için kullanılır. JSON ve xml e göre daha kolay ve basit bir kullanımı var. Key: value düzeni ile yazılır. value array ise -
işareti ile alt alta yazılır. Subkey bir iç çıkıntıda yazılır. Bu nedenle intent (çıkıntı) kavramı çok önemli.
İlk önce version
keyi yazılır. Dockerın hangi sürümünün kullanılacağını belirler. Bu yapılacak işlemleri etkiler.
sonra services
altına çalıştırılacak containerlar yazılır.
önceki projelerde yaptığımız node server içindeki app.js, package.json ve package-lock.json proje klasörümüzde app klasörüne kopyalandı. Dockerfile ise direk proje klasörümüze kopyalandı.
docker-compose.yml dosyası:
version: '3.4'
services:
node-server:
container_name: my-server
build: .
ports:
- 3001:3000
Dockerfile dosyası bazı işleri docker-compose.yml üzerine taşıdığımız için ve bazı klasörlerin yeri değiştiği için tekrar düzenlendi.
FROM node:16-slim
WORKDIR /opt/node-server
COPY app/ .
RUN npm install
CMD ["node", "app.js"]
Proje dizininde terminale
docker-compose builddiyerek build aldırılır.
Terminale
docker imagesyazdığımızda bizi
1-node-server-node-serveradında bir image karşılar. Burada ilk kısım klasörün adı (1-node-server) ikinci kısım da servisin adı (docker-compose.yml -> services: node-server: ...)
Proje dizininde terminale
docker-compose updiyerek çalıştırılır. Daha önce build alınmadıysa build alır ve sonra çalıştırır
5-node-mongo-todo projesindeki Dockerfile yeni projemizin kök dizinine, app.js, package.json package-lock.js ve TodoModel.js yeni ptojenin app klasörüne eklendi.
Dockerfile dosyası aşağıdaki gibi düzenlendi.
FROM node:16-slim
WORKDIR /opt/node-todo-app
COPY app/ .
RUN npm install
CMD ["node", "app.js"]
docker-compose.yml dosyası:
version: '3.4'
services:
todo-app:
container_name: dc-todo-app
build: .
ports:
- 3000:3000
mongodb:
image: mongo
ports:
- 27017:27017
volumes:
- todo-app-data:/data/db
volumes:
todo-app-data:
docker-compose ile volume eklerken container seviyesindeki volume name ana seviyede de belirtilmeli.
app/app.js içinde mondoDB bağlantısı için docker-compose.yml içindeki servis adı (mongodb) kullanılır.
app.listen(PORT, async () => {
...
await Mongoose.connect("mongodb://mongodb:27017/todos", {
...
});
...
});
Değişiklik yaptığımızda docker-compose up yapmadan önce docker-compose build ile build almak gerekir.
docker-compose downprojeyi durdurmanın en doğru yoludur. containerları tek tek kapatmak hataya neden olabilir.
Hocanın uygulamasını proje klasörümüze app klaaörü içine ekledik.
Proje klasöründe Dockerfile dosyası eklendi.
FROM node:16-slim
WORKDIR /uploader-app
COPY app/. .
RUN npm i
EXPOSE 3000
CMD [ "node", "server.js" ]
docker-compose.yml dosyası
version: "3.4"
services:
uploader-app:
build: .
ports:
- 3000:3000
volumes:
- uploader-app-uploads:/uploads
volumes:
uploader-app-uploads:
volume olarak dosyaların uygulamada yüklendiği "uploads" klasörünü gösterdik.
Bu seferki ürünü sadece docker-compose.yml ile oluşturduk. hub.docker.com -> wordpress dökümantasyonundan faydalandık.
version: '3.4'
services:
wordpress:
image: wordpress
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: bloguser
WORDPRESS_DB_PASSWORD: test123
WORDPRESS_DB_NAME: blogdb
volumes:
- wordpress:/var/www/html
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: blogdb
MYSQL_USER: bloguser
MYSQL_PASSWORD: test123
MYSQL_RANDOM_ROOT_PASSWORD: "1"
volumes:
- db:/var/lib/mysql
volumes:
wordpress:
db:
services: db: ile database oluşturuldu. db ismine dikkat. bunu diğer serviste WORDPRESS_DB_HOST: db olarak kullandık.
Bu projenin dosyalarını hoca paylaşmamış sadece docker-compose.yml üzerinde konuştuk.
version: '3,4'
services:
twitter-app:
build: .
ports:
- 3000:3000
depends_on:
- mongodb
- redis
mongodb:
image: mongo:latest
ports:
- 27017:27017
volumes:
- data:/data/db
redis:
image: redis
ports:
- 6379:6379
volumes:
data:
depends_on: altına verilen servisler o servisin çalışması için gerekenleri tanımlar. Önce onlar çalışır. Sonra içine yazıldığı container çalışır.
Hoca işlemleri digitalocean.com üzerinden host alıp yapıyor. Biz de onu takip edeceğiz.
Create>Droplets ile formu doldurup makineyi ayağa kaldırıyoruz.
Oluşturduğumuz makineye docker kurmak için docker.com/engine/install/ubuntu/ adresindeki yönergeleri izleyeceğiz.
terminale
ssh root@<host-id>sintaxı ile bağlanıyoruz. Bizimki
ssh root@165.232.122.105Gelen ekrana parolamızı yazıp giriş yapıyoruz.
Ubuntuya girdiğimizde terminale
sudo apt-get updateyazarak mevcut paketleri güncelliyoruz.
Sonra terminale
sudo apt-get install ca-certificates curl gnupgyazıyoruz.
apt install docker.ioile docker kuruldu.
apt install docker-composeile docker-compose kuruldu.
systemctl status dockerile docker'ın çalışma durumu kontrol edilir.
Uzak bilgisayara bağlandıktan sonra kök dizinde terminale
cd /tmp
mkdir
mkdir web-apps
cd web-apps
yazılarak tmp içine web-apps dosyası oluşturuldu ve içine girildi
vi docker-compose.ymlile bu klasörde docker-compose.yml klasörü oluşturuldu ve içine girildi. Bu aşamada klavyede
iye basıp düzenleme (insert) modu açıldı. Daha önce wordpress için kullandığımız docker-compose içeriği buraya aktarıldı (hoca direk yapıştırdı. Bende düzgün yapışmadığından elle tek tek yazdım.)
version: '3.4'
services:
wordpress:
image: wordpress
ports:
- 8080:80
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: bloguser
WORDPRESS_DB_PASSWORD: test123
WORDPRESS_DB_NAME: blogdb
volumes:
- wordpress:/var/www/html
db:
image: mysql:5.7
restart: always
environment:
MYSQL_DATABASE: blogdb
MYSQL_USER: bloguser
MYSQL_PASSWORD: test123
MYSQL_RANDOM_ROOT_PASSWORD: "1"
volumes:
- db:/var/lib/mysql
volumes:
wordpress:
db:
esc
ile insert modundan çıkıldı. :wq
ile dosya kaydedilip kapatıldı.
terminale
mkdir videomeet
mv docker-compose.yml videomeet/
yazarak önce videomeet adında bir klasör oluşturduk ve ardından docker-compose.yml dosyasını buraya taşıdık.
cd videomeet
cat docker-compose
yazarak önce bu klasöre girdik. Sonra da docker-compose.yml içeriğini terminalde görüntüledik.
docker-compose upile projemizi ayağa kaldırdık.
Projeye 165.232.122.105:8080 ile ulaşabiliriz.
projeyi kapatırken ctrl + C
yeterli olur ancak tüm bileşenlerin kapanması için
docker-compose downkomutu kullanılır.
Reverse proxy (ters yönlü proxy), bir ağdaki istemcilerin (genellikle internet kullanıcıları) bir hizmet sunucusuna erişirken, istemcilerin bu hizmet sunucusunu doğrudan değil de arada bir sunucu üzerinden erişmelerini sağlayan bir teknolojidir. Bu arada sunucuya "reverse proxy" denir çünkü geleneksel olarak çalışan "forward proxy"nin tersine, istemciden gelen istekleri bir sunucuya ileterek geriye doğru işlem yapar.
Biz reverse proxy ile aynı IP ile de bağlı olan iki domaini isteğin geldiği server_name
e göre farklı container içine göndereceğiz.
Nginx kurulumu için hocanın kullandığı kaynak
terminale
apt install nginxyazılarak ngnix yüklenir.
Terminale
unlink /etc/nginx/sites-enabled/defaultyazılarak Nginxin, Ubuntu'nun paket yöneticisi apt aracılığıyla yüklendiğinde önceden yapılandırılmış olan varsayılan sanal ana bilgisayarı devre dışı bırakılır.
cd /etc/nginx/sites-available
vi reverse-proxy.conf
ile ilgili klasöre gidip revers proxy için configuration dosyası oluşturduk. içine yazmak için klavyede iye bastık ve aşağıdakileri yazdık.
server {
listen 80;
listen [::]:80;
server_name videomeet.app;
server_name_in_redirect off;
access_log /var/log/nginx/reverse-access.log;
error_log /var/log/nginx/reverse-error.log;
location / {
proxy_set_header Client-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
}
}
escile insert mode dan çıktık
:wqile kaydedip çıktık.
terminale
ln -s /etc/nginx/sites-available/reverse-proxy.conf /etc/nginx/sites-enabled/reverse-proxy.confile yazdığımız dosya gerekli olan başka bir klasör ile bağlandı.
Terminale
nginx -tyazarak nginx test edilir.
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
çıktısı alıyorsa her şey yolunda demektir.
systemctl restart nginxile nginx restart edilir. ngnixin sistemde çalışmasını sorgulamak için terminale
systemctl status nginxyazılır.
Terminale
cd /tmp/web-apps/videomeetyazılarak projemizin olduğu dosyaya ulaştık.
docker-compose upile projeyi ayağa kaldırdık.
Burada bazı işlemler domain gerektiriyor. Bunu daha sonra tekrar deneriz. Bu kısımda domaine ve wordpress e host id girildi.
Proje dosyasını ssh üzerinden scp ile göndereceğiz.
Bunun için daha önce hocanın dosyalarından aldığımız ve göndereceğimiz 8-vue-app-docker-file
klasörünü .tar
formatında sıkıştırıyoruz. Sıkıştıracağımız klasörde terminale
tar -cvf asana-clone.tar *yazdık.
Dosyayı göndermek için dosyanın olduğu klasörde terminale
scp asana-clone.tar ssh root@165.232.122.105:/tmp/web-apps/yazdık
server tarafında
cd /tmp/web-appsile dosyayı gönderdiğimiz dizine girdik.
chmod 755 asana-clone.tarile dosya erişim iznini değiştirdik.
tar xf asana-clone.tarile dizinden çıkarttık.
mkdir asana-cloneyazarak yeni bir klasör oluşturduk.
mv app asana-clone/app
mv Dockerfile asana-clone/Dockerfile
ile .tar dan çıkartılanlar bu dosyaya taşındı. rm asana-clone.tarile sıkıştırılmış dosya silindi
cd asana-clone
docker build . -t asana-clone-app
ile build aldık ve docker run -p 8090:8080 -d asana-clone-appile uygulama up edildi.
http://165.232.122.105:8090/ ile uygulamaya ulaşılabilir.
cd /etc/nginx/sites-available/ile nginx ayarlarının olduğu klasörü açtık.
vi reverse-proxy.confile içine girdik. Klavyede
iye basarak insert modunu açtık ve dosyaya gerekli eklemeleri yaptık. Son hali:
server {
listen 80;
listen [::]:80;
server_name videomeet.app;
server_name_in_redirect off;
access_log /var/log/nginx/reverse-access.log;
error_log /var/log/nginx/reverse-error.log;
location / {
proxy_set_header Client-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8080;
}
}
server {
listen 80;
listen [::]:80;
server_name talkinghead.app;
server_name_in_redirect off;
access_log /var/log/nginx/reverse-access.log;
error_log /var/log/nginx/reverse-error.log;
location / {
proxy_set_header Client-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:8090;
}
}
escsonra da ":wq" ile kaydedilip kapatılır.
Her iki domain de aynı IP ile de bağlı olsa isteğin geldiği server_name
e göre yönlendirme değişmektedir.
systemctl restart nginxile nginx restart edilir. Böylece yeni ayarlar devreye alınmış olur.
Domain aldığımızda biz de bu durumu deneriz.
Tamamen teorik bir eğitim. Uygulama adına hiçbir şey yapmadık.
Containerlar üzerinde çalışan microservice tabanlı uygulamaların orkestrasyonu.
Pod nedir Docker için container ne ise K8S için de Pod odur. Podların içinde containerlar çalışır. K8S ölöekleme birimidir. 1 Pod birden fazla K8S nodu üzerine deploy edilemez.
Deployment nedir? REST objeleridir. YAML yada JSON dosyasında tanımlanabilirler. Bir kere hazırlanıp birden fazla deploy edilebilirler. Versiyonlanabilirler. Yaratımı api-server üzerinden olur.
Service nedir? K8S üzerinde bir network var. Podların trafiğini service yönetir. Sadece sağlıklı podlara yönlendirir. Load balancing görevini de yerine getirir.
Cloudda veya lokalde herhangi bir host üzerinden çalışabilir. Cluster'a gözkulak olur. Cluster üzerinde nelerin çalışacağına master karar verir. Workload ayarlamaları, yaşam döngüsü, ölçekleme ve upgrade işlemlerinden sorumludur.
kube-api-server kuberneteste birşey yaratmak ve kullanmak için faydalanacağımız, K8S in beyni. API(REST) üzerinden fonksiyonları expose eder. JSON yada YAML dosyaları vasıtasıyla fonksiyonları kullanabilir. 443 portu üzerinden çalışır (HTTPS). $kubectl komut satırı ile kullanılır.
cluster store Yönetimdeki tek stateful kısımdır. Kalıcı bir saklama alanıdır. Key/value store teknolojisini kullanır.
kube-controller-manager controllerları koordine eder. Her işlem için controller bulunabilir. Desired state (arzulanan hal) pozisyonunu kontrol eder. Arzulanan halden çıkılırsa geri dönmek için gerekeni yapan kısımdır.
kube-scheduler api-serverdan gelen yeni pod yaratma görevleri için bekler. Node'lara workload atamasından sorumludur.
Cluster'ın çalışan gücü. Fiziksel yada sanal makinede olabilirler. Node'u node yapan en önemli şey container runtime'dır.
kubelet node'u cluster'a register etmeye yarar. api-server dan gelen direktifleri bekler. Pod oluşturmada görev alır. Master ile sürekli iletişim halinde.
container engine container'ları yönetme işini halleder. Pluggable (kaldırılabilir, değiştirilebilir). Genelde Docker Container Engine kullanılır. Container'ları start-stop etmede görevlidir.
kube-proxy kubernetes network fonksiyonlarını sağlar. Node içinde her pod tek bir IP adresine sahiptir. Service içinde tanımlanan Pod'ların yük dengelemesini sağlıyor. Frontend ve backend podlar kube-proxy üzerinden haberleşir.
api-server node'lardaki loglara erişmek, port-front etmek ve portlara erişmek için kubelet'i kullanır. api-server'ın node'lar, pod'lar ve service'ler ile iletişimi şu an için secure (https) değil.
Kubernetes karmaşık mikroservice yapılarını organize eder. Herhangi bir microservice down olursa yeni bir cluster kubernetes tarafından ayağa kaldırılır.
Biz kubectl kullanarak K8S in beyni olan api-server ile konuşur. Manifest dosyamiz ve kubectl komutu ile api-server üzerinden işlem başlar.
Hocanın notları Node ve Master kurulumunda notlardan faydalandık ancak bu kısımda bu dökümantasyondan faydalandık. Hocanınki bizde çalışmadı. Gerçi bizim yaptığımız hali de eninde sonunda çöktü :D
Hoca kurulumu direk linux ortamında yapmış. Ben de digitalocean üzerinden 2 makine açıp orada deneyeceğim
Hem master hem de node makinede swap disable edilmeli.
swapoff -aBu olmazsa kubernetes ayağa kalkmıyor.
swap nedir? Swap (Takas) Alanı, işletim sistemi tarafından sabit diskinizde ayrılmış bir bölümdür. İşlenecek veriler ön belleğe (RAM) sığmadığı zaman bu bölüm “RAM” gibi kullanılır ve böylelikle veri akışının ve proseslerinin devam etmesi sağlanır.
Her iki makineyi de güncelle
sudo apt-get update
Her iki makineye google apt reposty ekle
curl -fsSL https://dl.k8s.io/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
Her iki makineye kubernetes apt repository ekle.
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
Her iki makineyi tekrar güncelle
sudo apt-get update
Repository deki versiyonları daha sonra incelemek için apt-cache ile cacheliyelim.
apt-cache policy kubelet|head -n 20
apt-cache policy docker.io|head -n 20
Gerekli paketleri repositoryden makinemize çekelim.
sudo apt-get install -y docker.io kubelet kubeadm kubectl
kubelet, container runtime'mımız olan docker statusleri kontrol edelim.
sudo systemctl status kubelet.service
sudo systemctl status docker.service
sistem ayağa kalktığında çalışacak şekilde ayarlayalım.
sudo systemctl enable kubelet.service
sudo systemctl enable docker.service
Pod network yaratmak icin calico yaml lari indirelim
wget https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/rbac-kdd.yaml
wget https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml
Calico yaml file daki ip bilgisine uygun olarak, bir pod network range i belirleyerek Kubernetes cluster imizi olusturalim
sudo kubeadm init --pod-network-cidr=192.168.0.0/16
API server a admin erisim yetkisine sahip bir hesap yaratalim
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Pod network olusturmak icin gerekli yaml dosyalarini calistiralim
kubectl apply -f rbac-kdd.yaml
kubectl apply -f calico.yaml
Sistem specific podlari ve calico podlarini inceleyelim
Not : DNS pod umuz network deploy olup calisir halene kadar aktif olmayacak
kubectl get pods --all-namespaces
Cluster da mevcut podlarin listesine bakalim - sadece master gorunecek
kubectl get nodes
kubelet static pod manifestleri calistiriyor yani bir anlamda core cluster podlari calisir hale geliyor
sudo systemctl status kubelet.service
kubeconfig dosyasinin bulundugu directory i inceleyelim
ls /etc/kubernetes
master daki manifestleri inceleyelim
ls /etc/kubernetes/manifests
api-server ve etcd nin manifestlerini incelemek istersek...
sudo more /etc/kubernetes/manifests/etcd.yaml
sudo more /etc/kubernetes/manifests/kube-apiserver.yaml
kubelet ve container runtime service lerini kontrol ederim
sudo systemctl status kubelet.service
sudo systemctl status docker.service
Sistem basladigi zaman baslayacak sekilde set edelim
sudo systemctl enable kubelet.service
sudo systemctl enable docker.service
Master'da token bilgisi verilmisti eger not almadiysak su sekilde listeleyebiliriz
kubeadm token list
Yeniden bir token generate etmek istiyorsak
kubeadm token create
Master uzerinde ca cert hash bulunmakta. Onu elde etmek için:
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
Yukarıdaki kodlarla elde ettiğimiz token imiz ve cert ile Api Server in IP adresi ya da adını kullanarak Node'umuzu cluster a dahil edelim.
sudo kubeadm join <ip>:6443 --token<token> --discovery-token-ca-cert-hash <ca_cert_hash>
bizim durumumuzda aşağıdaki kod node'a yazılır.
kubeadm join 174.138.60.6:6443 --token nyndhw.xynrxsohej6fw400 \
--discovery-token-ca-cert-hash sha256:ccb7f01df76693e522c9ba719adb9817d8c28f0ab1cf18148fd21022ee04a74d
Kuberneteste Ptrafik yönetimi: Podlar tüm cruster içinde erişebilir olur. Service üzerinden Podları erişebilir hale getirir. kube-dns servislere otomatik DNS name atar.
NodePort nedir? Dış dünyadan gelen trafiği Cluster'imizin içine kabul etmenin temel yolu. Tüm nodelar üzerinde bir portu erişime açar (default range of 30000-32767). Cluster dışından <NodeIp>:<NodePort> şeklinde erişilebilir. Gelen istekler ilişkilendirilen Service'e yönlendirilir.
ClusterIp nedir? Service'e cluster genelinde geçerli bir IP verme yöntemi. Default olarak dış dünyaya erişime açmaz ama proxy vasıtasıyla dışarıdan erişim sağlanır.
LoadBalancer nedir? Kuberneteste service'i dış dünyaya expose etmek için standart yöntem. Service'lerin yük dağılımı NodePort üzerinden Service'e yönlendirme ile sağlanır. Yaratılan LoadBalancer tipindeki Service'lerin de bir IP si olur. İstek NodeBalancer üzerinden NodePort'a oradan podlara geçer.
Ingress aslında bir service değil bir object. Reverse proxy işi yapar. Service'ler arası yük dağıtan bir router gibi davranır. Çalışması için cluster'da bir Ingress Controllerîn bulunması gerekir.
Cluster üzerinde her Node üzerinde belirlediğimiz bir Pod'u çalıştırmanın yolu. İstenilen şartta bir Node oluştuğu anda set edilen işlemi gerçekleştirir (İçinde default olarak gelmesi istenen bir pod vs gibi). Spesifik işler yapmak için spesifik Node'lara deploy olabilirler.
DeamonSetlere ulaşmak için: DeamonSet'i yaratırken port bilgisi verilip, NodeIp-Port bilgisiyle veya DeamonSet podları bir Service objesine bind edilip service üzerinden ulaşılabilirler.
DeamonSetler genelde dışarı data push etmek için kullanılır (Loglama vs).
Imperative yöntem özel komutlar vasıtasıyla süreci yönetmek.
Declarative yöntem yapılacak işi bir veya birden fazla script içerisinde tanımlayıp çalıştırmak
Imperative bizim tek tek elle yaptığımız işlemlerken, declarative ise manifest dosyaları gibi önceden hazırlanmış dosyalarla yaptığımız kalıptan yapılan işlemlerdir.
Probe kubernetesin Pod'un durumunu öğrenmek için yaptığı işlem. Periyodik olarak cluster'da yapılan diagnostic operasyondur.
Clusterda olan bitenden haberdar olmak (monitmr etme, debug etme) için kullanılır.
Kubernetes api üzerinden loglara erişilir.
Node level ve cluster level olarak iki ayrı log seviyesi vardır. Node level loglarını default olarak tutar. Cluster level için K8S te bir log kayıt mekanizması yok. Biz ekliyoruz.
Kubernetesin var olma sebebi. Sistemde çalışan uygulamaların, mikroservislerin ve containerların çoklanması işlemidir. Kubernetese verdiğimiz desired state'e göre kill olanların yerini yeniler alarak bizim istediğimiz yapının kalıcılığı sağlanır.
Kubectl kubernetes command-line aracı. Cruster'ı yönetmeye (deployment yapmak, uygulamaları incelemek ve loglara erişmek) yarar. ~/.kube/config dosyasının içindeki bilgilere göre çalışır.
kubectl komutu syntax:
kubectl [command] [type] [name] [flags]Örnek:
kubectl get pods
kubectl get service my-service
kubectl create deployment nginx --image=nginx
Hoca heroku anlatacak ancak biz heroku artık ücretli olduğundan deta.space üzerinden takip etmeye çalışacağız.
diğer alternatifler: Render, Netlify, Cyclic
Proje ekranında terminale
npm init yile package.json oluşturuldu ve npm başlatıldı.
npm install --save express body-parserile gereken bağımlılıklar yüklendi
npm install --save-dev nodemonile nodemon kuruldu.
db.json dosyası oluşturuldu ve içine hocanın verdiği data eklendi.
app.js oluşturuldu son hali aşağıda.
const app = require("express")();
const db = require("./db.json");
const bodyParser = require("body-parser");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/users", (req, res) => {
res.status(200).send(db);
});
app.get("/users/:id", (req, res) => {
if (isNaN(req.params.id)) {
res.status(400).send({
message: "İşlenemeyen veri",
});
} else {
const user = db.find((user) => user.id == req.params.id);
if (user) {
res.status(200).send(user);
} else {
res.status(400).send({
message: "Kullanıcı bulunamadı",
});
}
}
});
app.post("/users", (req, res) => {
const willSaveData = {
id: new Date().getTime(),
full_name: req.body.full_name,
country: req.body.country,
email: req.body.email,
created_at: new Date(),
};
db.push(willSaveData);
res.send(willSaveData);
});
app.patch("/users/:id", (req, res) => {
if (isNaN(req.params.id)) {
res.status(400).send({
message: "İşlenemeyen veri",
});
} else {
const user = db.find((user) => user.id == req.params.id);
if (user) {
// Kayıt değişikliği
// pass by referance ve pass by value araştırılacak.
Object.keys(req.body).forEach((key) => {
user[key] = req.body[key];
});
res.status(200).send(user);
} else {
res.status(400).send({
message: "Kullanıcı bulunamadı",
});
}
}
});
app.delete("/users/:id", (req, res) => {
if (isNaN(req.params.id)) {
res.send(400, {
message: "İşlenemeyen veri",
});
} else {
const userIndex = db.findIndex((user) => user.id == req.params.id);
if (userIndex > -1) {
//silme işlemi
db.splice(userIndex, 1);
res.status(201).send({
message: "Kullanıcı Silindi",
});
} else {
res.status(400).send({
message: "Kullanıcı bulunamadı",
});
}
}
});
app.listen(process.env.PORT || 3000, () => {
console.log("Sunucu ayaktadır... Çalışıyor...");
});
nodemonun bizim her değişikliğimizde kodumuzu tekrar çalıştırması için package.json içine
"scripts": {
"start": "nodemon app.js"
},
eklendi ve terminale npm startyazılarak proje ayağa kaldırıldı.
Heroku ücretli olduğundan alternatif arayışındayız. deta.space terminal kullanımı ve tamamen ücretsiz olması nedeni ile ilgimizi çekti. Burayı deneyeceğiz.
diğer alternatifler: Render, Netlify, Cyclic
Terminale
iwr https://deta.space/assets/space-cli.ps1 -useb | iexyazarak bilgisayarımıza kurduk.
space loginile uygulamayı açtık. Bizden istediği access token için deta.space sayfasında en alttaki form yardımıyla setting>access token ürettik ve terminale girdik. Ve login olduk.
Proje dizininde terminale
space newyazılarak proje deta.space üzerinde pluşturulur.
Dockerdakine benzer bir şekilde projemiz için Spacefile adında bir manifest oluşturduk.
v: 0
micros:
- name: node-rest-api
src: ./
engine: nodejs16
primary: true
run: node app.js
dev: npm start
public: true
Terminale
space pushyazarak projeyi deploy ettik.