Container’lar server tarafında çalışan web uygulamaları, web servisler ve veri tabanı gibi GUI (Graphical User Interface) içermeyen uygulamalar için kullanılıyor. Peki container içerisinde bir GUI uygulaması kullanabilir miyiz? Buna neden ihtiyacımız olduğu ayrı bir konu (taşınabilir bir geliştirme ortamı?), ancak teknik olarak mümkün. Bunun için birkaç farklı seçenek var, bu yazıda Linux X Server yardımıyla container içerisinde yer alan bir uygulamayı host işletim sistemi üzerinden çalıştıracağız.
Biraz daha tanıdık olması açısından senaryomuz şu şekilde: İçerisine .NET Core 2.2 SDK kuracağımız bir Ubuntu imajına, C# plugin’i ile birlikte Visual Studio Code kurup, container içerisinde çalışan Visual Studio Code ara yüzü ile geliştirme yapmak.
NOT: Benzer şekilde Java geliştirme ortamı da kurabilirsiniz.
Öncelikle docker imajını hazırlamamız gerekiyor. Bunun için de ilk önce dockerfile’ı düzenlemeliyiz.
Base imaj olarak Ubuntu’nun son versiyonunu alıyoruz. Her ne kadar son versiyon da olsa güncelleme var mı diye bakmakta fayda var diyerek apt-get update ve apt-get upgrade komutlarını da çalıştırıyoruz.
Resim-1
İmajı güncelledikten sonra.NET Core SDK kurulumuna geçmeden önce kurulum için gerekli paketleri kuruyoruz.
Resim-2
packages-microsoft-prod.deb dosyasını /tmp altına indirip bu klasöre gidiyoruz, dpkg -i komutu ile yükledikten sonra da siliyoruz. Fazladan yer kaplamasına gerek yok J Daha sonra da universe repository’sini ekleyip, apt-transport-https paketini yüklüyoruz. Yeni bir repository eklediğimiz için bir kez daha apt-get update çalıştırıp son olarak da dotnet-sdk-2.2’yi yüklüyoruz.
Resim-3
.NET Core kurulumu tamam, sıra geldi Visual Studio Code’u kurmaya. Visual Studio Code kurmak için de öncesinde gerekli paketleri yüklememiz gerekiyor.
Resim-4
Visual Studio Code kurulum paketini de yine /tmp altına olacak şekilde, adını da biraz kısaltarak (vscode.deb) indiriyoruz. Sonra da yine /tmp altına giderek dpkg -i komutu ile kurulumu yapıp sonrasında da kurulum dosyasını siliyoruz.
Resim-5
Visual Studio Code’u root yetkileri ile çalıştırmak istemediğimiz için (denerseniz bu konuda bir uyarı mesajı çıkıyor) appuser adında yeni bir kullanıcı ekliyoruz ve bundan sonraki işlemleri bu kullanıcı ile yapıyoruz. Çalışma yerimiz de /home/appuser olsun.
Resim-6
Burada kullanıcıya id değerini 1001 vererek oluşturduk. Bu 1001 değeri nereden çıktı derseniz; Resim-7‘de göreceğiniz gibi host üzerindeki kullanıcı id’si de 1001. Nedeni ise yazının ileri kısımlarında detaylandıracağımız bir yetkilendirme konusu.
Resim-7
Son olarak da C# extension’ı yükleyip Visual Studio Code’u çalıştırıyoruz. Arka planla neler oluyor detaylı görmek için de verbose parametresi ile çalıştırıyorum. Açılışta da Projects klasörü ile açılmasını istiyorum.
Resim-8
NOT: Dockerfile’a buradan ulaşabilirsiniz.
Sırada build işlemimiz var. docker build -t dotnetcoredev . komutu ile imajımızı oluşturabiliriz. Dockerfile’da belirttiğimiz işlemlerin sırasıyla tamamlandıktan sonra “dotnetcoredev” isimli imajımız hazır hale gelecek.
Resim-9
Buraya kadar standard bir dockerfile hazırlayıp bir container imajı oluşturmak dışında ekstra bir şey yapmadık. Peki Visual Studio Code’u container içerisinde çalıştırınca arayüzü host işletim sistemine nasıl aktaracağız? Cevap: X Server.
X Server, Linux işletim sistemlerinde bitmap görüntüler için kullanılan bir pencereleme sistemi. Buradaki püf nokta ise host işletim sistemine ait X Server’a container üzerinden bağlanarak görüntüyü aktarmak.
Şimdi sıra geldi asıl işi yapacak komutumuza:
docker run -v $HOME/Projects:/home/appuser/Projects –net=host –env=”DISPLAY” –volume=”$HOME/.Xauthority:/root/.Xauthority:rw” dotnetcoredev
Parametreleri biraz detaylandıralım:
-v $HOME/Projects:/home/appuser/Projects
Container ile host arasında dosya paylaşımı yapmak için host üzerindeki kullanıcıya ait home/<kullanıcı adı>/Projects klasörü ile container içerisindeki home/appuser/Projects klasörünü bağlıyoruz. Böylece container içerisinde bu klasöre kaydettiğiniz dosyaları host üzerindeki aynı isimli klasörde görebileceksiniz. Buradaki yazma yetkisini sağlamak için host üzerinde kullanıcımız ile appuser kullanıcısının id’sini aynı verdik (Resim-7).
–net=host Container’ın host işletim sistemi ile aynı networkü paylaşmasını sağlar.
–env=”DISPLAY” Host işletim sisteminin display environment değişkenini container ile paylaşmasını sağlar.
–volume=”$HOME/.Xauthority:/root/.Xauthority:rw”
Host işletim sisteminin X Server’ını bir volume oluşturarak container ile paylaşmasını sağlar.
Komutu çalıştırdıktan sonra Resim-10‘de göreceğiniz gibi “Projects” klasörü ile açılmış Visual Studio Code ara yüzü çıkacak.
Resim-10
Dockerfile’a eklediğimiz C# extension’ı da kontrol etmek için Extensions’a bakabilirsiniz.
Resim-11
Şimdi de terminali açarak dotnet new console komutu ile yeni bir console projesi oluşturuyoruz.
Resim-12
Her şeyin düzgün olarak çalıştığından emin olmak için projemizi debug etmeyi deniyoruz. Resim-13‘te breakpoint’e de düştüğünü görebilirsiniz.
Resim-13
Kaydedilen dosyaları host üzerinde görebilmek için de kullanıcı klasörü (appuser) altında “Projects” adında bir klasör belirlemiştik. Buraya kaydettiğimiz dosyalara Resim-14 göreceğiniz gibi host üzerinden de erişebiliyoruz. Container içerisindeki Projects klasörünü otomatik olarak oluşturulacak, benzer şekilde host üzerindeki Projects klasörünü de eğer bu isimde bir klasör yoksa otomatik olarak oluşturuluyor. Burada dikkat etmemiz gereken kısım eğer bu klasör otomatik olarak oluşturulursa container içerisinden yazma yetkisinin olmayacağı, bu nedenle host üzerindeki klasörü de docker run komutunda belirttiğiniz şekilde önceden oluşturmalısınız.
Resim-14
Container’ı direkt olarak test etmek isterseniz docker hub’a buradan ulaşabilir ya da docker pull mertyeter/dotnetcoredev komutu ile direkt olarak indirebilirsiniz. Buradaki appuser uid değerinin (default değer olan) 1000 olarak set edildiğini de hatırlatmakta fayda var.
Bu konuyla ilgili sorularınızı alt kısımda bulunan yorumlar alanını kullanarak sorabilirsiniz.
Referanslar
https://dotnet.microsoft.com/download/linux-package-manager/ubuntu18-04/sdk-current
https://medium.com/@mccode/processes-in-containers-should-not-run-as-root-2feae3f0df3b
https://medium.com/@SaravSun/running-gui-applications-inside-docker-containers-83d65c0db110
https://github.com/mertyeter/dotnetcoredev
https://hub.docker.com/r/mertyeter/dotnetcoredev
TAGs: Docker, Containers, Dockerfile, Linux, Ubuntu, X Server, Ubuntu, Visual Studio Code, VSCode, Code, .NET Core