Docker Desktop ile VNC kullanımı

Selamlar, bu yazımda biraz farklı bir konuya değineceğim: Docker konteyneri içinde grafiksel bir uygulamayı çalıştırıp ona VNC ile bağlanmak. Konteyner deyince çoğumuzun aklına headless servisler, API'ler, cron job'lar geliyor. Tabii haksız da değiliz; konteynerin doğal habitatı orası. Ama gerçek hayatta arada bir 'şu eski Linux uygulamasını izole çalıştırsam', 'tarayıcı testlerini canlı izlesem', 'ekipteki herkese aynı hazır masaüstünü versem' diyebileceğiniz durumlar çıkıyor. İşte burada VNC + Docker ikilisi gerçekten cebimize yarıyor. Hadi başlayalım.

VNC ve Docker birlikte nasıl çalışır?

VNC (Virtual Network Computing) klasik bir istemci-sunucu protokolü. Konteynerin içinde bir VNC sunucusu çalışıyor, bu sunucu sanal bir framebuffer'a ekran çiziyor. Host makinedeki istemci de TCP üzerinden bu sunucuya bağlanıp gördüğünüz pikselleri çekiyor. Yani konteynerin gerçekten bir ekranı yok; biz onun için sahte bir ekran hazırlayıp dışarıdan bakabilen bir kapı açıyoruz.

Akış kabaca şöyle: VNC istemcisi (host) -> 5901 portu -> konteyner içindeki TigerVNC -> Xvfb sanal display -> GUI uygulaması.

En basit kurulum: Ubuntu + XFCE

Hadi minimum bir örnek yazalım. XFCE'yi seçtim çünkü hafif, KDE veya GNOME konteynere fazla geliyor.

FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
    xfce4 xfce4-terminal \
    tigervnc-standalone-server tigervnc-common \
    dbus-x11 fonts-liberation xfonts-base \
    && rm -rf /var/lib/apt/lists/*

RUN useradd -m -s /bin/bash vncuser
USER vncuser
WORKDIR /home/vncuser

RUN mkdir -p .vnc && \
    echo 'dockervnc' | vncpasswd -f > .vnc/passwd && \
    chmod 600 .vnc/passwd && \
    printf '#!/bin/bash\nstartxfce4 &\n' > .vnc/xstartup && \
    chmod +x .vnc/xstartup

EXPOSE 5901
CMD ['vncserver', ':1', '-geometry', '1280x720', '-depth', '24', '-fg']

Burada VNC parolasını imaj içine gömdük; production'da bunu yapmayın, environment değişkeniyle giriş anında üretin. Şimdi build alıp çalıştıralım:

docker build -f Dockerfile.vnc -t ubuntu-vnc .
docker run -d --name vnc-desktop -p 5901:5901 ubuntu-vnc

macOS'ta bilgisayarınızda bulunan Screen Sharing, Linux'ta TigerVNC Viewer ya da Remmina ile localhost:5901'e bağlanın. Parola dockervnc. Karşınıza küçük ama tam donanımlı bir XFCE masaüstü çıkıyor.

Tarayıcıdan erişim: noVNC

VNC istemcisi yüklemek istemiyorsanız, noVNC işinizi görür. Konteynerin içinde bir websockify proxy çalışıyor ve VNC akışını HTML5 üzerinden tarayıcıya servis ediyor.

# Yukaridaki Dockerfile'a novnc, websockify ve python3-numpy ekleyin
# Sonra start.sh icinden hem vncserver hem websockify ayaga kalksin:
websockify --web /usr/share/novnc 6080 localhost:5901

http://localhost:6080/vnc.html adresinden açıp parolayı girdiğinizde XFCE masaüstü direkt browser tabınızda. Bence bu yöntem ekipteki herkese istemci kurdurmaktan çok daha pratik; özellikle Windows kullanıcıları için.

Tek uygulama çalıştırmak

Her zaman bütün masaüstü gerekli değil. Diyelim sadece izole bir Firefox lazım: tarayıcı testleri için, ya da şüpheli bir siteyi sandbox'ta açmak için.

docker run -d --name firefox-vnc \
  -p 6080:6080 \
  --shm-size=512m \
  docker-firefox

--shm-size=512m kritik. Chrome ve Firefox paylaşımlı bellek üzerinden render ediyor; varsayılan 64 MB ile sayfa açılır açılmaz çöküyorlar. Şahsi tecrübemden söyleyebilirim, bu bayrağı koymadan harcadığım saatler oldu.

Compose ile temiz bir kurulum

Birden fazla VNC servisi çalıştıracaksanız Compose hayatınızı kolaylaştırır:

services:
  desktop:
    build: { context: ., dockerfile: Dockerfile.novnc }
    ports:
      - '6080:6080'
    shm_size: '1gb'
    volumes:
      - desktop-data:/home/vncuser
      - ./shared:/home/vncuser/shared

volumes:
  desktop-data:

shared klasörü ile host ve konteyner arasında dosya alışverişi yapabiliyorsunuz; bu özellikle 'tarayıcıda indirdim, host'a almam lazım' senaryosunda işe yarıyor.

Sık karşılaşılan hatalar

  • --shm-size vermemek: Tarayıcı tabanlı uygulamalar render ederken çöker, log'da SIGTRAP görürsünüz. En az 512 MB verin.
  • VNC parolasını imaja gömmek: Imaj registry'ye gittiğinde parola da gidiyor. Parolayı runtime'da vncpasswd -f ile env'den üretin.
  • Şifresiz açık port: VNC trafiği şifresiz. -p 5901:5901 ile internete açtığınızda kelimenin tam anlamıyla davet ediyorsunuz. Uzaktan erişim için SSH tüneli kurun: ssh -L 5901:localhost:5901 user@host.
  • Çift display üst üste açmak: Konteyneri restart edip eski :1 lock dosyası kalırsa VNC ayağa kalkmaz. xstartup öncesi vncserver -kill :1 || true koymak temiz bir alışkanlık.

Doğrulama

Konteyner ayağa kalktıktan sonra portu ve süreci hızlıca kontrol edin:

docker ps --filter name=vnc-desktop
docker exec vnc-desktop ss -tlnp | grep 5901

5901 dinleniyorsa ve tigervnc süreci görünüyorsa hazırsınız.

Kapanış

Bu yazıda Docker konteyneri içinde VNC sunucusu çalıştırmanın temel kurulumuna, noVNC ile tarayıcıdan erişime ve sık takılınan tuzaklara baktık. Bana sorarsanız, izole tarayıcı testleri ve ekibe standart geliştirme ortamı sunmak için bu yöntem hâlâ en pratik çözümlerden biri. Umarım faydalı olur, görüşmek üzere.