Go Dili İle Minimal Boyutlu Web Service Image’ları Oluşturun. Container Image’larına Yeni Bir Bakış Açısı Getirin.

Alper Reha YAZGAN
Turk Telekom Bulut Teknolojileri
5 min readJan 27, 2022

Hepinize merhaba ben Alper. Bugün sizlerle birlikte REST API geliştirirken Go dilini kullanarak geliştirme yapmanız durumunda Docker Container Image boyutlarında nasıl minimal boyutlarda (%90'a varan kazançlarla) uygulamalar oluşturabileceğinizi ve bu uygulamaları dağıtabileceğinizi göstereceğim. Bugün ki örnek için sizinle basit anlamda Node.js “HTTP Hello World” uygulaması ve Go dili ile “HTTP Hello World” uygulaması yapacağız ve birbirlerine göre nasıl bir farklılıkları var Container Image boyutları olarak karşılaştırarak sizlerle birlikte paylaşacağım.

(Bu yazı Image boyutları ve derleme süreci hakkında bilgilendirme ve uygulama amaçlıdır isterseniz direkt olarak sonuç kısmına gidip uygulamaların image boyutlarına bakabilirsiniz.)

Gereksinimler:

  • Container Yönetim Uygulaması (Docker, Podman)
  • Container Image Oluşturucu (Docker(Hazır geliyor), Buildah)
  • Go 1.17 versiyonu
  • Node.js

Node.js ve Go ile Basit HTTP Server Kodlanması:

Şimdi sizlerle birlikte çalışma dizini oluşturalım ve bu çalışma dizininde Node.js için ve Go için ayrı proje klasörleri oluşturup aşağıdaki kodları yazalım.

A. Node.js HTTP Hello World:

Node.js ile Hello World Uygulamamızı yapalım.

A.1) Öncelikle çalışma dizinimizde yeni bir klasör oluşturup burada npm projesi başlatıyoruz. Ayrıca projede yalnızca Express kütüphanesi kullanacağımız için paket yükleyicisiyle yükleme işlemini yapıyoruz.

# Cmd(Windows) veya Shell(Linux) Ekranında:mkdir node-hello
cd node-hello
npm init -y
npm install express

A.2) Npm projesi başlattığımız proje dizinine basit bir Express Hello World Uygulaması kodlarını aşağıdaki gibi server.js diye dosya oluşturarak içerisine yazıyoruz. (server.js dosyamız)

A.3) Şimdi oluşturduğumuz basit uygulamamızı Docker Container Image haline getirilebilmesi için birlikte bir Dockerfile yazmamız gerekiyor. Böylece yazdığımız kod artık platform bağımsız ve kurulum için ek maliyet gerektirmeyen bütün gereksinimlerin içerisinde kurulu olarak barındırıldığı bir Konteynır paketi haline getirilecektir. Biz de bu olayın sağlanması için proje dizininde Dockerfile isminde bir dosya oluşturup içerisine adım adım bu kendinden hazır paketin kurulumu için gerekli olan kodları aşağıdaki gibi söyleyeceğiz. (Dockerfile dosyamız)

Node.js Hello World Uygulamamız için Dockerfile dosyası

A.4) Dockerfile içerisinde birinci satırda “FROM” ifadesi ile hangi ana image üzerine kurulumu gerçekleştireceğimizi belirtiyoruz. Güncel olarak Node.js için birçok IMAGE hazırda bulunmakta. Biz boyutu olabildiğince düşürmek için ALPINE bazlı image’lar kullanacağız. İsterseniz farklı ana image yapıları da kullanabilirsiniz.

A.5) Şimdi Dockerfile kullanarak artık projemizi derleyip Container Image’ı haline getirebiliriz.

# Çalışma dizinindeyken
docker build -t hello-world-node .

Komutunu çalıştırıp proje kodlarımızı “hello-world-node” isminde bir konteynır imajı haline getirmesini bekliyoruz.

Bu konteynır image’ını oluşturduğumuzda bir temizleme işlemine tabii tutmadan ~172MB civarında tutmaktadır.

A.6) Oluşturulan image dosyamızı artık çalıştırabiliriz.

docker run --name my-node-hello-app -p 3000:3000 -d hello-world-node

Yukarıdaki kod sonrasında curl ile localhost:3000 url linkine istek attığınızda çalıştığını görebilirsiniz

Node.js Hello World uygulamamızı çalıştırdığımızda ve ne kadar alan kullandığını incelediğimizde ortaya çıkan ekran görüntüsü (173 MB)

B. Go Gin ile HTTP Hello World:

Şimdi ise Go dili Gin framework’ünü kullanarak Hello World uygulamamızı yapalım.

B.1) Yeni bir terminal ekranı açalım ve buradan Go için çalışma klasörü oluşturup HTTP Hello World uygulamamızı gerçekleştirelim.

# Cmd(Windows) veya Shell(Linux) Ekranında:mkdir go-hello
cd go-hello
go mod init go-hello # go projesi baslatiyoruz.

B.2) Çalışma dizinimiz ve Go projemiz başlayınca bulunduğumuz dizindeki projemize Golang Gin Web Framework kütüphanesini kuralım

go get -u github.com/gin-gonic/gin

B.3) Ardından main.go isminde bir dosya oluşturup içerisine basit bir şekilde “hello world” uygulamamızı aşağıdaki koddaki gibi yazıyoruz. (main.go dosyamız)

B.4) Sunucu tarafı kodumuz hazır olduğuna göre image’ı oluşturması için adım adım ne yapması gerektiğini Dockerfile içerisinde aşağıdaki gibi belirtiyoruz. (Dockerfile dosyamız)

Dockerfile içerisinde bir önceki Node.js Dockerfile dosyasından farklı olarak iki fazlı bir image build işlemi gerçekleştirdik. Birinci fazında kodu alıp derleme işlemini ve tek bir executable dosya üretme işlemini gerçekleştirip devamındaki ikinci fazda ise yalnızca bu dosyayı çalıştırma işlemine tabii tuttuk. Böyle çok yüksek bir yer kazancı sağlamış olacağız.

B.5) Şimdi Dockerfile kullanarak artık projemizi derleyip Container Image’ı haline getirebiliriz.

# Çalışma dizinindeyken
docker build -t hello-world-go .

Komutunu çalıştırıp proje kodlarımızı “hello-world-go” isminde bir konteynır imajı haline getirmesini bekliyoruz.

Image haline geldikten sonra uygulamamızı çalıştırabiliriz.

docker run --name my-go-hello-app -p 9090:9090 -d hello-world-go
Go Hello World uygulamamızı çalıştırdığımızda ve ne kadar alan kullandığını incelediğimizde ortaya çıkan ekran görüntüsü (14 MB)

Bu işlem gerçekleşip image boyutuna baktığımızda ise ~14MB image boyutu görmekteyiz.

Sonuç:

Image “build” sonrası Node.js ve Go Gin Image boyutları
Uygulamaların “run” esnasında kapladıkları alan boyutları

Go dili kendi doğası gereği ve derleme aşaması sonrası sağladığı imkanlar ile kodlanmış projenin bütün gereksinimlerinin bulunduğu tek bir executable file olarak çıktı verebilmektedir. Docker image içerisinde ise .exe dosyasını çalıştırıp geri kalan konteynır yönetimi ise Docker Deamon veya hangi Konteynır yönetim uygulaması kullanılıyorsa(Podman, Cri-o) ona bırakılabilmektedir.

Özetle REST API veya Stateless olarak tasarlanmış ve filesystem aksiyonlarının az olduğu web servis uygulama kodlarında Go dilinin güzelliklerinden faydalanılarak imaj boyutlarında %90'a varan boyut kurtarılmasına gidilebilir ve kazanılan yer ölçütünde uygulamanın yatayda büyümesine olanak sağlanabilmektedir. Ancak Web Front-end işlemlerinin ağır olduğu kodlamalar için ise Go dili halen yeni bir dil olup web-frontend için Node.js ve sağladığı kütüphaneler (React, Angular) kadar zengin içeriği bulunmamaktadır.

Go sayesinde Back-end operasyonları için CI/CD pipeline aşamasında sağladığı “kısa derlenme zamanı” ve “küçük imaj boyutu” sayesinde işlem süreçleri için harcanan işlem zamanını ve sistem gereksinimlerini azaltmaktadır.

Bu makale ile birlikte sizlerle birlikte Go dili basit Hello World uygulaması yaptık ve Docker image build ve run aşamalarını da gerçekleştirmiş olduk. Güncel olarak her web servis için gerekli olan yapıların bulunduğu (Cache, Swagger, SQL Orm, NATS Pub&Sub vb. gerekli kodların tek bir main.go dosyası içerisinde bulunduğu ve sizin de kullanabileceğiniz hazır kodların bulunduğu) Alya-Go-Gin-Boilerplate isminde bir repository açmıştım ve geliştirmekteyim. İnceler, yorum yapar ve PR atarsanız çok memnun olurum 😅.

Gelecek yazılarda görüşmek üzere.

Alper Reha YAZGAN.

--

--

Alper Reha YAZGAN
Turk Telekom Bulut Teknolojileri

Yıldız Teknik Üniversitesinde Bilgisayar Mühendisliği öğrencisi, yeni nesil teknoloji ve yeniliklere karşı araştırmacı ve meraklı birisiyim.