Python Web Sitesini Docker ile Dağıtma

Docker nedir, ne değildir? Gökhan Şengün'ün tüm detaylarıyla anlatılan çok güzel bir blog yazı serisi var. Buradan inceleyebilirsiniz.
Bu yazıda kendi python uygulamamızı nasıl docker image haline getiririz ve başka bir makinede kullanmak üzere docker hub'a nasıl yükleriz sorularının cevaplarını adım adım göreceğiz.

Python Web Sitenizi Oluşturun

Her zamanki gibi python web uygulaması için Flask framework'ünden yararlanacağız.

Dosya oluşturun

İlk önce komut satırından uygulamanız için yeni bir dizin oluşturun, sonra dizine geçin:

mkdir my_test_flaskapp
cd my_test_flaskapp

Ardından iki dosya oluşturun: main.py ve requirements.txt

Python Kodu Ekleyin

En sevdiğiniz düzenleyicide main.py dosyasını açın ve aşağıdaki kodu yapıştırın:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def main():
    return "Hello Docker Image Web App!"

if __name__ == "__main__":
    app.run(host='0.0.0.0')

Bu, basit bir merhaba dünya mesajı görüntüleyen basit bir web uygulaması oluşturur. Flask ile web uygulaması geliştirme ile ilgili daha detaylı bilgi için resmi sitesini inceleyebilirsiniz.

NOT: app.run (), 0.0.0.0 değerinde host denilen bir argüman alır. Docker ile çalışmak için bu önemlidir. Bu stackoverflow yanıtında bu konuda daha fazla bilgi edinebilirsiniz.

Gereksinimlerinizi ekleyin

requirements.txt dosyasını açın ve aşağıdakileri ekleyin:

Flask

Bu, Flask Kütüphanesini kurmak için pip tarafından kullanılacaktır.

Sitenizi çalıştırın

Son olarak, aşağıdakileri bir komut satırında çalıştırarak sitenizin çalıştığından emin olabilirsiniz:

pip3 install -r requirements.txt
python3 main.py

Web tarayıcınızdan localhost:5000'e giderseniz, yeni web sitenizi görürsünüz. Şuanda basit bir Flask uygulamasını oluşturmuş oldunuz.

Docker dosyası ekleyin

Uygulamanızı Docker kullanarak dağıtmaya hazır hale getirmenin ilk adımı bir Dockerfile eklemektir.

Python Uygulamanızın kök dizininde Dockerfile adlı bir dosya oluşturun ve aşağıdakileri ekleyin:

FROM python:alpine

LABEL Name=my_test_flaskapp Version=0.0.1
EXPOSE 5000

WORKDIR /app
ADD . /app

# Using pip:
RUN python3 -m pip install -r requirements.txt
CMD ["python3", "/app/main.py"]

Bu Dockerfile, resmi Python alpine image'ını kullanır. Docker dosyası daha sonra bir klasör kodu oluşturur ve tüm dosyaları geçerli dizinden docker image'ına kopyalar. Daha sonra, gereksinimler dosyasındaki tüm kütüphane bağımlılıklarını yükleyen pip çalıştırır (bu örnekte sadece Flask). Bağlantı noktasını açar ve sonunda web sitesini başlatan komutu çalıştırır.

Yukarıdaki Dockerfile, 5000 portunu erişimi açar ve flask uygulamamızı başlatan python /app/main.py komutunu çağırır.

Docker İmajınızı oluşturun

Uygulamanızı dağıtıma hazır hale getirmek için, Dockerfile oluşturmanızdan docker image'ınızı build işlemini gerçekleştirmeniz gerekir. Dockerfile oluşturduğunuz klasördeki komut isteminden aşağıdakini çalıştırın:

docker build -f Dockerfile -t testflaskapp:latest .

Bu build işlemi, Python alpine image'ı eğer local'de değilse indirir ve Dockerfile'ınızdaki işlemleri gerçekleştirir (dosya oluşturma / pip install / vs.) ve yeni docker image'ını testflaskapp olarak etiketler.

Yeni docker image'ını gerçekten çalıştırmak ve test etmek için, yeni oluşturulan image'ı docker kullanarak çalıştırın.

docker run -p 5000:5000 --rm testflaskapp

Aşağıdakine benzer şekilde çıktı almalısınız.

Şimdi localhost: 5000'e gidebilirsiniz ve Flask Uygulamanızın bir docker container içinde çalıştığını görmelisiniz.

Docker Image'ınızı Yayınlayın

Docker Hub'da yayınlamak için bir hesap oluşturun.

Docker image'ı yayınlamadan önce, "docker images" komutunu çalıştırarak ve testflaskapp container'ının image id'sini bulun:

Daha sonra, mevcut docker image'ı Docker Hub kullanıcı adınız ve image id'niz ile etiketleyin.
Not: Aşağıdaki komutta kendi image id ve docker hub kullanıcı adınız ile değiştirin.

docker tag 4ff3582fc461 yavuzkomecoglu/testflaskapp

Şimdi docker image'ınızı etiketlediğinize göre Docker Hub'da oturum açmanız ve resmi docker hub'a push işlemini gerçekleştirmeniz gerekir:

docker login #follow prompts for login
docker push yavuzkomecoglu/testflaskapp

Ve artık docker image'ı docker hub deponuzda görmelisiniz:

 

Uzak Depodaki Image’ı Çekip Çalıştırın

Şu andan itibaren "docker run" komutunu kullanabilir ve bu komut ile beraber uygulamanızı istediğiniz makinede çalıştırabilirsiniz:

docker run -p 5000:5000 yavuzkomecoglu/testflaskapp

Eğer image lokalinizdeki makinede mevcut değilse, Docker bunu depodan indirerek çalıştırır.

 

Apache Web Sunucusunda Python Flask Web Uygulaması Nasıl Çalıştırılır

Merhaba,
Daha önce "Derin Öğrenme Modellerini Kullanan Bir Web Uygulamasının Geliştirilmesi" yazımda Python Flask web uygulamasının oluşturulmasını anlatmıştım.

Bu yazıda, Python Flask web uygulamasını Apache Web sunucusunda nasıl çalıştıracağımızı göreceğiz.

mod_wsgi'yi Yükle ve Etkinleştir

WSGI (Web Server Gateway Interface / Web Sunucu Ağ Geçidi Arayüzü), web sunucuları ile python için web uygulamaları arasında bir arabirimdir.

mod_wsgi, Apache'nin Flask uygulamalarına hizmet etmesini sağlayan bir Apache HTTP sunucu modülüdür.

mod_wsgi'yi yüklemek için aşağıdaki komutu kullanmamız gerekiyor:

$ sudo apt-get install libapache2-mod-wsgi python-dev

mod_wsgi'yi etkinleştirmek için aşağıdaki komutu kullanabiliriz:

$ sudo a2enmod wsgi

Dosyalar

Şimdi Flask ortamımızı kurmaya hazırız.

cd /var/www/

Flask ortam dizinimizi oluşturalım.

mkdir FlaskApp

Yeni oluşturduğumuz dizine gidelim.

cd FlaskApp

Şimdi asıl uygulama dizinini oluşturalım.

mkdir helloworldapp

Şimdi yeni oluşturduğumuz uygulama dizinimizin içerisine gidelim.

cd helloworldapp/

Uygulama klasörü altına static dosyalar ve html sayfalar için iki klasör daha oluşturalım.

mkdir static

mkdir templates

Örnek bir uygulama için Flask Uygulamasının ana dosyasını oluşturalım.

nano __init__.py
__init__.py dosyasını aşağıdaki şekilde oluşturalım.
#! /bin/usr/python

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Flask Uygulamasina Hosgeldiniz!"

if __name__ == "__main__":
    app.run()

Virtualenv

VirtualEnv, projelerinizde gerekli olan paketleri sistemden ba��ımsız bir şekilde kurup, kullanmanızı sağlayacak sanal ortam sağlar.

virtualenv'i kuralım ve aktif edelim.

$ sudo virtualenv venv 
$ source venv/bin/activate 
(venv)$ 

Flask Kurulumu

Install Flask:

(venv)$ sudo pip install Flask

Sunucu Çalıştır

Uygulamamızı çalıştırıp herşeyin yolunda gittiğinden emin olalım

(venv)$ sudo python __init__.py 

Tarayıcımızdan localhost:5000/ adresine girdiğimizde "Flask Uygulamasina Hoşgeldiniz" yazısını göreceğiz.

Apache kurulumu - WSGI

Şimdi, WSGI üzerinden Apache'yi kullanarak sayfayı sunmak istiyoruz.

Apache yapılandırma dosyasını düzenleyelim.

nano /etc/apache2/sites-available/flaskhelloworldsite.com.conf
<VirtualHost *:80>
    ServerName www.flaskhelloworldsite.com
    ServerAdmin webmaster@flaskhelloworldsite.com
    ServerAlias flaskhelloworldsite.com

    WSGIDaemonProcess helloworldapp user=www-data group=www-data threads=5
    WSGIProcessGroup helloworldapp
    WSGIScriptAlias / /var/www/FlaskApp/helloworldapp/helloworldapp.wsgi
    Alias /static /var/www/FlaskApp/helloworldapp/static
    <Directory /var/www/FlaskApp/helloworldapp/static>
        Order allow,deny
        Allow from all
    </Directory>
    ErrorLog /var/www/flaskhelloworldsite.com/logs/error.log
    CustomLog /var/www/flaskhelloworldsite.com/logs/access.log combined
</VirtualHost>



Suncuyu etkinleştirelim.

$ sudo a2ensite flaskhelloworldsite.com.conf
$ service apache2 reload

WSGI dosyasını düzenleyelim

nano /var/www/FlaskApp/helloworldapp/helloworldapp.wsgi
#!/usr/bin/python 
import sys 
sys.path.insert(0,"/var/www/FlaskApp/")
from helloworldapp import app as application


/etc/hosts dosyasını düzenleyelim

sudo nano /etc/hosts

Aşağıdaki satırı /etc/hosts dosyasına ekleyelim:

127.0.0.1 flaskhelloworldsite.com

Ayrıca, /var/www/flaskhelloworldsite.com/logs dizinini de oluşturmamız gerekiyor:

$ sudo mkdir -p /var/www/flaskhelloworldsite.com/logs

Yetkilendirmesini yapalım

$ sudo chown -R www-data:www-data flaskhelloworldsite.com

Apache Server'ı yeniden başlatalım

$ sudo /etc/init.d/apache2 reload

Artık tarayıcımızdan alan adını flaskhelloworldsite.com adresini kontrol edebiliriz.

Not: Web uygulamanıza yaptığınız her bir .py dosyası değişikliği, service apache2 restart bu komutu çalıştırmanız gerekir.

Kaynaklar:

 

Yapay Zeka Konferansı (DeepCon'18) 5-6 Ekim’de Ankara’da

5-6 Ekim tarihlerinde Türkiye'nin en büyük yapay zeka topluluğu Deep Learning Türkiye tarafından, Bilgi Teknolojileri ve İletişim Kurumu (BTK) ve HAVELSAN iş birliğinde bu yıl ilki düzenlenecek olan DeepCon'18 Yapay Zeka Konferansı ile bu alanda çalışmakta olan akademi, özel sektör ve kamu aktörlerinin bir araya getirilmesi, yenilikçi ve ilgi çekici fikirlerin ortaya koyulması hedeflenmektedir.

Bilgi Teknolojileri ve İletişim Kurumu’nun ev sahipliği yaptığı DeepCon’18 etkinliğinin ilk gününde, alanında uzman isimlerin panel oturumlarına ve sunumlarına, ikinci gününde ise uygulamalı atölye çalışmalarına yer verilecektir.

Etkinlikte, finanstan savunmaya, sağlıktan bankacılığa kadar farklı pek çok sektörde yapay zekanın son teknolojideki gelişmeleri detaylıca incelenecek ve tartışılacaktır.

Etkinlik herkese açık ve ücretsizdir.

Konferans programı ve detaylı bilgi için http://deepcon.deeplearningturkiye.com/

Sponsorluk: deepcon2018@gmail.com

Derin Öğrenme Modellerini Kullanan Bir Web Uygulamasının Geliştirilmesi

Merhaba,
Bu yazımızda Keras ile eğitilen bir derin öğrenme modelini kullanmak ve test etmek için bir web uygulamasını nasıl geliştirip ücretsiz olarak host edebiliriz birlikte görelim.

Python Flask ile Web Uygulaması

Flask, Python tabanlı web uygulamaları geliştirebileceğiniz mikroçatı(microframework)’dır.

Öncelikle Flask'ı yükleyelim.

pip3 install Flask

Yeni bir app.py python dosyası oluşturalım ve aşağıdaki python kodlarını yazalım.

from flask import Flask

app = Flask(__name__)

@app.route("/")
def main():
    return "Merhaba Flask ;)"

if __name__ == "__main__":
    app.run()

 @app.route("/") ile  localhost:5000/ adresine istek gönderildiğinde ve def main(): fonksiyonu ile dönecek içerik için çağrılacak fonksiyon tanımlanıyor.

Terminalden oluşturduğumuz app.py kodumuzu çalıştıralım

python app.py

Terminalde Running on http://127.0.0.1:5000/ çıktısını gördüğümüzde tarayıcımızdan http://localhost:5000/ adresine gittiğimizde main() fonksiyonunda döndüğümüz string değerini göreceğiz.

Flask ile HTML Template Kullanma

Yeni bir templates klasörü açalım ve templates klasörü içerisine bir index.html dosyası oluşturalım ve aşağıdaki html kodlarını yazalım.

<!doctype html>
<html lang="en">
<head>
  <!-- Required meta tags -->
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
  <title>Merhaba Flask! Html demosu.</title>
</head>
<body>
  <div class="container">
    <div class="py-5 text-center">
      <h1>Merhaba Flask! Html demosu.</h1>

      <button type="submit" class="btn btn-primary">TEST</button>
    </div>
  </div>
  <!-- Optional JavaScript -->
  <!-- jQuery first, then Popper.js, then Bootstrap JS -->
  <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>
</html>

 

app.py python dosyamızda render_template paketini import edelim ve main() fonksiyonunu, yeni oluşturduğumuz index.html'i çağırması için aşağıdaki şekilde yeniden düzenliyoruz.

Terminalden yeniden app.py'yi çalıştırdığımızda aşağıdaki gibi html sayfasını göreceğiz.

 

Python Flask ile basit bir web uygulamasınu bu şekilde geliştirebilirsiniz.

Derin Öğrenme Web Uygulaması Geliştirme

Şimdi web uygulamamızı geliştirerek derin öğrenme modelini nasıl çalıştırabileceğimize bakalım.

Gerekli Keras paketlerini, resim sınıflandırma için kullanacağımız ağımız olan ResNet50 paketini ve ön işlemler için gerekli diğer paketleri ekleyelim.

from keras.applications import ResNet50
from keras.preprocessing.image import img_to_array
from keras.applications import imagenet_utils
from PIL import Image
import numpy as np
from flask import Flask, render_template, request, jsonify, send_from_directory
import io
import werkzeug
import datetime
import os

Resim sınıflandırma için ImageNet veriseti ile eğitilmiş modelimizi ve ağırlık dosyalarını yükleyelim.

model = ResNet50(weights="imagenet")

Form post metodu ile gönderilen resim dosyasını modelin uygun giriş formata getiren bazı ön işlemler uygulandıktan sonra modele gönderilip tahmin (prediction) sonucunun alındığı ve json formatında geri döndürdüğümüz predict() fonksiyonunu aşağıdaki gibi tanımlayalım.

@app.route("/predict", methods=["POST"])
def predict():
	# initialize the data dictionary that will be returned from the
	# view
	data = {"success": False}

	# ensure an image was properly uploaded to our endpoint
	if request.method == "POST" and request.files['image']:
		imagefile = request.files["image"].read()
		image = Image.open(io.BytesIO(imagefile))


		# preprocess the image and prepare it for classification
		image = prepare_image(image, target=(224, 224))

		# classify the input image and then initialize the list
		# of predictions to return to the client
		preds = model.predict(image)
		results = imagenet_utils.decode_predictions(preds)
		data["predictions"] = []

		# loop over the results and add them to the list of
		# returned predictions
		for (imagenetID, label, prob) in results[0]:
			r = {"label": label, "probability": float(prob)}
			data["predictions"].append(r)

		# indicate that the request was a success
		data["success"] = True

		print(data)

	# return the data dictionary as a JSON response
	return jsonify(data)

 

Son olarak geriye kalan bu servisi başlatmak.

if __name__ == "__main__":
	print("START FLASK")

	port = int(os.environ.get('PORT', 5000))
	app.run(host='0.0.0.0', port=port)

 

Uygulamamızın bu hali ile bir REST API olarak kullanabilir durumdayız.

Terminalden uygulamamızı çalıştırdıktan sonra başka bir terminalden http://0.0.0.0:5000/predict adresine örnek bir resmimizi curl ile post ediyoruz.
Örnek olarak amerikan papağını resmini sınıflandırmaya çalışalım:

Aşağıdaki gibi göndermiş olduğumuz resim modelde sınıflandırarak json sonucunu bize dönüyor.
Sonuçlar arasında en yüksek oranla %99 macaw olarak sınıflandırma yaptığını görüyoruz.


Şimdi ise yazmış olduğumuz API'yi kullanarak web arayüzünden bir resim dosyayı seçerek sınıflandırmayı gerçekleştirelim.

Bunun için index.html sayfamıza kullanıcının resim yükleyebilmesi için bir form ve dosya yükleme elementleri ekleyelim.

				<form id="upload-file" method="post" enctype="multipart/form-data">
					<div class="form-group">
						<label for="InputFile">Resim Dosyası:</label>
						<input name="image" type="file" class="form-control-file" id="InputFile" aria-describedby="fileHelp">
						<small id="fileHelp" class="form-text text-muted">Tanımak istediğiniz resmi bilgisayarınızdan seçiniz</small>
					</div>

					<button id="upload-file-btn" type="button" class="btn btn-primary">Gönder</button>
				</form>

 

Kullanıcı dosya yükleme elementi ile resim dosyasını seçtikten sonra 'Gönder' buttonuna tıklandığında, jquery ajax ile seçilen dosyayı app.py python kodunda tanımladığımız predict() fonksiyonunu çağıran REST API'mize POST isteği gönderelim.

		$('#upload-file-btn').click(function () {
			$('.loader').show();
			$("#results").html('');

			var form_data = new FormData($('#upload-file')[0]);
			$.ajax({
				type: 'POST',
				url: '/predict',
				data: form_data,
				contentType: false,
				cache: false,
				processData: false,
				async: false,
				success: function (data) {
					console.log(data.success);

					$('.loader').hide();

					$.each(data.predictions, function (i, item) {
						console.log(item);
						label = item["label"];
						prob = item["probability"].toFixed(2);
						percent = prob * 100;

						$("#results").append('<label>' + percent + '% ' + label + '</label><div class="progress"><div class="progress-bar" role="progressbar" aria-valuenow="' + percent + '" aria-valuemin="0" aria-valuemax="100" style="width:' + percent + '%"></div></div>');
					});
				},
			});
		});

 

Uygulamanın tüm kaynak kodlarına buradan ulaşabilirsiniz.
Kaynak kodları Keras kütüphanesi yüklü bir bilgisayara indirerek çalıştırabilir veya online şekilde yayınlamak isterseniz yazıyı okumaya devam edebilirsiniz.

Web Uygulamasını Heroku Üzerinde Yayınlama

Heroku, birçok dil desteği olan, uygulama alt yapısı sağlayan bir bulut platformudur.

Heroku’ya uygun düzenlemeleri yapmak ve kendiniz heroku uygulaması oluşturmak isterseniz gerekli adımları Sıddık Açıl’ın aşağıdaki buradaki yazısına göz atabilirsiniz.

Veya herhangi bir işlem yapmadan Heroku üzerinden bir hesap oluşturarak bu uygulamaya özel olarak hazırladığım aşağıdaki button ile tek tıkla kendi heroku hesabınız altında hızlıca yayına alabilirsiniz.

Görüşlerinizi aşağıdaki yorum bölümüne yazabilirsiniz.
Sorularınızı Türkiye’nin yapay zeka alanındaki tek soru&cevap platformu olan Deep Learning Türkiye’nin Soru&Cevap Sitesi’nde sorabilirsiniz.

Kaynaklar: