Kendi Docker İmajımızı Yapalım

Merhaba arkadaşlar, mobilhanem.com ‘da bir Docker dersi ile daha birlikteyiz.  Bir önceki yazımızda Docker imajlarını ve Docker Hub’daki hazır imajların kullanımını anlatmıştık. Bu yazımızda ise kendi Docker imajlarımızı nasıl oluşturup kullanabileceğimizi öğreneceğiz.

Docker imajı oluşturma

Docker imajı oluşturmak için 2 yöntem bulunmaktadır. İlk yöntem yeni bir container açıp, içinde yapmak istediğimiz değişiklikleri çalıştırdıktan sonra bu container’ı kaydetmektir. İkinci yöntem ise Dockerfile oluşturup, docker build komutunu çalıştırmak. Genelde tercih edilen yöntem Dockerfile yöntemidir. Çünkü bu yöntem sayesinde siz Docker imajınızın nasıl olması gerektiğini Dockerfile’a yazarsınız ve gerektiğinde tekrar kolaylıkla çalıştırabilirsiniz. İlk yöntem bir şeyler denerken belki işinize yarar ama tavsiye edilmediği için ben de bu yazımızda bahsetmeyeceğim.

Dockerfile dosyasının ilk satırında baz imaj ve versiyonu yazmalıdır. Her imaj bir baz imajdan türediği için bunun da Dockerfile’ın en başında belirtilmesi gerekir. Diğer her satırda ise çalıştırmak istediğiniz komutlar RUN, ya da dışarıdan eklemek istediğiniz dosyaları belirten ADD ve COPY şeklinde direktiflerle başlar. En sonda bulunan CMD ya da ENTRYPOINT direktifi ise imajınızın hangi komutla çalışması gerektiğini bildirir, fakat yazılması şart değildir. Yazılabilecek tüm direktiflere şuradan ulaşabilirsiniz: https://docs.docker.com/engine/reference/builder/

Kendi Dockerfile’ımıza basit bir örnek ile başlayacağız. Bir ubuntu imajının içine Nodejs kurabilen bir Dockerfile yapacağız.

FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install vim nodejs -y

Yukarıdaki içeriği, boş bir klasör açıp içine Dockerfile olarak kaydedelim. Boş klasör açmamızın sebebi, docker build komutu, ADD ve COPY komutlarının çalışabilmesi için o klasörün tüm içeriğini bilgisayarınızdaki Docker sunucusuna göndermesidir. Bu durum eğer bu komutları kullanmayacaksanız gereksiz yere dosya transferine ve yavaşlamaya sebep olabilir. Dockerfile’ı kaydettikten sonra ise docker build -t my-image olarak çalıştırmanız gerekmektedir. -t komutu oluşan Docker imajına isim verilmesini sağlıyor. Bu ismin sonuna my-image yerine my-image:v1 yazarak imajınızı farklı versiyonlarda kaydedebilirsiniz. Bu imajı kaydettikten sonra docker run -ti my-image yazıp, yeni contaniner açtıktan sonra içine girip, yüklediğimiz vim yazılımı ile dosya oluşturup nodejs ile çalıştırabiliriz.

Şimdi ise daha kompleks, ve gerçekçi bir Docker imajı yapacağız. Github’ta, Go ile yazmış olduğumuz bir web sunucuyu derleyip, farklı branch’lerden farklı imajlar alacağız.

FROM golang:1.14.1

ARG BRANCH=master

RUN git clone –single-branch –branch ${BRANCH} https://github.com/mustafaakin/docker-kubernetes-egitimi.git /code

WORKDIR /code/01-imaj/

RUN go build -o /server server.go

EXPOSE 8080

ENTRYPOINT /server

Bu imajı docker build . -t sunucu komutu ile derlediğinizde BRANCH argümanının varsayılan değeri olarak master ile çalışacaktır. Çalıştırdığımızda göreceksiniz ki golang:1.14.1 imajı Docker Hub’dan inecek, ve Dockerfile’daki her aşama teker teker çalıştırılacaktır.

Bu örnek Github repository’sinde ise test amaçlı oluşturduğumuz yeni-ozellik adında başka bir branch bulunmaktadır, bu branch’te sunucu “Merhaba Dünya” yerine “Merhaba Mobilhanem” yazacak. Bu iki branch değeri ile iki farklı imaj alacağız ve bu web sunucularına erişeceğiz. docker build . -t sunucu:yeni-ozellik –build-arg BRANCH=yeni-ozellik komutunu çalıştırdığınızda build-arg komutu docker build sırasında argüman vermemizi sağlar. Bu şekilde çalıştırdığımız zaman göreceksiniz ki golang:1.14.1 imajı tekrar indirilmeyecek, var olan imaj kullanılacaktır.

Peki bu imajları nasıl kullanacağız? Kurduğumuz bu programlar bir web sunucusu olduğundan, onlara ulaşmak için portlarına ulaşmamız gerekecektir. Docker dosya ve processleri izole ettiği gibi, aynı zamanda network’ü de izole eder. Her container’ın sunucudaki ana ağ kartına köprü (bridge) yöntemi ile bağlı izole sanal ağ kartları da bulunmaktadır. Bu sayede, containerlar sunucuda sanal bir ağda kendilerine özel IP adresi alır. Sunucumuzdan da bu IP adreslerine direkt ulaşabilir, ya da sunucunun bir portuna bağlanmasını sağlayabiliriz. Container’ımız 8080 portunda dinlediği için, bu iki container’ı sunucuda 10000 ve 10001 portlarına bağlayacağız. Sırayla  docker run -d -p 10000:8080 –name s1 sunucu:master ve docker run -d -p 10001:8080 –name s2 sunucu:yeni-ozellik komutlarını çalıştırın. Buradaki -d komutu container’ın arka planda çalışmasını sağlıyor. -p komutu ise sunucudaki portun container’daki, hangi porta bağlanacağını belirtiyor. Her container kendi içinde 8080 portunu kullansa da biz sunucumuzda ikisini de aynı porta bağlayamayac

Container’lar çalıştıktan sonra docker ps komutu ile container’ların çalıştığını görebilirsiniz. Container’ları durdurmak için ise docker kill s1 komutunu çalıştırabilir, docker remove s1 ile de container’ı tamamen kaldırabilirsiniz. Tarayıcınızdan 10000 ve 10001 portlarına girdiğinizde iki farklı container’ın isteklerinize cevap verdiğini ve ikinci container’ın yaptığımız değişiklik ile cevap verdiğini göreceksiniz:

ÖZET

Bu yaptığımız örneği geliştirme süreçlerinizde uyarladığınızı düşünün. Bir şirkette, bir koda aynı anda 10 geliştirici farklı branch’lerden kod geliştirdiği zaman, bunları deneyip görmek isteyebilirsiniz. Geliştiriciniz ya da CI (Continuous Integration) sisteminizin sağlayacağı, Git repository’sinden istenilen branch ile Docker imajları alma imkanı yarattığınız zaman, geliştiriciler ortak sunucularda birbirlerini engellemeden, kurulum sıkıntısı olmadan, sadece birkaç komutla yaptıklarını canlı olarak görebilirler. Docker’a adapte olmuş çoğu şirket, yazılımlarını, microservislerini Docker’da derleyip, paketleyip kullanıma hazır hale getiriyor. Bu sayede iz bırakmadan, izolasyon gibi sorunlarla uğraşmadan kolaylıkla değişiklikleri görüp onaylayabilirsiniz. Developer branch’e kodunu gönderdiği zaman testleri kolaylıkla Docker’da izole bir şekilde çalıştırıp, sonuçlardan kolaylıkla haberdar olabilir. Canlıya alma ve sorunlardan haberdar olma süresini çok kısa sürelere indirebilirsiniz. Tabi ki tüm bunları yapmak için Docker’a ihtiyacınız yok, geleneksel yöntemler de işinizi görebilir, fakat Docker burada size çok büyük kolaylık sağlayıp, sizin daha önemli şeylere vaktinizin kalmasını sağlayabilir.

Docker’ın sağladığı bu gibi imkanları şirketinizde, okulunuzda, kişisel projelerinizde nasıl uygulayabileceğinizi düşünün. Eminim ki Docker sayesinde birçok kullanım alanında iyileştirmeler yapabilirsiniz.

Tüm Docker derslerimiz için tıklayınız.

5

Mustafa Akın

SRE Architect @Atlassian Opsgenie
PhD Öğrencisi @Bilkent Üniversitesi

Yorum Yaz

Haftalık Bülten

Mobilhanem'de yayınlanan dersleri haftalık mail almak ister misiniz?