Yeni bir VDS aldınız, resmi kurulum betiğiyle Docker'ı kurdunuz ve ilk komutu yazdınız. Ekrana gelen cevap şu oldu:
Got permission denied while trying to connect to the Docker daemon socket at
unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.47/containers/json":
dial unix /var/run/docker.sock: connect: permission denied
Kurulum başarısız olmadı, servis de çalışıyor. sudo docker ps yazdığınızda her şey normal görünüyor. Yani bozuk bir şey yok; sadece komutu çalıştıran kullanıcının Docker soketine yazma yetkisi yok. Bu hata, muhtemelen Docker dünyasında en çok karşılaşılan tek hatadır ve neredeyse her yeni kurulumun ilk beş dakikasında çıkar.
Sorun şu ki Türkçe arama sonuçlarının önemli bir kısmı bu hatayı "çözerken" sunucuyu herkese açan bir komut öneriyor: sudo chmod 666 /var/run/docker.sock. Bu komut hatayı gerçekten susturur — ve aynı anda sunucudaki her kullanıcıya, çalışan her PHP/Python işlemine, her web uygulamasına root yetkisi verir. Bu yazının açık bir varlık sebebi bu tavsiyeyi düzeltmek.
Aşağıda önce mekanizmayı, sonra doğru çözümü, ardından "ekledim ama olmadı" şikâyetinin tek nedenini, en sonda da docker grubuna kimleri koymamanız gerektiğini ve rootless alternatifini ele alacağım. Docker'a yeni başlıyorsanız Docker nedir başlangıç rehberi buradaki kavramların temelini veriyor.
Hata Tam Olarak Ne Diyor?#
Mesajı parçalayınca kendi kendini açıklıyor:
- "Docker daemon socket" — Docker aslında iki parçadır.
dockerkomutu yalnızca bir istemcidir; asıl işi (imaj indirmek, konteyner başlatmak, ağ kurmak) root olarak çalışandockerdarka plan servisi yapar. - "unix:///var/run/docker.sock" — İstemci ile daemon arasındaki konuşma bir Unix domain soketi üzerinden geçer. Bu, dosya sisteminde duran özel bir dosyadır.
- "connect: permission denied" — İstemci o dosyaya bağlanmaya çalıştı, çekirdek dosya izinlerine baktı ve reddetti.
Yani hata Docker'ın içinde değil, klasik Linux dosya izinleri katmanında oluşuyor. docker komutu bir hata mesajı üretiyor ama kararı veren çekirdek. Soketin durumuna bakalım:
ls -l /var/run/docker.sock
# srw-rw---- 1 root docker 0 Aug 18 09:14 /var/run/docker.sock
Satırın okunuşu: baştaki s bunun bir soket olduğunu söyler. Sahibi root, grubu docker. İzinler rw- (sahip), rw- (grup), --- (diğerleri). Yani root ve docker grubundaki üyeler yazabilir; başka hiç kimse okuyamaz bile. Sizin kullanıcınız üçüncü kümede, yani "diğerleri" tarafında olduğu için bağlantı reddediliyor. İzin bitlerinin okunuşuna aşina değilseniz Linux dosya izinleri yazısı bu gösterimi ayrıntısıyla anlatıyor.
Kendi durumunuzu tek komutla görebilirsiniz:
id -nG # içinde bulunduğunuz gruplar
getent group docker # docker grubunun üyeleri
docker kelimesi ilk çıktıda yoksa hata beklenen davranıştır, arıza değil.
Docker Soketi Neden root:docker Sahipliğinde?#
Bu sahiplik tesadüf değil, paketin kasıtlı tasarımı. dockerd root olarak çalışmak zorundadır: cgroup oluşturur, namespace açar, ağ arayüzü ve iptables kuralları yazar, dosya sistemi mount eder. Bunların hepsi ayrıcalıklı işlemlerdir.
Ama her docker ps için root olmak zorunda kalmak da kullanışsız olurdu. Çözüm olarak paket, kurulumda docker adında bir sistem grubu oluşturur ve soketi bu gruba verir. Böylece "daemon root çalışsın, ama ona konuşma yetkisi seçilmiş kullanıcılarda olsun" ayrımı kurulur.
Bu ayarı yapan yer systemd soket birimidir:
systemctl cat docker.socket
Çıktının içinde şu satırları görürsünüz:
[Socket]
ListenStream=/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
Buradan iki önemli sonuç çıkar. Birincisi: soket dosyası her servis başlangıcında systemd tarafından yeniden oluşturulur. Bu yüzden dosyanın izinlerini elle değiştirseniz bile ilk systemctl restart docker veya ilk sunucu yeniden başlatmasında değişikliğiniz silinir. chmod çözümünün "bir süre sonra yine bozuldu" diye geri gelmesinin nedeni budur. İkincisi: kalıcı ve doğru düzeltme, dosyanın iznini değil, kullanıcının grup üyeliğini değiştirmektir.
/var/run çoğu modern dağıtımda /run dizinine sembolik bağdır, bu yüzden iki yol da aynı dosyayı gösterir; ikisi arasında pratikte fark yoktur.
Doğru Çözüm: Kullanıcıyı docker Grubuna Ekleme#
Kalıcı çözüm tek satırdır:
sudo usermod -aG docker $USER
Komutun okunuşu: -a "append", yani ekle; -G ise ek grupları belirtir. -a bayrağını asla unutmayın. usermod -G docker kullanici yazarsanız kullanıcının diğer tüm ek grup üyelikleri (sudo, adm, www-data…) silinir ve yerine yalnızca docker yazılır. Bu, sudo yetkisini kaybedip sunucuda mahsur kalmanın en hızlı yoludur. Grup yönetiminin ayrıntıları için Linux kullanıcı ve grup yönetimi yazısına bakabilirsiniz.
Başka bir kullanıcı için:
sudo usermod -aG docker deploy
Grup henüz yoksa (elle derlenmiş kurulumlarda olabilir) önce oluşturun, sonra servisi yeniden başlatın:
sudo groupadd docker
sudo systemctl restart docker
Grup Değişikliği Neden Hemen Etkili Olmuyor?#
"Komutu çalıştırdım ama hata aynı" şikâyetinin neredeyse tamamının tek bir nedeni var: grup üyelikleri oturum açılırken belirlenir. Linux'ta bir sürecin grup listesi, o süreç başlatıldığı anda çekirdek tarafından hesaplanır ve süreç ömrü boyunca sabit kalır. usermod komutu /etc/group dosyasını günceller, ama açık olan SSH oturumunuzun çekirdek düzeyindeki grup listesine dokunamaz.
Doğrulaması basit:
id -nG # eski liste — docker yok
getent group docker # dosya güncel — kullanıcınız listede var
İki çıktının çelişmesi normaldir ve tam olarak bu durumu gösterir. Üç çözümden birini seçin:
- Oturumu kapatıp yeniden açın. En temizi budur. SSH'tan çıkın, tekrar bağlanın. Masaüstünde tam oturum kapatma gerekir; sadece terminal penceresini kapatmak yetmez.
newgrp docker— Mevcut terminalde, yeni grup listesiyle bir alt kabuk başlatır. Anında çalışır, ama etkisi yalnızca o kabukla sınırlıdır; yeni açtığınız ikinci pencerede yine eski liste geçerlidir.sg docker -c "docker ps"— Tek bir komutu yeni grupla çalıştırır. Betiklerde kullanışlıdır.
newgrp docker
docker ps # artık sudo'suz çalışmalı
Sunucuyu yeniden başlatmaya gerek yoktur; bunu öneren rehberler yalnızca oturum yenileme adımını farkında olmadan yaptırıyor.
"Gruba Ekledim Ama Hâlâ Permission Denied" Kontrol Listesi#
Oturumu tazelediğiniz hâlde hata sürüyorsa sırayla şu belirtileri kontrol edin:
| Belirti | Olası sebep | Doğrulama |
|---|---|---|
id -nG çıktısında docker yok | Oturum tazelenmemiş veya yanlış kullanıcıya eklenmiş | getent group docker ile üyeleri karşılaştırın |
Soketin grubu docker değil | Elle chown yapılmış veya özel systemd birimi | ls -l /run/docker.sock |
Cannot connect to the Docker daemon (izin değil, bağlantı) | Daemon çalışmıyor | systemctl status docker |
| Sudo ile çalışıyor, kullanıcıyla çalışmıyor ama grup doğru | Kabuk DOCKER_HOST ile başka sokete yönleniyor | echo $DOCKER_HOST, docker context ls |
| Rootless kurulumda çıkan izin hatası | Kullanıcı soketi yerine sistem soketi kullanılıyor | docker context use rootless |
docker context ayrıntısı özellikle Docker Desktop veya rootless kurulumdan sistem kurulumuna geçenlerde sık sorun çıkarır: ~/.docker/config.json içindeki bağlam ayarı komutu hiç var olmayan bir sokete yönlendirir ve hata mesajı yine izin gibi görünür.
Bir diğer sık senaryo, komutun sizin adınıza değil bir servis kullanıcısı adına çalışmasıdır. Örneğin bir CI runner, bir cron işi ya da www-data altında koşan bir PHP betiği docker çağırıyorsa, gruba eklenmesi gereken kullanıcı sizin hesabınız değil, o servis hesabıdır. Sunucuda birden çok kullanıcıyla çalışıyorsanız root yerine kullanıcı ile çalışma yazısındaki hesap ayrımı burada da geçerlidir.
Neden chmod 666 /var/run/docker.sock Yapmamalısınız?#
Arama sonuçlarının başında çıkan ve hatayı gerçekten susturan komut şu:
# BU KOMUTU ÇALIŞTIRMAYIN
sudo chmod 666 /var/run/docker.sock
Ne yaptığını açıkça yazalım: soketi herkese okuma ve yazma izniyle açar. Sonuç, sunucudaki her yerel kullanıcının ve bu kullanıcılar altında çalışan her sürecin Docker daemon'a komut verebilmesidir. Etkilenen taraf yalnızca insanlar değil: paylaşımlı bir sunucuda başka bir hesabın kabuğu ya da güvenlik açığı bulunan bir web uygulamasının PHP süreci de aynı yetkiyi kazanır.
Bunun neden root'a eşdeğer olduğunu gösteren komut tek satır:
docker run -v /:/host --rm -it alpine chroot /host sh
Bu komut host'un kök dizinini konteyner içine bağlar ve içine geçer. O andan itibaren /etc/shadow okunabilir, /etc/sudoers yazılabilir, authorized_keys dosyasına yeni bir SSH anahtarı eklenebilir. Yetki yükseltme için bir güvenlik açığı gerekmez; bu, Docker'ın tasarlandığı gibi çalışmasıdır.
Aynı yetkiye üç ayrı yoldan ulaşılabilir ve üçü de aynı sonucu verir:
chmod 666ile soketi herkese açmak,- kullanıcıyı
dockergrubuna eklemek, sudo dockerçalıştırma yetkisi vermek.
Fark, kaç kişinin bu kapıdan geçebildiğidir. chmod 666 kapıyı herkese açar; grup üyeliği yalnızca sizin seçtiğiniz kişilere açar. Üstelik chmod kalıcı bile değildir: bir önceki bölümde gördüğümüz gibi soket her servis yeniden başlatmasında systemd tarafından 0660 izinleriyle yeniden oluşturulur. Yani güvenliği bozar, sorunu ise ancak sonraki yeniden başlatmaya kadar çözer.
docker Grubu Pratikte root Yetkisidir#
Bu, yazının en önemli cümlesi: bir kullanıcıyı docker grubuna eklemek, ona parolasız root vermekle pratikte aynı şeydir. Docker'ın kendi belgelerinde de bu uyarı açıkça yer alır.
Sonuçları somutlaştıralım. docker grubundaki bir kullanıcı:
- Host'un tüm dosya sistemini bir konteynere mount edip okuyabilir ve yazabilir.
--privilegedile çekirdek yeteneklerinin tamamına sahip bir konteyner başlatabilir.--pid=host --net=hostile host süreçlerini ve ağını görebilir.- Bunları yaparken
sudogünlüklerinde görünmez; iz bırakan tek yer Docker'ın kendi olay kaydıdır.
Bu yüzden pratikte şu kurallar geçerlidir:
dockergrubuna yalnızca sunucuda zaten root yetkisine güvendiğiniz kişileri koyun. Bir geliştiriciye "sadece konteynerleri görebilsin" diye grup üyeliği vermek, aslında ona tam yetki vermektir.- Ortak kullanılan sunucularda üyeliği tek bir dağıtım (deploy) hesabıyla sınırlayın, kişisel hesapları içeri almayın.
- Müşteri hesabı barındıran paylaşımlı ortamlarda
dockergrubunu hiç kullanmayın; bu senaryoda doğru araç, kullanıcı başına izole edilmiş bir çalışma zamanıdır.
Üyeliği geri almanız gerekirse:
sudo gpasswd -d kullanici docker
Değişiklik yine ancak kullanıcının bir sonraki oturumunda etkili olur; açık oturumlar eski yetkiyle çalışmaya devam eder. Bu yüzden yetkiyi gerçekten kesmeniz gereken bir durumda kullanıcının açık oturumlarını da sonlandırın.
Alternatifler: sudo ile Çalıştırma ve Rootless Docker#
Tek kullanıcılı bir sunucuda docker grubu makul bir tercihtir; siz zaten root'sunuz. Ama başka senaryolar için iki alternatif var.
1. Gruba hiç girmeyip sudo docker kullanmak. Yetki aynı kalır ama her komut sudo günlüğüne düşer ve parola istenir. Denetim izi istediğiniz ortamlarda anlamlıdır. sudoers içinde belirli komutlara daraltmaya çalışmak ise yanıltıcıdır: sudo docker run yetkisi tek başına tam root demektir, dolayısıyla "sadece run komutuna izin verdim" gibi bir kısıtlama güvenlik sağlamaz. Kural yazarken sudo güvenli yapılandırma yazısındaki ilkeleri gözden geçirin.
2. Rootless Docker. Asıl çözüm budur. Daemon'u root yerine sizin kullanıcınız altında, user namespace içinde çalıştırır. Soket /run/user/1000/docker.sock altına düşer ve zaten yalnızca size aittir; dolayısıyla docker grubu diye bir şeye ihtiyaç kalmaz. Konteyner kaçışı yaşansa bile saldırganın eline geçen kimlik root değil, sizin normal kullanıcınız olur.
# Ubuntu/Debian: gerekli paket
sudo apt-get install -y uidmap
# Sistem genelindeki daemon'u kapat (isteğe bağlı ama önerilir)
sudo systemctl disable --now docker.service docker.socket
# Rootless kurulumu kullanıcı olarak çalıştırın (sudo ile DEĞİL)
dockerd-rootless-setuptool.sh install
# Oturum kapansa da servis çalışmaya devam etsin
sudo loginctl enable-linger $USER
# İstemciyi kullanıcı soketine yönlendir
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock
docker context use rootless
Rootless'ın bedeli de vardır: 1024 altındaki portları doğrudan dinleyemezsiniz (80/443 için net.ipv4.ip_unprivileged_port_start ayarı ya da bir ters proxy gerekir), bazı ağ ve depolama sürücüleri desteklenmez, ağ katmanında bir miktar performans kaybı olur. Benzer bir güvenlik yaklaşımını varsayılan olarak sunan bir alternatif arıyorsanız Podman ve Docker karşılaştırması yazısına bakabilirsiniz.
Hangi Yöntemi Seçmelisiniz?#
| Yöntem | Güvenlik | Kullanım kolaylığı | Uygun olduğu yer |
|---|---|---|---|
chmod 666 soket | Çok kötü — herkes root | Kolay | Hiçbir yer |
docker grubu | Zayıf — üyeler root'a eşdeğer | Çok kolay | Tek kullanıcılı kendi sunucunuz |
Her komutta sudo | Aynı yetki, denetim izi var | Orta | Ekipli sunucu, kayıt gereken ortam |
| Rootless Docker | İyi — daemon root değil | Kurulum gerektirir | Çok kullanıcılı, dışa açık sunucular |
Pratik öneri: kendi VDS'inizde tek başınıza çalışıyorsanız usermod -aG docker $USER yeterlidir ve kimseyi kandırmaz — zaten sudo yetkiniz var. Sunucuda sizden başka hesaplar varsa ya da uygulama süreçleri Docker'a erişecekse rootless kuruluma geçin. chmod 666 ise hiçbir senaryoda doğru cevap değil; hatayı çözüyormuş gibi görünüp yerine çok daha büyük bir sorun bırakır.
Son bir alışkanlık notu: bir konteyner çalıştırırken Docker soketini konteynerin içine bağlamak (-v /var/run/docker.sock:/var/run/docker.sock) da aynı yetkiyi o konteynere devreder. İzleme panelleri ve otomasyon araçları bunu sık ister; kabul etmeden önce o imaja host'un tamamını teslim ettiğinizi bilerek karar verin. Zorunluysa soketi salt okunur (:ro) bağlamak bir miktar yardımcı olur ama tam koruma sağlamaz; asıl güvenli yol araya bir soket proxy'si koymaktır.
Sıkça Sorulan Sorular#
usermod komutunu çalıştırdım ama hata devam ediyor, ne yapmalıyım?#
Grup üyelikleri oturum açıldığı anda belirlenir ve süreç ömrü boyunca değişmez. usermod dosyayı günceller ama açık SSH oturumunuzun grup listesine dokunamaz. SSH'tan çıkıp yeniden bağlanın; masaüstünde tam oturum kapatma gerekir. Hemen denemek isterseniz newgrp docker yazarak yeni grup listesine sahip bir alt kabuk açabilirsiniz. id -nG çıktısında docker göründüğü anda komut çalışır.
chmod 666 komutunu çalıştırdım, nasıl geri alırım?#
Doğru izinleri geri vermek için soketin iznini 660'a, sahipliğini root ve docker grubuna çevirin. Daha kısa yolu servisi yeniden başlatmaktır: systemd soketi 0660 ve root:docker olarak sıfırdan oluşturur. Soket açık kaldığı sürede sunucuya erişimi olan başka hesaplar varsa, yetkisiz bir konteyner çalıştırılmadığından emin olmak için Docker olay kaydını ve çalışan konteyner listesini gözden geçirin.
Docker'ı sudo olmadan kullanmak güvenli mi?#
Rahatlık açısından evet, güvenlik açısından hayır. docker grubundaki bir kullanıcı host dosya sistemini konteynere bağlayarak parolasız root yetkisi elde edebilir. Kendi tek kullanıcılı sunucunuzda bu bir kayıp değildir, çünkü zaten sudo yetkiniz vardır. Sunucuyu başkalarıyla paylaşıyorsanız veya web uygulamaları aynı makinede çalışıyorsa rootless Docker'a geçmek çok daha doğru bir tercihtir.
docker grubu sunucumda hiç yok, ne yapmalıyım?#
Bazı elle yapılan veya paket dışı kurulumlarda grup oluşturulmaz. Önce groupadd docker ile grubu açın, ardından Docker servisini yeniden başlatarak soketin yeni grupla oluşturulmasını sağlayın. Sonrasında soket satırında grup adının docker göründüğünü doğrulayın, sonra kullanıcınızı usermod -aG docker ile ekleyip oturumu yenileyin. Sıralamayı bozarsanız soket eski grupla kalır ve hata sürer.
Cannot connect to the Docker daemon hatası da aynı sorun mu?#
Hayır, bunlar farklı hatalardır. "Permission denied" soketin var olduğunu ama erişemediğinizi söyler. "Cannot connect to the Docker daemon" ise soketin hiç bulunamadığı, yani daemon'un çalışmadığı anlamına gelir. Servisin durumuna bakın, gerekirse başlatın ve servis günlüğünde bir başlangıç hatası olup olmadığını kontrol edin. İki hatayı karıştırmak, çalışmayan bir servis için boşuna izin ayarıyla uğraşmaya yol açar.
Cron veya CI betiğimde docker komutu izin hatası veriyor, sebebi ne?#
Bu betikler çoğunlukla sizin hesabınızla değil, kendi servis kullanıcılarıyla çalışır. Gruba eklenmesi gereken kullanıcı, komutu gerçekten çalıştıran hesaptır. Betiğin başına id -nG koyup hangi kullanıcı ve gruplarla koştuğunu görün. Ayrıca cron ortamının DOCKER_HOST gibi değişkenleri devralmadığını unutmayın; rootless kurulumda bu değişkeni betik içinde açıkça tanımlamanız gerekir.