SSD Nodes Learn Hosting plans →
Rehberler Matt ConnorYazan Matt Connor

Ubuntu 24.04 VPS için Docker Compose kurulumu

Ubuntu 24.04 üzerinde Docker Engine ve Compose eklentisini kurun; Miniflux ile PostgreSQL yığınını çalıştırın, ufw port tuzağından kaçının ve volume yedekleyin.

Ne kuruluyor

Docker Compose, bu sitedeki diğer yapıların neredeyse tamamının temelini oluşturur. Nextcloud, Vaultwarden, n8n, Immich, Rocket.Chat; bu kılavuzların her biri "bu compose dosyasını yazın" ifadesiyle başlar. Bu sayfada ise söz konusu dosyanın gerçekte ne anlama geldiği açıklanır. Ubuntu 24.04 üzerinde Docker Engine ve Compose eklentisi, Docker'ın kendi apt deposundan kurulacaktır. Ardından iki servisten oluşan gerçek bir yığın çalıştırılacaktır: küçük bir RSS okuyucu olan Miniflux ve PostgreSQL. Bu ikili, daha büyük uygulamalarda kullanılan tüm kalıpları gösterir: sabitlenmiş imajlar, healthcheck tanımlı bir veritabanı, adlandırılmış bir volume, bir .env dosyasında tutulan secrets ve yalnızca localhost'a yayınlanan bir port.

Kurulum beş dakika sürer. Kılavuzun geri kalanında daha sonra sorun çıkaran noktalar ele alınır: docker grubunun farklı bir adla root yetkisi vermesi, yayınlanan portların ufw kurallarını doğrudan aşması ve docker compose down üzerindeki, onay istemeden veritabanınızı silen tek flag.

Ön koşullar: yeni kurulmuş bir Ubuntu 24.04 KVM VPS, sudo yetkisine sahip bir kullanıcı ve en az 1 gigabyte RAM. Mevcut bir Docker kurulumu da kullanılabilir; ilk bölümde kaldırılması gereken bileşenler açıklanır.

Docker deposundan yükleme yapılmalı, Ubuntu deposundan değil

İlk komuttan önce iki yanlış seçeneği elemek gerekir. Ubuntu'nun kendi docker.io paketi çalışır, ancak Docker sürümlerinin gerisinde kalır ve diğer bileşenlerin varsaydığı eklenti düzenini içermez. Tireli docker-compose komutu ise eski eğitimlerin yönlendirdiği yoldur. Eski bir sunucuda bu komut genellikle Python ile yazılmış Compose v1 sürümünü çalıştırır. Docker bu sürümü kullanım ömrü sona ermiş olarak ilan etmiştir. Eski eğitimlerin çalışmamasının nedeni de budur. Docker hâlâ güncel Go kodundan derlenen bağımsız bir docker-compose ikili dosyası yayımlar. Ancak kendi kurulum sayfası bu yöntemi önerilmez olarak belirtir ve yalnızca geriye dönük uyumluluk için destekler. Güncel Compose, arada boşluk bulunan docker compose biçimindedir. Bu, engine ile aynı depodan kurulan bir CLI eklentisidir.

Bunlardan herhangi biri sistemde zaten varsa, docker-compose-v2 ve docker-buildx dahil olmak üzere önce kaldırılmalıdır. Bunlar Ubuntu'nun eklentiler için sağladığı paketlerdir. Böylece tüm bileşenler tek bir depodan gelir:

sudo apt remove -y docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc

Package 'docker.io' is not installed, so not removed, yeni bir VPS üzerinde normal çıktıdır. Ardından Docker deposu eklenmeli ve kurulum yapılmalıdır:

sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Üç katmanın tümü doğrulanmalıdır:

docker --version
docker compose version
sudo docker run --rm hello-world

İlk iki komut sürüm dizelerini yazdırır. Docker Compose version v5.x.x ise kullanım ömrü sona ermiş v1 ikili dosyası yerine eklentinin bulunduğunu doğrular. Eklenti, eski compose dosyası biçimi sürümleriyle karışıklığı önlemek için 3 ve 4 sürümlerini atlayarak Aralık 2025'te v2 sürümünden doğrudan v5 sürümüne geçti. Bu nedenle burada v2.x.x gösteren kılavuzlar aynı aracı açıklar. hello-world komutunun çıktısı Hello from Docker! ile bitmelidir. Paket, servisin boot sırasında etkinleşmesini sağlar; systemctl is-enabled docker çıktısı enabled olur.

docker grubu root yetkisindedir, sonuçlarını bilerek karar verin

Şu anda her docker komutu sudo gerektirir, çünkü /var/run/docker.sock adresindeki daemon soketinin sahibi root kullanıcısı ve docker grubudur. Bu gruba dahil değilseniz, Docker ile ilgili en çok aranan şu hatayı alırsınız:

permission denied while trying to connect to the Docker daemon socket at
unix:///var/run/docker.sock

Standart çözüm şudur:

sudo usermod -aG docker $USER

Grup üyeliği oturum açma sırasında geçerli olur, bu nedenle hata mevcut kabuğunuzda devam edecektir. Bu oturum için newgrp docker komutunu çalıştırın veya oturumu kapatıp tekrar açın; id komutu artık gruplarınız arasında docker değerini listelemelidir.

Şimdi dürüst olma vakti: docker grubuna üye olmak, ana makinede root yetkisine sahip olmak demektir. "Root benzeri" veya "yükseltilmiş" değil, doğrudan root. Bu gruptaki herkes docker run --rm -it -v /:/host alpine chroot /host komutunu çalıştırabilir ve parola sormaksızın tüm dosya sisteminin sahibi olabilir. Bu grup güvenlik için değil, kolaylık sağlamak için vardır.

Docker'ın rootless modu gerçek bir alternatiftir; daemon doğrudan sizin yetkisiz kullanıcınızla çalışır. Bunun bazı maliyetleri vardır: 1024 altındaki portlar ek yapılandırma gerektirir, ağ trafiği ölçülebilir bir ek yük getiren bir kullanıcı alanı katmanı üzerinden akar ve bazı imajlar gerçek root yetkisi olmadan düzgün çalışmaz. Tek bir yöneticinin bulunduğu ve zaten sudo yetkisine sahip olduğu bir VPS üzerinde, bu grup değişikliği pratikte hiçbir şeyi değiştirmez ve buradaki tüm rehberler bunu varsayar; ancak bu yetkiyi asla sudo'dan daha az önemliymiş gibi dağıtmayın.

Compose dosyasının yapısı

Her stack için ayrı bir dizin kullanın. Dizin adı proje adı olur ve container, network ve volume adlarının başına eklenir:

sudo mkdir -p /opt/miniflux && sudo chown $USER /opt/miniflux && cd /opt/miniflux

compose.yml dosyasını oluşturun (güncel ad budur; docker-compose.yml hâlâ çalışır). Eski version: anahtarını kullanmayın. Bu anahtar artık geçersizdir ve Compose bulunduğunda uyarı verir.

services:
  miniflux:
    image: miniflux/miniflux:2.2.9
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:8080"
    environment:
      - DATABASE_URL=postgres://miniflux:${POSTGRES_PASSWORD}@db/miniflux?sslmode=disable
      - RUN_MIGRATIONS=1
      - CREATE_ADMIN=1
      - ADMIN_USERNAME=admin
      - ADMIN_PASSWORD=${ADMIN_PASSWORD}
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      - POSTGRES_USER=miniflux
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - POSTGRES_DB=miniflux
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "miniflux", "-d", "miniflux"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  db-data:

Yukarıdaki her satır bir karardır. Kararları tek tek ele alın.

Image sürümlerini sabitleyin; :latest ve pull işlemi otomatik yükseltme anlamına gelir

postgres:16-alpine kullanın, postgres:latest kullanmayın. Tag sabit değildir: :latest her pull işleminde, maintainer'ın en son gönderdiği sürüme yeniden çözümlenir. Bunu birazdan öğreneceğiniz düzenli yükseltme alışkanlığı olan docker compose pull && docker compose up -d ile birleştirdiğinizde :latest, major sürüm geçişlerinin sizin seçtiğiniz zamanda değil, upstream tarafından yayımlandıkları anda gerçekleşmesi anlamına gelir. PostgreSQL için bu yalnızca teorik bir risk değildir: 16'dan 17'ye beklenmedik bir geçiş, uyumsuz bir data directory nedeniyle container'ın sürekli yeniden başlatılmasına yol açar. Çünkü Postgres major yükseltmeleri yeniden başlatma değil, dump ve restore işlemi gerektirir.

En azından major sürümü sabitleyin (postgres:16-alpine, 16.x patch sürümlerini izler). Uygulamaları miniflux/miniflux:2.2.9 gibi tam bir release sürümüne sabitleyin. Projenin releases sayfasını kontrol edin ve dosyayı yazdığınız sırada geçerli olan sürümü kullanın. Böylece yükseltme, bilinçli olarak yaptığınız ve git diff içinde görülebilen tek satırlık bir düzenlemeye dönüşür.

Docker ufw kurallarını atladığı için 127.0.0.1'e publish edin

"127.0.0.1:8080:8080", host adresi, host portu ve container portudur. Çoğu tutorial "8080:8080" yazar. Bu, 0.0.0.0:8080:8080 ifadesinin kısa biçimidir ve public arayüz dahil tüm arayüzlerde dinleme yapılacağı anlamına gelir.

Buradaki sorun hemen herkesin en az bir kez karşısına çıkar. Docker, paketin hedefini filtreleme işleminden önce container'ın dahili IP adresine yeniden yazan bir DNAT kuralı oluşturarak port publish eder. Böylece paket FORWARD yolunu izler ve ufw kurallarınızın bulunduğu INPUT katmanına hiç ulaşmaz. sudo ufw deny 8080 başarılı olduğunu bildirir, ufw status portun reddedildiğini gösterir, ancak servis yine de tüm internete yanıt verir. Güvenlik duvarınız bozuk değildir; tasarım gereği devre dışı bırakılmıştır. Docker'ın ufw'yi neden aştığını ve container trafiğinin gerçekte nasıl filtreleneceğini başlıklı bölüm mekanizmayı ve public kalması gereken portlar için DOCKER-USER çözümünü açıklar.

Sorunu tamamen ortadan kaldıran alışkanlık şudur: özel bir nedeniniz olmadıkça publish edilen portları 127.0.0.1 adresine bind edin. Dünyaya açılması gereken servislerin önüne reverse proxy koyun. Bu sayfanın ardından gelen Traefik reverse proxy kılavuzu tam olarak bu yapıyı kurar: 80 ve 443 portlarının sahibi olan tek bir container, TLS kullanarak hostname üzerinden diğer tüm servislere yönlendirme yapar. Eski bir Traefik v2 kurulumundan mı geçiyorsunuz? Traefik v2'den v3'e geçiş kılavuzu ad değişikliklerini ve kural değişikliklerini açıklar.

Stack'i başlattıktan sonra bind işlemini doğrulayın: sudo ss -tlnp | grep 8080 çıktısında 127.0.0.1:8080 görünmelidir; 0.0.0.0:8080 veya *:8080 görünmemelidir.

Named volume ve bind mount karşılaştırması

db-data:/var/lib/postgresql/data bir named volume'dur. Docker, /var/lib/docker/volumes/ altında bir dizin oluşturur ve yönetir; bu dizin container içine mount edilir. Diğer seçenek, host üzerinde seçtiğiniz bir yolu eşleyen bind mount olan ./data:/var/lib/postgresql/data işlemidir.

Pratikte geçerli olan ayrım şöyledir: Yalnızca container'ların eriştiği veriler için named volume kullanın. Özellikle veritabanlarında bu tercih edilmelidir. Docker, volume'u image'ın beklediği sahiplikle başlatır ve dosya izinleri genellikle sorunsuz çalışır. Host üzerinden erişeceğiniz dosyalar için bind mount kullanın. Metin düzenleyiciyle değiştirdiğiniz config dosyaları, rsync ile kopyaladığınız media library ve yolunun açıkça görünmesini istediğiniz diğer dosyalar buna dahildir. Bind mount kullanımındaki klasik sorun sahipliktir: image, işlemini sabit bir UID ile çalıştırır (Miniflux image'ı UID 65534 ile çalışır, postgres:16-alpine ise UID 70'e düşer), host üzerindeki dizin UID 1000'e aittir ve uygulama başlangıçta permission denied mesajını log'larına yazarak durur. Named volume kullanımı, verilerin aşağıda açıklanan Docker tarafından yönetilen bir yolda tutulması karşılığında bu tür sorunları büyük ölçüde ortadan kaldırır.

environment ve .env; secret bilgileri git dışında tutun

Compose, compose.yml dosyasının yanında bulunan .env adlı dosyadan ${POSTGRES_PASSWORD} değerlerini doldurur. Ancak shell zaten ilgili değişkeni tanımlamışsa bu işlem yapılmaz: shell ortamında export edilen değer, .env dosyasındaki değere üstün gelir. Önceki bir denemeden kalan export POSTGRES_PASSWORD=... bu nedenle dosyadaki değeri sessizce geçersiz kılabilir. docker compose config (aşağıda) hangi değerin kullanıldığını gösterir. Dosyayı oluşturun:

cat > .env <<'EOF'
POSTGRES_PASSWORD=change-me-to-something-long
ADMIN_PASSWORD=change-me-too
EOF
chmod 600 .env
echo ".env" >> .gitignore

Gerçek değerleri openssl rand -hex 24 ile üretin. Bilinçli olarak base64 yerine hex kullanın. Bu parola DATABASE_URL connection string içinde yer alır ve base64 tarafından üretilen /, + ve = karakterleri URL ayrıştırmasını bozabilir. Hata syntax error olarak değil, authentication error olarak ortaya çıkar ve saatlerce sorun giderme gerektirebilir. .gitignore satırını ilk commit'ten önce ekleyin: compose dosyası publish edilip version control altında tutulabilir, ancak .env dosyası tutulmamalıdır. Git geçmişine girmiş bir secret rotate edilmelidir. Stack'i bir değişken eksikken başlatırsanız Compose yüksek öncelikli bir uyarı verir ve boş string ile devam eder. Postgres parolası için bu durum bozuk bir deployment anlamına gelir:

WARN[0000] The "POSTGRES_PASSWORD" variable is not set. Defaulting to a blank string.

docker compose config, fully interpolated dosyayı yazdırır. Bu, container'ların gerçekte hangi değerleri alacağını kontrol etmenin en hızlı yoludur. Çıktının secret bilgilerinizi içerdiğini unutmayın.

depends_on healthcheck eklenmediği sürece hiçbir şeyi beklemez

Basit bir depends_on: [db] yalnızca başlatma sırasını belirler: Compose önce Postgres'i başlatır, ardından uygulamayı başlatır. Ancak Postgres bağlantıları kabul etmeye başlamadan önce birkaç saniye geçebilir. Uygulama veritabanına bağlanmayı dener, başarısız olur ve ne kadar iyi yazıldığına bağlı olarak çöker veya yeniden deneme yapar.

Güvenilir yöntem, yukarıdaki dosyada kullanılan yöntemdir: db servisi bir healthcheck tanımlar (Postgres bunun için pg_isready sağlar) ve uygulama depends_on ile birlikte condition: service_healthy tanımlar. Compose veritabanını başlatır, kontrolü her 10 saniyede bir sorgular ve Miniflux'ı yalnızca kontrol başarılı olduktan sonra başlatır. Veritabanı sağlıklı duruma hiç geçmezse, örneğin parola hatalıysa veya volume bozuksa, uygulama başlatılmaz ve Compose hangi dependency'nin başarısız olduğunu bildirir:

dependency failed to start: container miniflux-db-1 is unhealthy

Bu mesaj sizi gerçek hatanın bulunduğu docker compose logs db konumuna yönlendirir.

restart: unless-stopped

Her iki serviste restart: unless-stopped kullanılması, container'ların crash sonrasında ve VPS yeniden başlatıldıktan sonra tekrar çalışmasını sağlar. Ancak docker compose stop komutunu bilerek çalıştırdıysanız container'lar durur. Alternatif olan always, manuel olarak durdurulan container'ları bile yeniden başlatır; bu genellikle istenen davranış değildir. Restart policy kullanılmazsa kernel güncellemesi sonrasında saat 4'te gerçekleşen reboot, siz fark edene kadar servislerin sessizce durmasına yol açar.

Günlük işlemler

Günlük tüm işlemler, proje dizininden çalıştırılan beş komuttan ibarettir.

docker compose up -d        # create and start; idempotent, recreates only what changed
docker compose ps           # status, ports, and health of this project's containers
docker compose logs -f miniflux   # follow one service's logs; --tail 100 for recent history
docker compose pull && docker compose up -d   # upgrade to the pinned tags
docker compose down         # stop and remove containers and the network

up -d komutunu tekrar tekrar çalıştırmak güvenlidir; dosya ile mevcut durum arasındaki farkı karşılaştırır ve yalnızca yapılandırması veya imajı değişen servisleri etkiler. Yükseltme çifti, sabitlenmiş etiketlerinizin (pinned tags) işaret ettiği sürümleri çeker: postgres:16-alpine altındaki yama sürümleri güncellenir, ancak siz düzenlemediğiniz sürece tam sürüm sabitlemeleri değişmez; zaten amaç da budur. Yükseltmelerden sonra eski imajlar birikir; disk alanını geri kazanmak için docker image prune -f kullanın.

Şimdi yıkıcı olan komuta gelelim, yüksek sesle belirtmek gerekir: docker compose down komutunu çalıştırmak güvenlidir; container'lar ve ağ yapısı geçicidir, verileriniz ise volume içinde tutulur. docker compose down -v komutu adlandırılmış volume'leri de siler. Bu, veritabanınızın anında ve geri dönüşü olmaksızın, herhangi bir onay istemeden silinmesi demektir. -v bayrağı, denemeleri temizlemek için mevcuttur; gerçek verilerin bulunduğu bir yığında, bu komuta rm -rf komutuna yaklaştığınız gibi yaklaşın. /var/lib/docker/volumes/ altında bir çöp kutusu bulunmaz.

Çalışan bir container içinde tek seferlik bir kabuk (shell) oturumu açmak için: docker compose exec db psql -U miniflux sizi veritabanına, docker compose exec miniflux sh ise uygulama içinde bir kabuğa ulaştırır.

Verilerinizin gerçekte nerede saklandığı

Named volume'lar proje öneki alır; bu nedenle db-data, miniflux adlı bir dizin içinde miniflux_db-data haline gelir:

docker volume ls
docker volume inspect miniflux_db-data

inspect çıktısı, önemli olan satırı içerir:

"Mountpoint": "/var/lib/docker/volumes/miniflux_db-data/_data"

Bu dizin veritabanıdır, ana makine dosya sisteminde root sahipliğindedir ve down, yükseltmeler ve container yeniden oluşturma işlemlerinden sonra varlığını korur. Ayrıca yedeklerinizin mutlaka alması gereken veriler tam olarak bunlardır.

Named volume yedekleme

Standart yöntem, birimi salt okunur olarak bir ana makine dizinine bağlayan ve içeriği tar ile arşivleyen geçici bir container kullanmaktır:

docker run --rm \
  -v miniflux_db-data:/data:ro \
  -v "$PWD":/backup \
  alpine:3.22 tar czf /backup/miniflux-db-$(date +%F).tar.gz -C /data .

Kurulum gerektirmez, arka planda çalışan bir süreç bırakmaz. Geri yükleme işlemi ise bunun tam tersidir; tar xzf komutu ile aynı bağlama noktaları tersine çevrilerek boş bir birime aktarım yapılır.

Veritabanları için önemli bir uyarı: çalışan bir Postgres veri dizinini tar ile arşivlemek, yazma işlemi sırasında tutarsız bir durum oluşturabilir ve veritabanının düzgün başlamasını engelleyebilir. Arşivleme süresince docker compose stop komutunu kullanın veya daha iyisi, yapısı gereği tutarlı olan mantıksal bir döküm (logical dump) alın:

docker compose exec -T db pg_dump -U miniflux miniflux | gzip > miniflux-$(date +%F).sql.gz

-T bayrağı, Compose tarafından varsayılan olarak atanan sözde terminali (pseudo-terminal) devre dışı bırakır; döküm çıktısını bir TTY üzerinden aktarmak veriyi bozabilir. Bu komutlardan birini cron içine ekleyin ve sonucu VPS dışına kopyalayın; verinin bulunduğu diskle aynı diskte tutulan bir kopya, yedek değil yalnızca bir kopyadır. Nextcloud rehberi, tam olarak bu iki yöntemi temel alan planlı bir yedekleme rutini oluşturur.

Hata durumları ve görülecek dizeler

permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock, henüz docker grubunda değilsiniz veya gruba eklenmeden önce başlatılmış bir oturum kullanıyorsunuz. id etkin gruplarınızı gösterir; newgrp docker mevcut shell'i düzeltir, oturumu kapatıp yeniden açmak ise tüm grup üyeliklerini yeniler.

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?, farklı bir sorun var: daemon'ın kendisi çalışmıyor. sudo systemctl status docker ve sudo journalctl -u docker -n 50 bunun nedenini gösterir. VPS üzerinde klasik neden diskin tamamen dolmasıdır; önce df -h /var/lib/docker çalıştırılmalıdır.

Bind for 127.0.0.1:8080 failed: port is already allocated, başka bir container bu host portunu zaten yayınlamıştır. docker ps hangi container olduğunu gösterir; haftalar önce yapılan deneysel bir docker run işleminden kalan stale container genellikle sorunun nedenidir. docker ps temizse portu Docker dışındaki bir süreç kullanıyordur: sudo ss -tlnp | grep 8080 bu sürecin adını gösterir.

yaml: line 14: did not find expected key, adı belirtilen satırda veya hemen üzerinde bir girinti hatası olduğunu gösterir. Compose dosyaları YAML biçimindedir: iki boşluklu girinti kullanılmalı, yalnızca boşluk karakterleri kullanılmalı ve herhangi bir yerde tab karakteri bulunmamalıdır; aksi durumda işlem başarısız olur. docker compose config dosyayı hiçbir şeyi başlatmadan doğrular; her düzenlemeden sonra çalıştırılması düşük maliyetli bir alışkanlıktır.

ufw sürprizi hiç hata yazdırmaz; bunu tehlikeli yapan da budur: deploy başarılı olur, ufw status doğru görünür ve dışarıdan yapılan bir port taraması veritabanınıza yine de ulaşır. Yukarıdaki portlar bölümünü yeniden okuyun, her ports: girdisinde 127.0.0.1: ön ekinin eksik olup olmadığını kontrol edin ve farklı bir makineden curl http://your-vps-ip:8080 ile doğrulama yapın; almak istediğiniz yanıt connection refused olmalıdır.

Buradan Traefik kılavuzu, bu tek stack'i tek bir HTTPS giriş noktası arkasında birden fazla uygulamaya dönüştürür. 2026'da self-host etmeye değer uygulamalar ise bu yapı üzerinden çalıştırılacak uygulama listesini sunar. Bu stack'lerden birkaçını çalıştırdığınızda ve her biri kendi login formunu oluşturduğunda, Authentik gibi self-host edilen bir SSO server, aynı proxy'nin arkasındaki tek bir hesapta bunları yeniden birleştirir.

VPS üzerinde Minecraft server gibi bir game server, pratik yapmak için uygun bir ilk Compose projesidir. Her gün açacağınız bir şey üzerinde öğrenmeyi tercih ediyorsanız self-host edilen bir workout tracker olan openGym, image tag yerine git tag'e sabitlenmiş küçük bir stack'tir ve ilk passkey'i kaydetmeden önce önünde TLS bulunmasını ister. Fotoğraflar, insanların genellikle başka birinin cloud ortamından geri almak istediği ilk veridir; PhotoPrism ve Immich karşılaştırması, bir volume'ü bunlardan birine tahsis etmeden önce kabul edeceğiniz RAM tabanını ve backup rutinini netleştirir. İki servis yetersiz gelmeye başladığında Notion tarzı bir workspace olarak AFFiNE kurulumu, dört container'da aynı kalıpları uygular ve yukarıdaki sabitlenmiş tag'lerin, healthcheck'lerin ve named volume'lerin alışkanlığa dönüşüp dönüşmediğini adil biçimde test eder.

FAQ

"permission denied while trying to connect to the Docker daemon socket" hatasını neden alıyorum?

Kullanıcınız docker grubunda değildir veya mevcut oturum başladıktan sonra gruba eklenmiştir. Grup üyeliği yalnızca oturum açıldığında uygulanır. sudo usermod -aG docker $USER komutunu, ardından newgrp docker komutunu çalıştırın veya oturumu kapatıp yeniden açın. Üyeliği id ile doğrulayın. Bu grup, host üzerinde root ile eşdeğer erişim sağlar. Bu nedenle yalnızca sudo yetkisi vereceğiniz kullanıcıları ekleyin.

docker compose down verilerimi siler mi?

Standart docker compose down komutu verileri silmez. Container'ları ve proje ağını kaldırır. Named volume'lar korunur ve sonraki up -d çalıştırıldığında yeniden bağlanır. docker compose down -v yıkıcı seçenektir. Named volume'ları siler. Bu, veritabanınızın da silineceği ve işlem için onay alınmayacağı anlamına gelir. Geri alma imkanı yoktur. Doğrulanmış bir yedeğiniz yoksa gerçek veri içeren bir stack üzerinde -v komutunu çalıştırmayın.

docker-compose ile docker compose arasındaki fark nedir?

docker-compose (tireli biçim), Compose'u çağırmanın eski yöntemidir. Eski sunucularda bu genellikle Docker'ın kullanım ömrünün sona erdiğini belirttiği, Python ile yazılmış özgün Compose v1 sürümüdür. Docker, güncel Go kodundan oluşturulan bağımsız bir docker-compose binary'sini de yayımlar. Ancak bu kurulumun önerilmediğini ve yalnızca geriye dönük uyumluluk için desteklendiğini belirtir. Bu nedenle yeni sunucularda kullanılmamalıdır. docker compose (boşluklu biçim), güncel Compose sürümüdür. Compose v2 ve sonraki sürümlerden itibaren kullanılır ve Aralık 2025'ten beri v5 olarak numaralandırılır. Docker CLI için bir Go plugin'idir ve Docker'ın apt repository'sinden docker-compose-plugin olarak kurulur. Komutlar ve YAML dosyaları neredeyse tamamen uyumludur. Eski bir tutorial docker-compose up diyorsa docker compose up yazın.

ufw portu engellemesine rağmen Docker container'ıma internetten neden erişebiliyorum?

Docker, portları iptables içindeki PREROUTING chain'inde DNAT kurallarıyla yayımlar. Yeniden yazılan paketler Docker'ın kendi chain'leri üzerinden FORWARD yolunu izlediği için ufw kurallarının uygulandığı INPUT chain'ine ulaşmaz. Bu nedenle ufw deny 8080, yayımlanmış bir container portu üzerinde etkili olmaz. Sorunu kaynağında çözün: 127.0.0.1: adresine publish edin ve servislere bunun yerine bir reverse proxy üzerinden erişim sağlayın.

Named volume mu, bind mount mu kullanılmalı?

Yalnızca container'ın kullandığı veriler için, özellikle veritabanlarında, named volume kullanılmalıdır. Docker, image'ın beklediği sahipliği ayarlar ve izinler doğrudan çalışır. Host üzerinden de yöneteceğiniz dosyalar için bind mount kullanılmalıdır. Buna düzenlediğiniz config dosyaları, yüklediğiniz medya dosyaları ve yolunu açıkça belirlemek istediğiniz diğer dosyalar dahildir. Bir container, bind mount üzerinde permission denied hatasıyla başlangıçta başarısız olursa ilk olarak host ile container arasındaki UID uyuşmazlığı kontrol edilmelidir.