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

Docker Stack Deploy

Docker ile tanışana kadar bir geliştirici olarak geliştirme ortamını ayağa kaldırmak, hazırlamak hep baş belası olmuştu. Virtualbox / Vagrant gibi çözümler var olsa da bu çözümler birçok problemi yanında getiriyordu. Ancak docker ile tanıştıktan sonra sıfır bir cihazı alıp geliştirme ortamını hazırlamak dakikalarla ifade edilebilir oldu. Her ne kadar uzun süredir geliştirme ortamında docker kullansam da production seviyesinde kullanma fırsatını hiç yakalayamadım.

WordPress 5.2 versiyonu çıktıktan sonra blogumu güncellemeye çalıştığımda farkına vardım ki kullandığım PHP versiyonu yeterli gelmiyor – evet benim için çok ayıp! -. Tam 6 sene önce uygulamayı nasıl ayağa kaldırdıysam herşey aynı şekilde duruyordu -çalışıyorsa dokunma dediler-. Bende fırsat bu diyerek blogu dockerize ettim aynı zamanda deployment için de docker kullanmaya karar verdim. Ardından da bu süreci yazmak farz oldu tabi.

Ön Koşullar


  • Docker ve Docker komut seti hakkında temel bilgiye sahip olmak.
  • Docker Swarm Mode hakkında temel bilgiye sahip olmak.

Çalışma Özeti


  • Bir wordpress uygulamasını dockerize ederek, kendi bilgisayarımızda ayağa kaldırılması.
  • Docker Machine kullanarak DigitalOcean üzerinde bir sunucu oluşturulması.
  • Uygulamalarımızın DigitalOcean üzerinde oluşturduğumuz sunucuya deploy edilmesi.

Çalışma Kapsamında Olmayacaklar


  • Docker Swarm Mode’un getirdiği şahane özelliklerin ayrıntıları.
  • Docker Compose kullanımı

Uygulamanın dockerize edilmesi


Bir uygulamanın dockerize edilmesi uygulama kapsamındaki servislerin belirlenerek bu servislerin çalıştırılabileceği konteynerlerin oluşturulması anlamına geliyor. Örnek vermek gerekirse; elinizde çok basit bir web uygulamasının var olduğunu düşünün. Bu uygulamanın en az bir veritabanı sunucusu bir de uygulama sunucusu olacaktır. Ayrıca bu bir web uygulaması olduğu için uygulama sunucusu önünde Nginx veya Apache gibi bir web sunucusu da bulunmalıdır. İşte bu sunucuların kendi başlarına çalışabileceği en küçük konteynerleri oluşturup ve bu konteynerlerin arasındaki veri akışını sağlayacak konfigurasyonları Docker kullanarak yaptığımızda aslında uygulamayı dockerize etmiş oluyoruz.

Öncelikle boş bir wordpress uygulaması oluşturalım.

$ wget https://wordpress.org/latest.tar.gz && tar -xzvf latest.tar.gz && cd wordpress/

Eğer hali hazırda bir wordpress projeniz varsa bu adımı geçebilirsiniz. Daha sonra uygulama dizini içerisinde docker-compose.yml dosyasını oluşturabiliriz.

version: '3.1'

volumes:
   db-data:

services:
   wordpress:
      image: wordpress
      restart: always
      ports:
         - 80:80
      environment:
         - WORDPRESS_DB_HOST=mysql
         - WORDPRESS_DB_PASSWORD=root
         - WORDPRESS_DB_USER=root
      volumes:
         - ./:/var/www/html
   mysql:
      image: mysql:5.7
      restart: always
      ports:
         - 33060:3306
      volumes:
         - db-data:/var/lib/mysql
      environment:
         - MYSQL_ROOT_PASSWORD=root

İlgili Docker imajları hakkında bilgi için:

https://hub.docker.com/_/wordpress
https://hub.docker.com/_/mysql

Gördüğünüz gibi veritabanı ve uygulama sunucusunun tanımını yaptık. wordpress imajı kendi içerisinde web sunucusunu barındırdığı için ayrıca bir servis oluşturmadık. Ancak büyük ölçekli uygulamalarda web sunucusunun ayrı konteynerde çalıştırılması kesinlikle daha faydalı olacaktır. Docker özelinde de bir konteynerin sadece tek bir işi yüklenmesi doğru yaklaşımdır.

Bu aşamadan sonra kendi bilgisayarınızda aşağıdaki komut ile uygulamayı çalıştırabiliyor olmalısınız.

$ docker-compose up

Boş bir wordpress uygulaması kullandığımız için wordpress kurulum sayfasına yönlendiriliyoruz. Burada önemli olan uygulamamızın artık dockerize edilmiş olması ve bu şekilde bir sunucuya deploy edilebilir halde olmasıdır.

Docker Machine ile DigitalOcean’da sunucu oluşturulması


Şu anda elimizde dockerize edilmiş bir uygulama bulunuyor ve biz bu uygulamayı sunucuya yine Docker kullanarak deploy etmek istiyoruz. Öncelikle deploy edeceğimiz sunucuyu oluşturalım. Ben servis sağlayıcı olarak DigitalOcean kullanacağım ancak desteklenen diğer sürücüleri görmek isterseniz https://docs.docker.com/machine/drivers/ buraya bakabilirsiniz.

Öncelikle DigitalOcean API’sini kullanabilmek için token üretelim. DigitalOcean > API > Generate New Token yolunu takip ederek oluşturabilirsiniz. Oluşan token’ı saklamayı unutmayın. Sayfayı kapattığınızda tekrar göremeyeceksiniz.

Daha sonra aşağıdaki komutu kullanarak en küçük boyutta bir droplet oluşturabilirsiniz.

$ docker-machine create --driver digitalocean --digitalocean-access-token=<TOKEN> --digitalocean-region=fra1 --digitalocean-size=1gb <DROPLET ADI>

Lütfen <TOKEN> ve <DROPLET ADI> kısımlarını değiştirmeyi unutmayın. Yazının devamında <DROPLET ADI> olarak myblog kullanacağım.

DigitalOcean hesabınıza girip Droplets sekmesinde oluşan sunucuyu görebilirsiniz. Makineyi oluştururken kullanabileceğiniz tüm opsiyonları ise https://docs.docker.com/machine/drivers/digital-ocean/ buradan inceleyebilirsiniz.

Artık sunucumuz deploy işlemi için hazır.

Çevre değişkenlerinin ayarlanması


Uygulamamızı dockerize ederken çevre değişkenlerini önemsemeden vermiştik. Ancak uygulamanızı bir sunucuya deploy ettiğinizde bu bilgiler önem arz ediyor. Farklı sunucular için farklı değişkenlerin kullanılması gerekiyor. Dolayısıyla daha önceden oluşturduğumuz docker-compose.yml dosyasında birkaç değişiklik yapmamız gerekiyor. Diyelimki oluşturduğumuz sunucuyu production ortamı olarak kullanacağız.

# docker-compose.production.yml

version: '3.1'

services:
   wordpress:
      environment:
         - WORDPRESS_DB_HOST=mysql
         - WORDPRESS_DB_PASSWORD=<SECRET PASSWORD>
         - WORDPRESS_DB_USER=root
   mysql:
      environment:
         - MYSQL_ROOT_PASSWORD=<SECRET PASSWORD>
$ docker-compose -f docker-compose.yml -f docker-compose.prod.yml up

Uygulamayı bu şekilde çalıştırdığımızda veritabanı parolasının değiştiğini görebiliriz. Bu sayede production ortamında farklı çevre değişkenleri tanımlayabiliriz.

İkinci ve oldukça önemli olan bir diğer nokta ise yine docker-compose.yml içerisinde tanımladığımız volumes farklı sunucularda değişiklik göstermektedir. Development ortamında host üzerinde fiziksel olarak var olan bir dizin kullanılırken production ortamında ağa bağlı bir disk kullanılmak istenebilir.

# docker-compose.production.yml

version: '3.1'

services:
   wordpress:
      volumes:
         - /var/www/html:/var/www/html
      environment:
         - WORDPRESS_DB_HOST=mysql
         - WORDPRESS_DB_PASSWORD=<SECRET PASSWORD>
         - WORDPRESS_DB_USER=root
   mysql:
      environment:
         - MYSQL_ROOT_PASSWORD=<SECRET PASSWORD>

Production ortamında uygulama kodunun /var/www/html dizininde olduğunu varsayarsak tanımlamayı yukarıdaki gibi yapabiliriz.

ÖNEMLİ!!!

Şu anki durumda hem docker-compose.yml hem de docker-compose.production.yml dosyalarında konteyner içerisindeki /var/www/html dizinine mount işlemi yapılıyor. İlerde deployment işlemini yaparken bu durum sorun çıkarmaktadır. Ayrıca birden fazla geliştirici proje üstünde çalışıyorsa geliştiriciler kendi ortamlarındaki mount işlemlerini kendilerine göre yapmak isteyebilirler. Bu durumda volume tanımını docker-compose.override.yml dosyasına taşımak güzel bir çözüm olacaktır.

Sonuç olarak tüm konfigürasyon dosyaları aşağıdaki gibi olacaktır:

# ***************************
# docker-compose.yml
# ***************************

version: '3.1'

volumes:
   db-data:

services:
   wordpress:
      image: wordpress
      restart: always
      ports:
         - 80:80
      environment:
         - WORDPRESS_DB_HOST=mysql
         - WORDPRESS_DB_PASSWORD=root
         - WORDPRESS_DB_USER=root
   mysql:
      image: mysql:5.7
      restart: always
      ports:
         - 33060:3306
      volumes:
         - db-data:/var/lib/mysql
      environment:
         - MYSQL_ROOT_PASSWORD=root


# ***************************
# docker-compose.override.yml
# ***************************

version: '3.1'

services:
   wordpress:
      volumes:
         - ./:/var/www/html


# ***************************
# docker-compose.production.yml
# ***************************

version: '3.1'

services:
   wordpress:
      volumes:
         - /var/www/html:/var/www/html
      environment:
         - WORDPRESS_DB_HOST=mysql
         - WORDPRESS_DB_PASSWORD=<SECRET PASSWORD>
         - WORDPRESS_DB_USER=root
   mysql:
      environment:
         - MYSQL_ROOT_PASSWORD=<SECRET PASSWORD>

Deployment

Tüm parçaları oluşturduktan sonra artık servislerimizi deploy edebiliriz. Öncelikle docker-machine ile sunucuya geçiş yapalım.

$ eval `docker-machine env myblog`

Bu komuttan sonra docker komut seti işlemlerini sunucu üzerinde çalıştıracaktır.

Görüntüdeki komutu çalıştırdığımızda ACTIVE sekmesi altındaki yıldız hangi makinenin aktif olduğunu gösteriyor. Bu işlemi geri almak istersek;

$ eval `docker-machine env -u`

Aktif makineyi myblog olarak seçtikten sonra bu sunucu üzerindeki swarm modu aktif edelim.

$ docker swarm init

Daha sonra kodumuzu /var/www/html dizinine deploy etmeyi unutmayalım. Aşağıdaki komut sizin bilgisayarınızdaki kodu taşımayacaktır. Burada yapılan işlem konteynerlerin sunucu üzerinde verilen konfigurasyonlar ile oluşturulmasıdır.

$ docker stack deploy --compose-file docker-compose.yml -c docker-compose.prod.yml <STACK NAME>

Yukarıdaki komut ile deployment işlemini tamamlayabiliriz. Bu işlem konfigurasyon dosyalarını okuyup servisleri oluşturmak için ilgili imajları sunucuya indirecek. Ardından ilgili konteynerleri servis olarak ayağa kaldıracaktır. Aslında konfigurasyon dosyalarında her bir servisten kaç adet olacağını, en az ne kadar belleğe ihtiyaç duyduğunu, hangi tipte sunuculara deploy edilebileceğini ve buna benzer bir çok şeyi söyleyebiliyoruz. Bu örnekte ben sadece tek bir sunucu oluşturdum ve tüm servislerimi orada ayağa kaldırdım. Ancak gerçek dünyada elimizde bir grup sunucu ve ayağa kaldırmamız gereken bir grup servis bulunuyor. Burada bu ayrıntılara değinmedim ancak öğrenmek isteyenler için Gökhan Şengün olabilecek en güzel şekilde anlatıyor. İlgili arkadaşların kesinlike ve kesinlikle izlemesini ve takip etmesini tavsiye ederim.

Deploy işlemi tamamlandıktan sonra sunucu IP adresini ziyaret ettiğinizde wordpress kurulum ekranını görmelisiniz.