"Enter"a basıp içeriğe geçin

Flask Uygulamalarını Ubuntu Server Üzerinde Yayınlama

Python ile web tabanlı uygulamalar geliştirmek her ne kadar bir çok yönden avantajlı olasa da kendi içerisinde bazı dezavantajlarıda mevcut. Bu dezavantajlardan biriyse, geliştirilen uygulamanın yayına alınmasının PHP gibi betik dillerine nazaran daha fazla efor sarfettirmesidir.

Bu, Python’ın çok yönlü bir dil olmasından kaynaklı bir durum. Çünkü Python ile sadece web tabanlı uygulamalar geliştirilmiyor, bir çok şey yapılabiliyor. Dolayısıyla uygulamayı yayınlamadan önce sunucumuzu Python için özel olarak yapılandırmamız gerekiyor yada Python destekli paylaşımlı bir hosting edinmemiz gerekiyor. Pratikte Python ile geliştirilmiş bir web uygulamasını yayına almak (deploy işlemi) için 3 yol mevcut.

  1. Python destekli, paylaşımlı bir hosting üzerinde yayınlamak. (İlgili Blog Yazısı İçin Tıklayın)
  2. Dockerize edip bir sunucu üzerinde yayınlamak.
  3. Sunucuyu, web uygulamamız için özel olarak yapılandırıp yayınlamak.

İlk yöntem en kolay yöntem olsada, uygulamanızın eğer bazı bağımlılıkları varsa (redis, celery vs gibi) ve hosting firmanız bunu sağlamıyorsa işinize yaramayacaktır.

Dockerize yöntemi en kolay ve stabil yöntem olsada Docker ile uğraşmak istemediğiniz yada yetersiz kaynağa sahip sunucularda yine işinize yaramayacaktır.

Bu yüzden biz, bu yazıda 3. yöntemi inceleyeceğiz ve Ubuntu bir sunucu üzerinde nasıl yayına alacağımızı göreceğiz. Sunucuyu bir kez yapılandırdıktan sonra yeni uygulamaları yayınlamak oldukça kolay hale gelecektir.

Diğer 2 yöntem içinse fırsat buldukça yazılar hazırlayacağım. Haydi başlayalım.

Gereksinimler

Bir web uygulaması yayınlamak için çeşitli servislere ihtiyaç var ve bu servislerin yönetimi çeşitli uygulamalar yardımı ile yapılabilir. Bu servisler, açıklamaları ve bu servisleri kontrol edecek uygulamalar aşağıdaki tablodaki listelenmiştir.

ServisAçıklamaUygulama
Web UygulamasıYayına alınacak Flask uygulamasıConfidant
WSGI ServisiUygulamamızı yayınlayacak servisGunicorn
Process Control ServisiUygulamamızı yönetecek ve loglayacak servisSupervisor
HTTP ServerProxy işlemlerini yönetecek ve statik dosyaları yayınlayacak servisNginx
FirewallSunucu güvenlik duvarı ve port kontrol işlemlerini yapacak servis (isteğe bağlı)UFW
Sanal (İzole) OrtamProje paketlerinin, sistem ve diğer projelerin paketleri ile çakışmamasını sağlayacak servis (isteğe bağlı)Virtualenv
Versiyon Kontrol SistemiProjenin sürüm kontrol işlemlerini yönetecek servis (isteğe bağlı)Git

Bu yazıda örnek olması için bir günlük olan Confidant uygulamasını kullanacağım. İsterseniz tabloda önerdiğim uygulamaları, kendi taleplerinize göre alternatif uygulamalar ile değiştirebilirsiniz.

Kurulum

İlk işlemler

Kuruluma başlamadan önce bir Ubuntu sunucu kiralamamız gerekmekte. Sunucuyu kiraladıktan sonra bize verilen erişim bilgileri ile sunucumuza erişiyoruz ve sunucumuzu güncelliyoruz.

~$ sudo apt-get update && apt-get upgrade

Güncelleme işlemi biraz uzun sürebilir. Tamamlandıktan sonra sunucuya gerekli uygulamaları kurmaya başlayabiliriz.

Not: Devam etmeden önce, root olarak sunucuda işlem yapmak oldukça tehlikeli olacağından yeni bir kullanıcı hesabı oluşturulması önerilir. Oluşturulan kullanıcı ile sisteme tekrar giriş yaparak işlemlere devam edebilirsiniz.

Şimdi sunucumuza Python, Git, PIP, Virtualenv gibi çeşitli programları kurmamız gerekiyor.

~$ cd ~
~$ sudo apt install python3 python3-pip git
~$ pip3 install virtualenv

İlk satırda ana dizinde olmama ihtimaline karşı kullanıcının ana dizinine geçiyoruz. İkinci adımda Python3, PIP ve Git kurulumlarını yapıyoruz. Son adımda ise projemiz için kullanılan python paketlerinin izole olması için virtualenv kurulumunu gerçekleştiriyoruz.

Uygulama Kurulumu

Artık Flask uygulamamızı kurabiliriz. Kullanıcının ana dizininde iken git ile projeyi klonluyoruz ve uygulama dizinine geçiyoruz. Eğer isterseniz sunucunuza FTP kurulumu yaparak, FTP kullanarak dosyalarınızı yükleyebilirsiniz.

~$ git clone https://github.com/emregeldegul/confidant && cd confidant

Daha sonra uygulamamızı sistemden izole bir şekilde çalıştırabilmek için virtualenv ile sanal ortam kurulumu yapıyorum ve sanal ortamı aktif hale getiriyorum.

~$ python3 -m virtualenv venv && source venv/bin/active

Bu komut sonrası eğer bir terslik olmadıysa sanal ortam aktif olacaktır. Yani bu projeye yükleyeceğiniz bütün paketler bu proje özelinde çalışacaktır. Eğer sanal ortam aktifse terminal aşağıdaki görünüme kavuşacaktır.

(venv) ~$

Şimdi, uygulamamız için gerekli bütün paketleri requirements.txt dosyasından yükleyebilirsiniz.

(venv) ~$ pip install -r requirements.txt

WSGI servisinin (gunicorn) requirements.txt dosyası içerisinde tanımlandığına dikkat edin. Böylece WSGI servisini de kurmuş olduk.

Uygulama migration dosyalarıda içerdiğinden migration işleminide yapıyoruz (sizin uygulamanızda yoksa, geçebilirsiniz).

(venv) ~$ flask db upgrade

Güvenlik Duvarı ve Port Yönetimi

Uygulamamız henüz çalışır vaziyette değil. Öncelikle güvenlik duvarı kurulumunu yapacağız, yapmak istemiyorsanız bu adımı geçebilirsiniz.

Güvenlik duvarı olarak UFW kullanacağız. Oldukça basit olan bu uygulamayı kurmak ve ilk ayarları yapmak için sırasıyla aşağıdaki komutları verebilirsiniz.

~$ sudo apt install ufw
~$ sudo ufw default allow outgoing
~$ sudo ufw default deny incoming
~$ sudo ufw allow ssh
~$ sudo ufw allow 5000
~$ sudo ufw enabled
  1. Satır: UFW programını kurduk.
  2. Satır: Varsayılan olarak sunucudan dışarı çıkan bütün isteklere onay verdik.
  3. Satır: Varsayılan olarak sunucuya dışarıdan gelen bütün istekleri reddettik (portları kapattık).
  4. Satır: SSH servisine dışarıdan erişim izni verdik (varsayılan 22 numaralı port).
  5. Satır: 5000 numaralı porta dışarıdan erişim izni verdik.
  6. Satır: Güvenlik duvarını aktif hale getirdik.

Not 1: Güvenlik duvarını aktif hale getirmeden önce SSH erişimine izin vermeniz gerekiyor. Aksi durumda sunucu erişiminizi kaybedersiniz.

Not 2: 5000 numaralı port, uygulamamızı test ederken kullanacağımız porttur. Daha sonra kapatacağız.

İlk Kontrol Noktası

Eğer bütün işlemler tamamsa uygulamanın doğru çalışıp çalışmadığını test etme vakti geldi demektir. Uygulama dizinindeyken (ve sanal ortam aktifken) aşağıdaki komutu çalıştırıyoruz.

(venv) ~$ flask run --host=0.0.0.0 --port=5000

Her şey tamamsa tarayıcıdan http://sunucu_ip_adresi:5000 adresine gittiğimizde uygulama düzgün bir şekilde bizi karşılayacaktır. Aksi durumda adımlardan birinde hata yapmışız demektir. Şimdi ilk kontrolü sonlandırıp (CTRL + C komutu ile sonlandırabilirsiniz) Supervisor ile uygulamayı kontrol etmek için gerekli ayarlamaları yapıyoruz. Ama önce 5000 numaralı portu erişime kapatalım.

~$ sudo ufw delete allow 5000

Supervisor Kurulumu

Supervisor, uygulamalarımızı yönetecek, loglarını tutacak ve daima çalışmasını sağlayacak basit ve etkili bir program. Ayrıca web arayüz desteğide sunuyor ki bu oldukça hoşuma gidiyor.

Supervisor Web Arayüzü

Kurulum için aşağıdaki komutu sisteme veriyoruz.

~§ sudo apt-get install supervisor

Hepsi bu kadar, supervisor sisteme kuruldu. Supervisor konusunda daha fazla detay isterseniz aşağıdaki yazıyı size öneririm.

Ali Orhun Akkirman: Supervisor Süreç Yöneticisi

Supervisor, yöneteceği her uygulama için /etc/supervisor/conf.d/ dizinin içerisinde .conf uzantılı bir yapılandırma dosyası oluşturmamızı istiyor. Dolayısıyla burada tanımlayacağımız her uygulama, supervisor tarafından yönetilebilir olacaktır. Hemen nano ile ilk yapılandırma dosyamızı oluşturuyoruz.

~$ sudo nano /etc/supervisor/conf.d/confidant.conf

Uygulama ismi ile yapılandırma dosyamı oluşturdum, şimdi içeriğini hazırlayabilirim.

[program:confidant]
directory=/home/<USER_PATH>/confidant
command=/home/<USER_PATH>/confidant/venv/bin/gunicorn -w 3 run:app -b 0.0.0.0:13001
user=<USER>
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
stderr_logfile=/home/<USER_PATH>/logs/confidant/confidant.err.log
stdout_logfile=/home/<USER_PATH>/logs/confidant/confidant.out.log

Aslında yeterince açıklayıcı olduğunu düşünüyorum. Ancak yinede kabaca belirtmem gerekirse

1. satırda program ismini belirtiyoruz. Bu ismin benzersiz olmasına dikkat edin, uygulamamızı bu isimle yöneteceğiz.
2. satır uygulamamızın çalışma dizinini işaret eder.
3. satır uygulamamızı çalıştıracak komutu belirler. Sanal ortam içerisindeki gunicorn ile çalıştırdığımıza dikkat edin. Burada dikkat edilecek bir diğer nokta run:app diyerek run.py içerisindeki app nesnesine işaret etmiş olmamız. Portuda bir kenara not ediyoruz. Her uygulama için farklı port kullanılması gerekmekte.
4. satıra sunucuya giriş yaptığımız kullanıcının adını giriyoruz.
5. satırda uygulama çökse bile otomatik olarak yeniden başlatmasını söylüyoruz.
9. ve 10. satırlar ise hata logları ile program çıktılarının loglandığı dosyaları işaret ediyor.

Eğer bu işlemleri tamamladıysanız CTRL + X diyerek dosyamızı kaydediyoruz ve editörden çıkıyoruz. Hata logların basılacağı dosyaları oluşturuyoruz.

~$ mkdir -p logs/confidant
~$ sudo touch /logs/confidant/confidant.err.log
~$ sudo touch /logs/confidant/confidant.out.log

İkinci Kontrol Noktası

Şimdi supervisor ile çalıştıracağımız uygulamayı test ediyoruz. Öncelikle yapılandırma dosyalarının supervisor tarafından okunabilmesi reload komutunu veriyoruz ve uygulamamızın çalışıp çalışmadığını görmek için status komutu ile kontrol ediyoruz.

~$ sudo supervisorctl reload
~$ sudo supervisorctl status

Eğer her şey yolunda ise confidant için running çıktısını ekranda göreceğiz. Hemen tarayıcıdan kontrol edelim. Eğer UFW kurduysanız, yapılandırma dosyasında belirtilen portu (13001) açmayı unutmayın.

~$ sudo ufw allow 13001

Şimdi tarayıcıya sunucu IP adresini ve portu girip programımızı kontrol edebiliriz. Tarayıcıdan http://<sunucu_ip_adres>:13001 adresine gidiyoruz. Uygulama karşımızda ise, ikinci kontrol noktasını da tamamlamış oluyoruz. Şimdi UFW ile portu kapatabiliriz.

~$ sudo ufw delete allow 13001

Supervisor ile uygulamalarımızı kontrol etmek için bilmemiz gereken bir kaç komut bulunuyor. Burada reload komutu yeni bir yapılandırma dosyası eklediğimizde, var olanı değiştirdiğimizde yada sildiğimizde çalıştıracağımız komuttur. Aynı şekilde restart komutu ise ismi verilen uygulamayı yeniden başlatır. Uygulamaları başlatmak yada durdurmak için ise start ve stop kullanılabilir.

~$ sudo supervisorctl reload
~$ sudo supervisorctl restart <APP_NAME>
~$ sudo supervisorctl start/stop <APP_NAME>

NGINX Kurulumu

Nginx sadece bir web sunucusu değil aynı zamanda ters vekil sunucusu ve yük dengeleyici gibi çeşitli alanlarda kullanılan oldukça gelişmiş bir uygulamadır. Flask uygulamamızı sanal olarak host edebilmemize olanak sağlarken statik dosyalarımızı da yayınlayacak kendisi. Hemen kurulumunu yapalım.

~$ sudo apt install nginx

Artık /etc/nginx/site-enabled klasörü içerisine yapılandırma dosyalarımızı oluşturabiliriz. Bu klasör içerisinde eklenen dosyalar nginx tarafından kullanılabilir. Ama öncesinde varsayılan yapılandırma dosyasını silmemiz gerekiyor.

~$ sudo rm /etc/nginx/sites-enabled/default

Şimdi nano kullanarak kendi uygulamamızın ismi ile yapılandırma dosyası oluşturabiliriz.

~$ sudo nano /etc/nginx/site-enabled/confidant

Yapılandırma dosyamızın içeriğini oluşturabiliriz artık.

server {
    server_name <domain_name_or_server_ip_address>;

    location /static {
        alias /home/<USER_PATH>/<APP_PATH>/app/static;
    }

    location / {
        proxy_pass http://localhost:<PORT_NUMBER>;
        include /etc/nginx/proxy_params;
        proxy_redirect off;
    }
}

server_name olarak sitemizin yayın yapacağı domain adresini giriyoruz. Eğer hali hazırda bir domaininiz varsa ve kayıtlarını sunucunuza yönlendirmişseniz domain ismini girebilirsiniz. Eğer domain yoksa sunucu IP adresini girmeniz yeterli.

Statik dosyalarımızın NGINX tarafından sunulmasını istediğimiz için uygulamamızın statik dosya klasörünün yolunu belirtiyoruz.

Ve son olarak, kök dizine gelen istekleri, supervisor tarafından çalıştırılan uygulamamıza iletecek şekilde düzenliyoruz. Port numarasını ise, supervisor yapılandırma dosyasına yazdığımız port numarasını yazıyoruz. Artık CTRL + X diyerek kaydedebiliriz. Şimdi NGINX servisini yeniden başlatabiliriz.

~$ sudo systemctl restart nginx.service

Eğer UFW kurulumu yaptıysanız, HTTP/TCP servisinede onay veriyoruz (80 numaralı port).

~$ sudo ufw allow http/tcp

Artık tarayıcıdan sunucu ip adresine giderek çalışıp çalışmadığını kontrol edebiliriz. Her şey tamamsa uygulamamız düzgün bir şekilde çalışıyor demektir.

http://<server_ip_address>

Uygulamamızı başarıyla yayına aldık. Biraz yorucu oldu ama deploy etmeyi başardık. Ve yeni uygulamalar eklerken bu kadar uğraşmamıza artık gerek kalmayacak.

Faydalı olmasını umuyorum. Uygulamayı nasıl bir domaine bağlayacağımıza ise bir sonraki konuda değineceğim, o zamana kadar sağlıcakla kalın!

Bir yanıt yazın

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