🐳 Docker Kapsamlı Rehber (Comprehensive Docker Guide)
Full-stack geliştiriciler için pratik Docker referans rehberi. A practical Docker reference for full-stack developers (PHP/Laravel, Node.js, React, Python).
Ne zaman Docker kullanmaliyim?
✅ Kullan: Her proje için izole geliştirme ortami, CI/CD pipeline, mikroservis mimarisi, takim uyelerinin ayni ortamda calismasi gerektiginde
⚠️ Opsiyonel: Basit, tek servisli proje -- direkt calistirmak daha hızlı olabilir
❌ Gereksiz: Sadece statik site sunmak (Netlify/Vercel yeterli)
Önerilen araclar: Docker + Docker Compose
Alternatifler: Podman (daemonless, rootless), LXC/LXD (sistem container), nerdctl (containerd CLI)
🧱 Docker Temelleri
Container vs VM (Sanal Makine)
| Özellik | Container | Virtual Machine |
|---|---|---|
| Başlatma süresi | Saniyeler (seconds) | Dakikalar (minutes) |
| Boyut (Size) | MB seviyesinde | GB seviyesinde |
| Izolasyon | Process-level | Full OS-level |
| Kernel | Host kernel paylasilir (shared) | Kendi kernel'i var |
| Performans | Native'e yakin | Overhead var |
| Tasinabilirlik (Portability) | Cok yüksek | Orta |
💡 Container'lar uygulamayi ve bagimliklarini paketler ama OS kernel'ini host ile paylasir. Containers package the app and its dependencies but share the host OS kernel.
🔧 Kurulum (Installation)
Ubuntu / Debian
# 1. Eski sürümleri kaldır (remove old versions)
sudo apt-get remove docker docker-engine docker.io containerd runc 2>/dev/null
# 2. Gerekli paketleri kur (install prerequisites)
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
# 3. Docker'ın resmi GPG anahtarını ekle (add Docker's official GPG key)
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# 4. Docker repository'sini ekle (add Docker repository)
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
# 5. Docker Engine'i kur (install Docker Engine)
sudo apt-get update
sudo apt-get install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
# 6. Docker'ı sudo'suz kullan (run Docker without sudo)
sudo usermod -aG docker $USER
# Oturumu yeniden başlat (logout & login veya):
newgrp docker
# 7. Kurulumu doğrula (verify installation)
docker --version # Docker version 27.x.x
docker compose version # Docker Compose version v2.x.x
docker run hello-world # Test container çalıştırKurulum sonrası kontrol listesi (Post-install checklist):
# Docker servisi çalışıyor mu? (Is Docker service running?)
sudo systemctl status docker
# Otomatik başlatma (Start on boot)
sudo systemctl enable docker
sudo systemctl enable containerd
# Kullanıcı docker grubunda mı? (Is user in docker group?)
groups $USER # "docker" görünmeli
# Eğer "permission denied" hatası alıyorsan:
# 1. Logout/Login yap
# 2. Veya: newgrp docker
# 3. Veya: sudo chmod 666 /var/run/docker.sock (geçici çözüm)Sorun giderme (Troubleshooting):
| Sorun (Problem) | Çözüm (Solution) |
|---|---|
permission denied | sudo usermod -aG docker $USER + logout/login |
Cannot connect to Docker daemon | sudo systemctl start docker |
docker compose komutu yok | docker-compose-plugin paketini kur |
| GPG key hatası | /etc/apt/keyrings/docker.asc dosyasını sil ve tekrar ekle |
| Disk dolu | docker system prune -a ile temizle |
Windows
Docker Desktop (önerilen / recommended):
# 1. Önkoşul: WSL 2 kurulu olmalı (prerequisite: WSL 2)
wsl --install # WSL 2 + Ubuntu kur
wsl --set-default-version 2 # Varsayılan WSL sürümü
# 2. Docker Desktop indir ve kur
# https://www.docker.com/products/docker-desktop/
# veya winget ile:
winget install Docker.DockerDesktop
# 3. Kurulum sonrası bilgisayarı yeniden başlat (restart required)
# 4. Docker Desktop ayarları (Settings):
# ✅ General > Use WSL 2 based engine
# ✅ Resources > WSL Integration > Ubuntu aktif et
# 5. Doğrula (verify)
docker --version
docker compose version
docker run hello-worldDocker Desktop olmadan (WSL 2 içinde Docker Engine):
# WSL 2 Ubuntu terminalinde (inside WSL 2 Ubuntu):
# Yukarıdaki Ubuntu kurulum adımlarını aynen uygula
# Docker Desktop gerektirmez, ücretsiz ve hafifWindows Docker sorun giderme:
| Sorun | Çözüm |
|---|---|
| WSL 2 yok | wsl --install çalıştır, BIOS'ta Virtualization aktif et |
| Docker Desktop açılmıyor | Hyper-V ve WSL 2 aktif mi kontrol et |
| Port çakışması | netstat -ano | findstr :3306 ile hangi process kullanıyor bul |
| Yavaş performans | WSL 2 backend kullan, dosyaları WSL içinde tut (/home/ altında) |
macOS
# Yöntem 1: Docker Desktop (önerilen / recommended)
brew install --cask docker
# Docker Desktop uygulamasını aç ve "Start" butonuna bas
# Yöntem 2: Homebrew ile CLI only (Colima — hafif alternatif)
brew install docker docker-compose colima
colima start # Hafif VM başlat
docker run hello-world # Test et
# colima stop # Durdur
# Doğrula (verify)
docker --version
docker compose versionmacOS Docker sorun giderme:
| Sorun | Çözüm |
|---|---|
| Docker Desktop çok RAM kullanıyor | Settings > Resources > Memory limiti düşür veya Colima kullan |
docker: command not found | Docker Desktop çalışıyor mu kontrol et veya PATH'e ekle |
| Dosya paylaşımı yavaş | Settings > Resources > File sharing > VirtioFS kullan |
Docker Compose Kurulumu
Docker Compose artık Docker Engine ile birlikte geliyor (docker compose — tire yok). Eski docker-compose (tireli) ayrı kurulum gerektiriyordu.
# Yeni yol (v2 — plugin olarak gelir):
docker compose version # v2.x.x
# Eğer gelmiyorsa:
sudo apt-get install docker-compose-plugin
# Eski yol (v1 — artık önerilmiyor):
# sudo apt install docker-compose # ESKI, kullanma| Eski (v1) | Yeni (v2) |
|---|---|
docker-compose up | docker compose up |
docker-compose down | docker compose down |
docker-compose build | docker compose build |
| Ayrı binary | Docker plugin'i |
Kurulum Hızlı Referans (Quick Reference)
| Platform | Komut / Yöntem | Docker Compose |
|---|---|---|
| Ubuntu | apt (resmi repo) | Plugin olarak gelir |
| Windows | Docker Desktop veya WSL 2 | Desktop ile gelir |
| macOS | Docker Desktop veya Colima | Desktop/brew ile gelir |
| Arch Linux | sudo pacman -S docker docker-compose | Ayrı paket |
| Fedora | sudo dnf install docker-ce | Plugin olarak gelir |
📦 Temel Kavramlar (Core Concepts)
- Image: Uygulamanin read-only sablonu (blueprint). Dockerfile'dan olusturulur.
- Container: Image'den calistirilan instance. Yazilabilir katman (writable layer) eklenir.
- Dockerfile: Image olusturmak için talimat dosyasi (instruction file).
- Docker Compose: Birden fazla container'i tanimlayip yonetme araci (multi-container orchestration).
- Volume: Kalici veri saklama (persistent data storage).
- Network: Container'lar arasi iletisim (inter-container communication).
- Registry: Image'lerin depolandigi yer (Docker Hub, private registry).
⚡ Temel Komutlar
Container Yönetimi (Container Management)
| Komut | Açıklama (Description) | Örnek (Example) |
|---|---|---|
docker run | Yeni container oluştur ve çalıştır | docker run -d -p 8080:80 nginx |
docker ps | Calisan container'lari listele | docker ps -a (tumunu göster) |
docker stop | Container'i durdur | docker stop my_container |
docker start | Durmus container'i baslat | docker start my_container |
docker restart | Container'i yeniden baslat | docker restart my_container |
docker rm | Container'i sil | docker rm -f my_container |
docker exec | Calisan container'da komut çalıştır | docker exec -it app bash |
docker logs | Container loglarini göster | docker logs -f --tail 100 app |
docker inspect | Detayli bilgi al (JSON) | docker inspect my_container |
docker stats | Canli kaynak kullanimi | docker stats |
docker top | Container icindeki process'ler | docker top my_container |
docker cp | Dosya kopyala (host↔container) | docker cp app:/var/log/app.log . |
Image Yönetimi (Image Management)
| Komut | Açıklama | Örnek |
|---|---|---|
docker build | Dockerfile'dan image oluştur | docker build -t myapp:1.0 . |
docker images | Yerel image'leri listele | docker images |
docker pull | Registry'den image indir | docker pull node:20-alpine |
docker push | Registry'ye image yükle | docker push myuser/myapp:1.0 |
docker rmi | Image sil | docker rmi myapp:1.0 |
docker tag | Image'e tag ekle | docker tag myapp myuser/myapp:latest |
docker history | Image katmanlarini göster | docker history nginx |
Temizlik Komutları (Cleanup)
# Durmus container'lari sil (remove stopped containers)
docker container prune
# Kullanilmayan image'leri sil (remove dangling images)
docker image prune
# Kullanilmayan volume'lari sil (remove unused volumes)
docker volume prune
# Hepsini temizle (remove all unused data)
docker system prune -a --volumes
# Disk kullanimini goster (show disk usage)
docker system dfdocker run Önemli Flag'leri
# Arka planda calistir (detached mode)
docker run -d nginx
# Port yonlendirme (port mapping) — host:container
docker run -d -p 3000:3000 myapp
# Isim ver (name the container)
docker run -d --name my_nginx nginx
# Ortam degiskeni (environment variable)
docker run -d -e MYSQL_ROOT_PASSWORD=secret mysql:8
# Volume bagla (mount volume)
docker run -d -v mydata:/var/lib/mysql mysql:8
# Bind mount (host dizinini bagla)
docker run -d -v $(pwd)/src:/app/src myapp
# Otomatik yeniden baslat (restart policy)
docker run -d --restart unless-stopped nginx
# Bellek limiti (memory limit)
docker run -d --memory=512m myapp
# CPU limiti
docker run -d --cpus=1.5 myapp
# Ag belirt (specify network)
docker run -d --network my_network myapp
# Interaktif terminal (interactive shell)
docker run -it ubuntu bash
# Container kapandiginda sil (remove on exit)
docker run --rm -it alpine sh📄 Dockerfile
Temel Komutlar (Instructions)
# Base image sec (select base image)
FROM node:20-alpine
# Metadata ekle
LABEL maintainer="fahri@example.com"
LABEL description="My Node.js Application"
# Build-time arguman (build argument)
ARG NODE_ENV=production
ARG APP_VERSION=1.0.0
# Ortam degiskeni (environment variable — runtime'da da gecerli)
ENV NODE_ENV=${NODE_ENV}
ENV PORT=3000
# Calisma dizini (working directory)
WORKDIR /app
# Dosya kopyala (copy files)
COPY package*.json ./
# Komut calistir (run command — build sirasinda)
RUN npm ci --only=production
# Uygulama kodunu kopyala
COPY . .
# Port bildir (declare port — documentation amacli)
EXPOSE 3000
# Saglik kontrolu (health check)
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# Calistirma komutu (default command)
CMD ["node", "server.js"]FROM vs CMD vs ENTRYPOINT
# CMD — Varsayilan komut, docker run ile override edilebilir
CMD ["node", "server.js"]
# docker run myapp node other.js → other.js calisir
# ENTRYPOINT — Sabit komut, override edilmez (arguman eklenir)
ENTRYPOINT ["node"]
CMD ["server.js"]
# docker run myapp other.js → node other.js calisir
# Exec form (onerilen — recommended)
CMD ["node", "server.js"]
# Shell form (shell uzerinden calisir, signal handling sorunlu olabilir)
CMD node server.jsCOPY vs ADD
# COPY — Basit dosya kopyalama (tercih edin — preferred)
COPY . .
COPY --chown=node:node package.json ./
# ADD — Ekstra ozellikler: URL'den indirme, tar otomatik acma
ADD https://example.com/file.tar.gz /tmp/
ADD archive.tar.gz /app/
# ⚠️ Genelde COPY kullanin, ADD sadece tar acma gerektigindeRUN — Layer Optimizasyonu
# ❌ Kotu — Her RUN yeni layer olusturur (each RUN creates a new layer)
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y git
RUN rm -rf /var/lib/apt/lists/*
# ✅ Iyi — Tek layer, daha kucuk image
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
git \
&& rm -rf /var/lib/apt/lists/*.dockerignore
# Git
.git
.gitignore
# Dependencies
node_modules
vendor
# Environment
.env
.env.local
.env.*.local
# IDE
.vscode
.idea
*.swp
# OS
.DS_Store
Thumbs.db
# Build / Test
dist
build
coverage
*.log
# Docker
Dockerfile
docker-compose*.yml
.dockerignore🐙 Docker Compose
Temel Yapi (Basic Structure)
# docker-compose.yml
version: "3.8" # Compose file version (3.8+ onerilir)
services:
app:
build:
context: .
dockerfile: Dockerfile
args:
NODE_ENV: production
image: myapp:latest
container_name: myapp
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=db
env_file:
- .env
volumes:
- ./src:/app/src
- node_modules:/app/node_modules
depends_on:
db:
condition: service_healthy
networks:
- app-network
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
db:
image: mysql:8
container_name: mydb
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- db_data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- "3306:3306"
networks:
- app-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db_data:
driver: local
node_modules:
networks:
app-network:
driver: bridgeDocker Compose Komutları
# Tum servisleri baslat (start all services)
docker compose up -d
# Build edip baslat (build and start)
docker compose up -d --build
# Loglari takip et (follow logs)
docker compose logs -f app
# Belirli servisi yeniden baslat
docker compose restart app
# Servisleri durdur ve kaldir (stop and remove)
docker compose down
# Volume'larla birlikte kaldir (remove with volumes)
docker compose down -v
# Servis durumlarini goster
docker compose ps
# Belirli bir serviste komut calistir
docker compose exec app bash
# Tek seferlik komut calistir (one-off command)
docker compose run --rm app npm test
# Sadece belirli servisi baslat (start specific service)
docker compose up -d db
# Konfigurasyonu dogrula (validate config)
docker compose configdepends_on ve Servis Sirasi
services:
app:
depends_on:
db:
condition: service_healthy # DB saglikli olana kadar bekle
redis:
condition: service_started # Redis baslayana kadar bekle
migration:
condition: service_completed_successfully # Migration bitene kadar bekle
migration:
build: .
command: npm run migrate
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpineDocker Compose İleri Seviye
Profiles -- Ortama Gore Servis Secimi
Profiles ile bazi servisleri sadece belirli profillerde calistirabilirsiniz. Ornegin debug araçları sadece development ortaminda aktif olsun:
services:
app:
build: .
ports:
- "3000:3000"
# profil belirtilmezse her zaman calisir
db:
image: postgres:16
# profil belirtilmezse her zaman calisir
adminer:
image: adminer
ports:
- "8080:8080"
profiles:
- debug # sadece debug profili ile baslar
mailhog:
image: mailhog/mailhog
ports:
- "1025:1025"
- "8025:8025"
profiles:
- debug
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
profiles:
- monitoring # sadece monitoring profili ile baslar# Sadece profil-siz servisleri baslat
docker compose up -d
# debug profilindeki servisleri de baslat
docker compose --profile debug up -d
# birden fazla profil
docker compose --profile debug --profile monitoring up -dOverride Dosyalari
Docker Compose override dosyaları ile ortama ozel yapılandırma yapabilirsiniz. docker-compose.override.yml dosyasi otomatik olarak yuklenir:
# docker-compose.yml (base -- production)
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
restart: always# docker-compose.override.yml (otomatik yuklenir -- development)
services:
app:
build:
target: development
volumes:
- ./src:/app/src
environment:
- NODE_ENV=development
- DEBUG=true
command: npm run dev# development: base + override otomatik birlesir
docker compose up -d
# production: sadece base + prod dosyasini kullan
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# staging ortami
docker compose -f docker-compose.yml -f docker-compose.staging.yml up -denv_file ile Ortam Degiskeni Yönetimi
services:
app:
env_file:
- .env # varsayilan
- .env.local # yerel override (gitignore'da)
- .env.${ENV:-dev} # ortama gore: .env.dev, .env.prod
environment:
- APP_VERSION=1.0.0 # env_file'i override eder# .env dosyasi ornegi
DB_HOST=db
DB_PORT=5432
DB_NAME=myapp
DB_USER=postgres
DB_PASSWORD=secretYAML Anchor ve Alias (Tekrar Onleme)
Compose dosyalarinda tekrarlanan yapilandirmalari anchor/alias ile ortadan kaldirabilirsiniz:
# x- prefiksi ile extension field tanimla (Compose tarafindan ignore edilir)
x-common-env: &common-env
TZ: Europe/Istanbul
LANG: tr_TR.UTF-8
x-logging: &default-logging
driver: json-file
options:
max-size: "10m"
max-file: "3"
x-healthcheck-defaults: &healthcheck-defaults
interval: 30s
timeout: 10s
retries: 3
start_period: 15s
services:
app:
build: .
environment:
<<: *common-env # anchor'u kullan
NODE_ENV: production
logging: *default-logging # logging yapilandirmasi
healthcheck:
<<: *healthcheck-defaults
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
worker:
build: .
command: npm run worker
environment:
<<: *common-env # ayni env tekrar kullanilir
WORKER_CONCURRENCY: "4"
logging: *default-logging
scheduler:
build: .
command: npm run scheduler
environment:
<<: *common-env
logging: *default-logging💾 Volumes & Networking
Volume Turleri (Volume Types)
1. Named Volumes (Isimli Volume'lar)
# Volume olustur
docker volume create mydata
# Volume listesi
docker volume ls
# Volume detayi
docker volume inspect mydata
# Kullan
docker run -d -v mydata:/var/lib/mysql mysql:8# docker-compose.yml icinde
services:
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
driver: local💡 Named volume'lar Docker tarafindan yonetilir, container silinse bile veri kalir (data persists).
2. Bind Mounts (Host Dizin Baglama)
# Host dizinini container'a bagla
docker run -d -v /home/fahri/project/src:/app/src myapp
# Sadece okunabilir (read-only)
docker run -d -v $(pwd)/config:/app/config:ro myapp# docker-compose.yml — development icin ideal
services:
app:
volumes:
- ./src:/app/src # Kaynak kodu (source code)
- ./config:/app/config:ro # Sadece okunur (read-only)💡 Bind mount'lar development'ta hot-reload için cok kullanisli. Production'da named volume tercih edin.
3. tmpfs Mounts (Gecici Bellek)
# RAM'de gecici storage (temporary in-memory storage)
docker run -d --tmpfs /tmp:rw,size=100m myappVolume Karşılaştırma (Comparison)
| Özellik | Named Volume | Bind Mount | tmpfs |
|---|---|---|---|
| Konum (Location) | Docker yonetir | Host path belirtilir | RAM |
| Veri kaliciligi (Persistence) | Evet | Evet | Hayir |
| Backup kolayligi | Kolay | Kolay | Yok |
| Performans | Iyi | Host FS'ye bagli | En hızlı |
| Kullanım alani | Production data | Dev source code | Secrets, cache |
🌐 Networking
Network Turleri (Network Types)
| Tur | Açıklama | Kullanım |
|---|---|---|
bridge | Varsayilan, izole ag | Tek host uzerinde container iletisimi |
host | Host agini dogrudan kullan | Performans gerektiginde |
overlay | Birden fazla host arasi ag | Docker Swarm / cluster |
none | Ag baglantisi yok | Izole islemler |
macvlan | Container'a fiziksel MAC adresi | Legacy uygulamalar |
Network Komutları
# Ag olustur (create network)
docker network create my_network
# Belirli subnet ile olustur
docker network create --subnet=172.20.0.0/16 my_network
# Aglari listele
docker network ls
# Ag detayi (hangi container'lar bagli)
docker network inspect my_network
# Container'i aga bagla (connect)
docker network connect my_network my_container
# Container'i agdan cikar (disconnect)
docker network disconnect my_network my_container
# Agi sil
docker network rm my_networkPort Mapping (Port Yonlendirme)
# Tek port — host:container
docker run -d -p 8080:80 nginx
# Birden fazla port
docker run -d -p 8080:80 -p 8443:443 nginx
# Belirli IP'ye bagla (bind to specific IP)
docker run -d -p 127.0.0.1:8080:80 nginx
# Rastgele host port (random host port)
docker run -d -p 80 nginx
# docker ps ile hangi port atandigini gorebilirsin
# UDP port
docker run -d -p 53:53/udp dns-serverContainer'lar Arasi İletişim
# Ayni network'teki container'lar birbirini isimle cozumler (DNS resolution)
services:
app:
networks:
- backend
environment:
- DB_HOST=db # "db" servis adi hostname olarak kullanilir
- REDIS_HOST=redis
db:
image: mysql:8
networks:
- backend
redis:
image: redis:7-alpine
networks:
- backend
networks:
backend:
driver: bridgeCustom Network ve DNS Resolution
Ayni bridge network'teki container'lar Docker'in dahili DNS servisi sayesinde birbirini servis adiyla bulur. Farkli network'lerdeki container'lar birbirine erisemez (izolasyon):
services:
frontend:
build: ./frontend
networks:
- frontend-net
- backend-net # hem frontend hem backend aginda
api:
build: ./api
networks:
- backend-net # sadece backend aginda
- db-net
db:
image: postgres:16
networks:
- db-net # sadece db aginda -- frontend erisemez
networks:
frontend-net:
driver: bridge
backend-net:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
db-net:
driver: bridge
internal: true # dis dunyaya erisim yok# Container icinden DNS cozumlemesini test et
docker exec -it api ping db
docker exec -it api nslookup db
# Ayni network'teki container'lari gor
docker network inspect backend-net --format '{{range .Containers}}{{.Name}} {{end}}'🛠️ Pratik Ornekler
1. Laravel + MySQL + Redis + Nginx
Proje Yapisi
laravel-docker/
├── docker/
│ ├── nginx/
│ │ └── default.conf
│ └── php/
│ └── Dockerfile
├── src/ # Laravel kaynak kodu
├── docker-compose.yml
└── .envdocker-compose.yml
version: "3.8"
services:
# PHP-FPM (Laravel)
app:
build:
context: .
dockerfile: docker/php/Dockerfile
container_name: laravel_app
working_dir: /var/www/html
volumes:
- ./src:/var/www/html
- ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini
environment:
- DB_CONNECTION=mysql
- DB_HOST=db
- DB_PORT=3306
- DB_DATABASE=${DB_DATABASE:-laravel}
- DB_USERNAME=${DB_USERNAME:-laravel}
- DB_PASSWORD=${DB_PASSWORD:-secret}
- REDIS_HOST=redis
- REDIS_PORT=6379
- CACHE_DRIVER=redis
- SESSION_DRIVER=redis
- QUEUE_CONNECTION=redis
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
networks:
- laravel-network
# Nginx
nginx:
image: nginx:1.25-alpine
container_name: laravel_nginx
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
networks:
- laravel-network
# MySQL
db:
image: mysql:8
container_name: laravel_db
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-rootsecret}
MYSQL_DATABASE: ${DB_DATABASE:-laravel}
MYSQL_USER: ${DB_USERNAME:-laravel}
MYSQL_PASSWORD: ${DB_PASSWORD:-secret}
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
networks:
- laravel-network
# Redis
redis:
image: redis:7-alpine
container_name: laravel_redis
ports:
- "6379:6379"
volumes:
- redis_data:/data
command: redis-server --appendonly yes
networks:
- laravel-network
# Queue Worker
queue:
build:
context: .
dockerfile: docker/php/Dockerfile
container_name: laravel_queue
working_dir: /var/www/html
command: php artisan queue:work redis --sleep=3 --tries=3 --max-time=3600
volumes:
- ./src:/var/www/html
depends_on:
- app
- redis
networks:
- laravel-network
restart: unless-stopped
volumes:
mysql_data:
redis_data:
networks:
laravel-network:
driver: bridgedocker/php/Dockerfile
FROM php:8.3-fpm-alpine
# Sistem bagimliliklari (system dependencies)
RUN apk add --no-cache \
freetype-dev \
libjpeg-turbo-dev \
libpng-dev \
libzip-dev \
zip \
unzip \
git \
curl
# PHP eklentileri (extensions)
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) \
pdo_mysql \
gd \
zip \
bcmath \
opcache
# Redis eklentisi
RUN apk add --no-cache --virtual .build-deps $PHPIZE_DEPS \
&& pecl install redis \
&& docker-php-ext-enable redis \
&& apk del .build-deps
# Composer kur
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Calisma dizini
WORKDIR /var/www/html
# Kullanici olustur (non-root user)
RUN addgroup -g 1000 -S www && \
adduser -u 1000 -S www -G www
USER www
EXPOSE 9000
CMD ["php-fpm"]docker/nginx/default.conf
server {
listen 80;
server_name localhost;
root /var/www/html/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}2. Node.js/Express + MongoDB
# docker-compose.yml
version: "3.8"
services:
api:
build: .
container_name: express_api
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- MONGO_URI=mongodb://mongo:27017/myapp
- JWT_SECRET=${JWT_SECRET:-supersecretkey}
volumes:
- ./src:/app/src
- ./package.json:/app/package.json
depends_on:
mongo:
condition: service_healthy
networks:
- app-net
command: npm run dev
mongo:
image: mongo:7
container_name: mongodb
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER:-admin}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASS:-secret}
MONGO_INITDB_DATABASE: myapp
volumes:
- mongo_data:/data/db
- ./docker/mongo/init.js:/docker-entrypoint-initdb.d/init.js:ro
healthcheck:
test: echo 'db.runCommand("ping").ok' | mongosh --quiet
interval: 10s
timeout: 5s
retries: 5
networks:
- app-net
mongo-express:
image: mongo-express
container_name: mongo_ui
ports:
- "8081:8081"
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: ${MONGO_USER:-admin}
ME_CONFIG_MONGODB_ADMINPASSWORD: ${MONGO_PASS:-secret}
ME_CONFIG_MONGODB_URL: mongodb://${MONGO_USER:-admin}:${MONGO_PASS:-secret}@mongo:27017/
depends_on:
- mongo
networks:
- app-net
volumes:
mongo_data:
networks:
app-net:
driver: bridgeNode.js Dockerfile
FROM node:20-alpine
WORKDIR /app
# Bagimliliklari once kopyala (dependency caching)
COPY package*.json ./
RUN npm ci
# Uygulama kodunu kopyala
COPY . .
EXPOSE 3000
# Development modunda nodemon ile calistir
CMD ["npm", "run", "dev"]3. React Development Container
# docker-compose.yml
version: "3.8"
services:
react-app:
build:
context: .
dockerfile: Dockerfile.dev
container_name: react_dev
ports:
- "5173:5173" # Vite default port
volumes:
- ./src:/app/src
- ./public:/app/public
- ./index.html:/app/index.html
- ./vite.config.ts:/app/vite.config.ts
environment:
- VITE_API_URL=http://localhost:3000/api
- CHOKIDAR_USEPOLLING=true # Docker'da file watching icin
stdin_open: true
tty: trueDockerfile.dev
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 5173
# Vite dev server — host 0.0.0.0 Docker'da gerekli
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]4. Python Flask + PostgreSQL
# docker-compose.yml
version: "3.8"
services:
web:
build: .
container_name: flask_app
ports:
- "5000:5000"
environment:
- FLASK_APP=app.py
- FLASK_ENV=development
- DATABASE_URL=postgresql://postgres:secret@db:5432/flaskapp
- SECRET_KEY=${SECRET_KEY:-dev-secret-key}
volumes:
- ./app:/app/app
- ./migrations:/app/migrations
depends_on:
db:
condition: service_healthy
networks:
- flask-net
command: flask run --host=0.0.0.0 --debug
db:
image: postgres:16-alpine
container_name: flask_db
ports:
- "5432:5432"
environment:
POSTGRES_DB: flaskapp
POSTGRES_USER: postgres
POSTGRES_PASSWORD: secret
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
networks:
- flask-net
pgadmin:
image: dpage/pgadmin4
container_name: flask_pgadmin
ports:
- "5050:80"
environment:
PGADMIN_DEFAULT_EMAIL: admin@admin.com
PGADMIN_DEFAULT_PASSWORD: admin
depends_on:
- db
networks:
- flask-net
volumes:
pgdata:
networks:
flask-net:
driver: bridgeFlask Dockerfile
FROM python:3.12-slim
WORKDIR /app
# Sistem bagimliliklari
RUN apt-get update && \
apt-get install -y --no-install-recommends gcc libpq-dev && \
rm -rf /var/lib/apt/lists/*
# Python bagimliliklari (cache layer)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["flask", "run", "--host=0.0.0.0"]🏗️ Multi-Stage Builds
Multi-stage build ile development araclarini (compiler, dev dependencies) final image'dan cikararak cok daha küçük production image'lar olusturabilirsiniz. Use multi-stage builds to exclude dev tools from the final image, resulting in much smaller production images.
Node.js Production Dockerfile
# ============================================
# Stage 1: Dependencies (Bagimliliklar)
# ============================================
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# ============================================
# Stage 2: Build (Derleme)
# ============================================
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# ============================================
# Stage 3: Production (Final Image)
# ============================================
FROM node:20-alpine AS runner
WORKDIR /app
# Guvenlik: non-root kullanici
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 appuser
# Sadece gerekli dosyalari kopyala
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./package.json
USER appuser
EXPOSE 3000
ENV NODE_ENV=production
CMD ["node", "dist/server.js"]
# Final image boyutu: ~80MB (vs ~400MB tek stage ile)React Production Build (Nginx ile)
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Serve with Nginx
FROM nginx:1.25-alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# Final image boyutu: ~25MBLaravel Production Dockerfile
# ============================================
# Stage 1: Composer Dependencies
# ============================================
FROM composer:latest AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install \
--no-dev \
--no-scripts \
--no-autoloader \
--prefer-dist
COPY . .
RUN composer dump-autoload --optimize --no-dev
# ============================================
# Stage 2: Frontend Assets
# ============================================
FROM node:20-alpine AS frontend
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# ============================================
# Stage 3: Production Image
# ============================================
FROM php:8.3-fpm-alpine
RUN apk add --no-cache \
libpng-dev libjpeg-turbo-dev freetype-dev libzip-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install pdo_mysql gd zip bcmath opcache
# OPcache ayarlari
RUN echo "opcache.enable=1" >> /usr/local/etc/php/conf.d/opcache.ini && \
echo "opcache.memory_consumption=128" >> /usr/local/etc/php/conf.d/opcache.ini && \
echo "opcache.max_accelerated_files=10000" >> /usr/local/etc/php/conf.d/opcache.ini && \
echo "opcache.validate_timestamps=0" >> /usr/local/etc/php/conf.d/opcache.ini
WORKDIR /var/www/html
# Vendor ve frontend asset'lerini kopyala
COPY --from=vendor /app/vendor ./vendor
COPY --from=frontend /app/public/build ./public/build
# Uygulama kodunu kopyala
COPY . .
# Storage ve cache izinleri
RUN chown -R www-data:www-data storage bootstrap/cache && \
chmod -R 775 storage bootstrap/cache
# Cache olustur
RUN php artisan config:cache && \
php artisan route:cache && \
php artisan view:cache
USER www-data
EXPOSE 9000
CMD ["php-fpm"]Python Production Dockerfile
# Stage 1: Build
FROM python:3.12-slim AS builder
WORKDIR /app
RUN apt-get update && \
apt-get install -y --no-install-recommends gcc libpq-dev && \
rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
# Stage 2: Production
FROM python:3.12-slim
WORKDIR /app
RUN apt-get update && \
apt-get install -y --no-install-recommends libpq5 && \
rm -rf /var/lib/apt/lists/*
COPY --from=builder /install /usr/local
RUN useradd --create-home appuser
USER appuser
COPY . .
EXPOSE 5000
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "app:create_app()"]📦 Docker Registry
Docker Hub
# Giris yap (login)
docker login
# Kullanici adi ve sifre / access token sor
# Image'i tag'le (tag for push)
docker tag myapp:latest fahriaydin/myapp:1.0.0
docker tag myapp:latest fahriaydin/myapp:latest
# Push et (upload)
docker push fahriaydin/myapp:1.0.0
docker push fahriaydin/myapp:latest
# Pull et (download)
docker pull fahriaydin/myapp:1.0.0
# Docker Hub'da arama
docker search nginxPrivate Registry (Self-Hosted)
# Basit registry calistir
docker run -d -p 5000:5000 --name registry \
-v registry_data:/var/lib/registry \
registry:2
# Image'i private registry'ye push et
docker tag myapp:latest localhost:5000/myapp:1.0.0
docker push localhost:5000/myapp:1.0.0
# Baska bir makineden pull et
docker pull my-server.com:5000/myapp:1.0.0GitHub Container Registry (ghcr.io)
# GitHub token ile giris
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
# Push
docker tag myapp:latest ghcr.io/fahriaydin/myapp:1.0.0
docker push ghcr.io/fahriaydin/myapp:1.0.0Tag Stratejileri (Tagging Strategies)
# Semantic versioning (onerilen — recommended)
docker tag myapp fahriaydin/myapp:1.0.0
docker tag myapp fahriaydin/myapp:1.0
docker tag myapp fahriaydin/myapp:1
docker tag myapp fahriaydin/myapp:latest
# Git commit hash
docker tag myapp fahriaydin/myapp:$(git rev-parse --short HEAD)
# Tarih bazli (date-based)
docker tag myapp fahriaydin/myapp:$(date +%Y%m%d-%H%M%S)🏭 Production Best Practices
Base Image Secimi -- Karşılaştırma Tablosu
| Özellik | Alpine | Slim (Debian) | Distroless |
|---|---|---|---|
| Boyut | En küçük (~5MB base) | Orta (~80MB base) | Küçük (~20MB base) |
| Paket yoneticisi | apk | apt | Yok |
| Shell | ash (varsayılan) | bash | Yok |
| Güvenlik yuzey alani | Düşük | Orta | En düşük |
| Debug kolayligi | Orta | Iyi | Zor (shell yok) |
| glibc/musl | musl | glibc | glibc |
| Uyumluluk | Bazi native modullerde sorun | Genis uyumluluk | Sınırlı |
| Kullanım alani | Genel üretim | Native bağımlılık gerektiginde | Maksimum güvenlik |
# Alpine -- en yaygin tercih
FROM node:20-alpine # ~135MB
FROM python:3.12-alpine # ~50MB
# Slim -- glibc gerektiginde
FROM node:20-slim # ~200MB
FROM python:3.12-slim # ~125MB
# Distroless -- maksimum guvenlik
FROM gcr.io/distroless/nodejs20-debian12 # ~130MB
FROM gcr.io/distroless/python3-debian12 # ~50MBImage Boyut Kucultme Kontrol Listesi
- Multi-stage build kullan (dev araçları final image'da olmaz)
- Alpine veya slim base image seç
.dockerignoreile gereksiz dosyaları disla--no-install-recommends(apt) veya--no-cache(apk) kullan- Tek RUN komutunda birlestir ve gecici dosyaları temizle
npm ci --only=productionveyapip install --no-cache-dirkullan- COPY ile sadece gerekli dosyaları kopyala (
COPY . .yerine spesifik)
# Image boyutunu kontrol et
docker images myapp
docker history myapp:latest
# Dive ile katman analizi (opsiyonel arac)
# https://github.com/wagoodman/dive
dive myapp:latestLayer Caching Stratejisi
Dockerfile'da az degisen katmanlari uste, sik degisenleri alta yerlestirin:
FROM node:20-alpine
WORKDIR /app
## 1. Sistem bagimliliklari (nadiren degisir)
RUN apk add --no-cache curl
## 2. Paket dosyalari (ara sira degisir)
COPY package*.json ./
RUN npm ci --only=production
## 3. Uygulama kodu (sik degisir -- en alta)
COPY . .
CMD ["node", "server.js"]🩺 Health Check ve Monitoring
HEALTHCHECK Instruction
Dockerfile icinde HEALTHCHECK tanimlanarak Docker'in container sagligini otomatik kontrol etmesi saglanir:
# HTTP endpoint kontrolu
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# TCP port kontrolu (curl yoksa)
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD nc -z localhost 3000 || exit 1
# Veritabani kontrolu
HEALTHCHECK --interval=10s --timeout=5s --retries=5 \
CMD pg_isready -U postgres || exit 1
# Dosya bazli kontrol
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD test -f /tmp/healthy || exit 1HEALTHCHECK parametreleri:
| Parametre | Varsayilan | Açıklama |
|---|---|---|
--interval | 30s | Kontroller arasi bekleme süresi |
--timeout | 30s | Tek bir kontrol için maksimum sure |
--start-period | 0s | Baslangic bekleme süresi (bu surede basarisizlik sayilmaz) |
--retries | 3 | Kac basarisiz denemeden sonra unhealthy sayilacagi |
# Container saglik durumunu kontrol et
docker inspect --format='{{.State.Health.Status}}' my_container
# Saglik kontrolu gecmisini gor
docker inspect --format='{{json .State.Health}}' my_container | jqRestart Policies
| Policy | Açıklama | Kullanım |
|---|---|---|
no | Yeniden başlatma (varsayılan) | Test / gecici container'lar |
on-failure | Sadece hata ile ciktiginda yeniden baslat | Batch isler |
on-failure:5 | Maksimum 5 deneme ile yeniden baslat | Sınırlı yeniden deneme |
always | Her zaman yeniden baslat (manuel stop haric) | Kritik servisler |
unless-stopped | always gibi ama Docker daemon yeniden basladiginda durmus kalir | Genel production |
# docker-compose.yml
services:
app:
restart: unless-stopped # onerilen production ayari
worker:
restart: on-failure
deploy:
restart_policy:
condition: on-failure
max_attempts: 5
delay: 10s
window: 60sResource Limits (Kaynak Sinirlandirma)
services:
app:
deploy:
resources:
limits:
cpus: "2.0" # maksimum 2 CPU
memory: 512M # maksimum 512MB RAM
reservations:
cpus: "0.5" # garanti 0.5 CPU
memory: 256M # garanti 256MB RAM# Komut satirindan kaynak sinirlandirma
docker run -d \
--memory=512m \
--memory-swap=1g \
--cpus=1.5 \
--pids-limit=100 \
myapp
# Canli kaynak kullanimini izle
docker stats
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}"Docker Logs ve Log Drivers
# Temel log komutlari
docker logs my_container # Tum loglar
docker logs -f my_container # Canli takip
docker logs --tail 50 my_container # Son 50 satir
docker logs --since 1h my_container # Son 1 saat
docker logs --since 2024-01-01T00:00:00 my_container # Belirli tarihten itibaren
docker logs -f --until 10m my_container # Son 10 dakikaya kadarDesteklenen log driver'lar:
| Driver | Açıklama | Kullanım |
|---|---|---|
json-file | Varsayilan, JSON formatinda dosyaya yazar | Genel kullanım |
local | Optimize edilmis yerel depolama | json-file alternatifi |
syslog | Syslog daemon'a gonderir | Linux sunucular |
journald | systemd journal'a gonderir | systemd tabanli sunucular |
fluentd | Fluentd collector'a gonderir | Merkezi loglama |
awslogs | Amazon CloudWatch'a gonderir | AWS ortami |
gcplogs | Google Cloud Logging'e gonderir | GCP ortami |
none | Log tutmaz | Hassas veri işleme |
# docker-compose.yml -- log yapilandirmasi
services:
app:
logging:
driver: json-file
options:
max-size: "10m" # dosya basina max boyut
max-file: "5" # max dosya sayisi
compress: "true" # eski dosyalari sikistir
tag: "{{.Name}}/{{.ID}}"🔐 Güvenlik
Non-Root Kullanici
Container'lari root olarak calistirmak güvenlik riski olusturur. Her zaman non-root kullanici kullanin:
# Alpine
RUN addgroup --system --gid 1001 appgroup && \
adduser --system --uid 1001 --ingroup appgroup appuser
# Debian/Ubuntu
RUN groupadd --system --gid 1001 appgroup && \
useradd --system --uid 1001 --gid appgroup --create-home appuser
# Dosya sahipligini ayarla
COPY --chown=appuser:appgroup . .
WORKDIR /app
RUN chown -R appuser:appgroup /app
USER appuserImage Tarama (Vulnerability Scanning)
# Docker Scout (Docker Desktop ile gelir)
docker scout cves myapp:latest
docker scout quickview myapp:latest
# Trivy (acik kaynak, kapsamli)
trivy image myapp:latest
trivy image --severity HIGH,CRITICAL myapp:latest
trivy image --exit-code 1 myapp:latest # CI/CD'de basarisiz yap
# Snyk
snyk container test myapp:latest
snyk container monitor myapp:latest # surekli izleme# CI/CD pipeline icinde tarama ornegi (GitHub Actions)
# .github/workflows/scan.yml
# - name: Trivy scan
# uses: aquasecurity/trivy-action@master
# with:
# image-ref: myapp:latest
# severity: HIGH,CRITICAL
# exit-code: 1Docker Secrets
# Swarm mode'da secret olustur
echo "my-secret-password" | docker secret create db_password -
docker secret create ssl_cert ./cert.pem
# Serviste kullan
docker service create \
--secret db_password \
--secret ssl_cert \
myapp# docker-compose.yml ile secrets (Swarm veya Compose v2)
services:
app:
secrets:
- db_password
- api_key
environment:
DB_PASSWORD_FILE: /run/secrets/db_password
secrets:
db_password:
file: ./secrets/db_password.txt # development
api_key:
external: true # production (onceden olusturulmus)Read-Only Filesystem
services:
app:
read_only: true # root filesystem read-only
tmpfs:
- /tmp # gecici dosyalar icin yazilabilir alan
- /var/run # PID dosyalari icin
volumes:
- app_data:/app/data # sadece gerekli dizinler yazilabilirGüvenlik Sertlestirme
services:
app:
security_opt:
- no-new-privileges:true # privilege escalation onle
cap_drop:
- ALL # tum Linux capability'leri kaldir
cap_add:
- NET_BIND_SERVICE # sadece gerekli olanlari ekle
read_only: true
tmpfs:
- /tmp# Docker Content Trust -- image imzalama
export DOCKER_CONTENT_TRUST=1
docker push myapp:latest # otomatik imzalar
docker pull myapp:latest # imzali degilse reddeder
# Container'i guvenlik opsiyonlariyla calistir
docker run -d \
--read-only \
--security-opt no-new-privileges:true \
--cap-drop ALL \
--cap-add NET_BIND_SERVICE \
--tmpfs /tmp:rw,noexec,nosuid \
--user 1001:1001 \
myappLinux Capabilities Referansi
| Capability | Açıklama | Gerekli mi? |
|---|---|---|
NET_BIND_SERVICE | 1024 altindaki portlara bind | Web sunuculari |
CHOWN | Dosya sahipligi değiştirme | Nadiren |
SETUID/SETGID | Kullanici/grup değiştirme | Nadiren |
SYS_PTRACE | Process trace (debug) | Sadece debug |
NET_RAW | Raw socket (ping vb.) | Nadiren |
MKNOD | Ozel dosya oluşturma | Hayir |
Genel kural: cap_drop: ALL ile başla, sadece gereklileri cap_add ile ekle.
🔍 Debugging & Best Practices
Debugging Teknikleri
# Container'a baglan (attach to running container)
docker exec -it my_container bash
docker exec -it my_container sh # Alpine image'larda sh kullan
# Loglari incele (inspect logs)
docker logs my_container # Tum loglar
docker logs -f my_container # Canli takip (follow)
docker logs --tail 50 my_container # Son 50 satir
docker logs --since 1h my_container # Son 1 saat
# Container event'lerini izle
docker events
# Container process'lerini goster
docker top my_container
# Kaynak kullanimini izle (resource monitoring)
docker stats
docker stats my_container --no-stream # Tek seferlik snapshot
# Container dosya sistemini incele
docker diff my_container # Degisen dosyalari goster
# Cikis kodunu kontrol et (check exit code)
docker inspect my_container --format='{{.State.ExitCode}}'
# Network sorunlarini debug et
docker exec -it my_container ping db
docker exec -it my_container nslookup db
docker exec -it my_container curl -v http://api:3000/health
# Image katmanlarini incele
docker history myapp:latest
docker inspect myapp:latest
# Build sirasinda debug (build debug)
docker build --no-cache -t myapp . 2>&1 | tee build.log
docker build --progress=plain -t myapp .Sik Karsilasilan Sorunlar (Common Issues)
# "port is already allocated"
# Cozum: Portu kullanan process'i bul ve durdur
sudo lsof -i :8080
docker ps -a | grep 8080
docker stop <container_id>
# "no space left on device"
# Cozum: Docker temizligi
docker system prune -a --volumes
docker builder prune
# Container hemen kapaniyor (exits immediately)
# Cozum: Loglari kontrol et
docker logs my_container
# veya interaktif calistir
docker run -it myapp bash
# "permission denied" — Volume sorunlari
# Cozum: Dosya sahipligini kontrol et
docker exec -it my_container ls -la /app
# Dockerfile'da: RUN chown -R appuser:appuser /app
# Container'lar birbirini bulamiyor (DNS resolution)
# Cozum: Ayni network'te olduklarini kontrol et
docker network inspect my_networkBest Practices
1. Küçük Base Image Kullan (Use Small Base Images)
# Buyuk — ~900MB
FROM node:20
# Kucuk — ~130MB
FROM node:20-alpine
# Daha da kucuk (gerektiginde) — ~80MB
FROM node:20-slim2. Layer Cache'i Optimize Et
# Kotu — Her kod degisikliginde npm install tekrar calisir
COPY . .
RUN npm ci
# Iyi — package.json degismezse cache kullanilir
COPY package*.json ./
RUN npm ci
COPY . .3. Non-Root Kullanici (Security)
# Kullanici olustur ve gec
RUN addgroup --system --gid 1001 appgroup && \
adduser --system --uid 1001 --ingroup appgroup appuser
# Dosya sahipligini ayarla
COPY --chown=appuser:appgroup . .
USER appuser4. Saglik Kontrolu Ekle (Health Check)
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 15. .dockerignore Kullan
Her zaman .dockerignore dosyasi oluştur (always create one). Build context boyutunu kucultur, build suresini azaltir.
6. Secrets Yönetimi (Secret Management)
# Kotu — Secret image layer'ina yazilir
ENV API_KEY=my-secret-key
COPY .env /app/.env
# Iyi — Runtime'da environment variable olarak ver
# docker run -e API_KEY=my-secret-key myapp
# Docker secrets (Swarm mode)
# docker secret create my_secret ./secret.txt# docker-compose.yml ile environment
services:
app:
env_file:
- .env # .env dosyasi .gitignore'da olmali
environment:
- API_KEY # Host'taki env variable'i gecir7. Log Yönetimi (Log Management)
# Log driver ayarla (set log driver)
docker run -d --log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
myapp
# Container log boyutunu kontrol et
docker inspect --format='{{.LogPath}}' my_container
du -sh $(docker inspect --format='{{.LogPath}}' my_container)# docker-compose.yml — tum servisler icin log limiti
services:
app:
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"8. Image Boyut Optimizasyonu (Image Size Optimization)
## 1. Multi-stage build kullan (yukaridaki orneklere bak)
## 2. Gereksiz dosyalari temizle
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
## 3. Tek RUN komutu ile birlestir (combine into single RUN)
RUN apk add --no-cache curl && \
curl -o /tmp/file.tar.gz https://example.com/file.tar.gz && \
tar xzf /tmp/file.tar.gz -C /app && \
rm /tmp/file.tar.gz
## 4. COPY ile sadece gerekli dosyalari kopyala
COPY package*.json ./
COPY src/ ./src/
COPY public/ ./public/
# COPY . . yerine spesifik kopyalama
## 5. --no-cache-dir flag'ini kullan (Python)
RUN pip install --no-cache-dir -r requirements.txt
## 6. npm ci --only=production (Node.js)
RUN npm ci --only=production📋 Sik Kullanilan Komutlar Tablosu (Quick Reference)
Container Islemleri
| Komut | Açıklama |
|---|---|
docker run -d -p 80:80 --name web nginx | Nginx container baslat |
docker ps | Calisan container'lari göster |
docker ps -a | Tüm container'lari göster |
docker stop web | Container'i durdur |
docker start web | Container'i baslat |
docker restart web | Yeniden baslat |
docker rm -f web | Container'i zorla sil |
docker exec -it web bash | Container'a baglan |
docker logs -f web | Loglari takip et |
docker cp web:/etc/nginx/nginx.conf . | Dosya kopyala |
docker stats | Kaynak kullanimini göster |
Image Islemleri
| Komut | Açıklama |
|---|---|
docker build -t myapp:1.0 . | Image oluştur |
docker images | Image listesi |
docker pull node:20-alpine | Image indir |
docker push user/myapp:1.0 | Image yükle |
docker rmi myapp:1.0 | Image sil |
docker tag myapp user/myapp:latest | Image tag'le |
docker save -o backup.tar myapp | Image'i dosyaya kaydet |
docker load -i backup.tar | Dosyadan image yükle |
Docker Compose
| Komut | Açıklama |
|---|---|
docker compose up -d | Servisleri baslat |
docker compose up -d --build | Build edip baslat |
docker compose down | Servisleri durdur ve kaldir |
docker compose down -v | Volume'larla birlikte kaldir |
docker compose ps | Servis durumlari |
docker compose logs -f | Tüm loglar |
docker compose logs -f app | Belirli servis loglari |
docker compose exec app bash | Servise baglan |
docker compose run --rm app npm test | Tek seferlik komut |
docker compose pull | Image'leri güncelle |
docker compose config | Config doğrula |
Volume & Network
| Komut | Açıklama |
|---|---|
docker volume ls | Volume listesi |
docker volume create mydata | Volume oluştur |
docker volume inspect mydata | Volume detayi |
docker volume rm mydata | Volume sil |
docker volume prune | Kullanilmayan volume'lari sil |
docker network ls | Network listesi |
docker network create mynet | Network oluştur |
docker network inspect mynet | Network detayi |
docker network connect mynet web | Container'i aga bagla |
docker network rm mynet | Network sil |
Temizlik & Bakim
| Komut | Açıklama |
|---|---|
docker system df | Disk kullanimini göster |
docker system prune | Kullanilmayan her seyi sil |
docker system prune -a --volumes | Agresif temizlik |
docker container prune | Durmus container'lari sil |
docker image prune -a | Kullanilmayan image'leri sil |
docker builder prune | Build cache temizle |
💡 Tips ve İpuçları
docker system prune -- Kapsamli Temizlik
# Kullanilmayan container, network, image (dangling) temizle
docker system prune
# Tum kullanilmayan image'ler + volume'lar dahil
docker system prune -a --volumes
# Sadece 24 saatten eski olanlari temizle
docker system prune -a --filter "until=24h"
# Ne kadar alan kullanildigini gor
docker system df
docker system df -v # detayliBuildx ile Multi-Platform Build
Tek Dockerfile'dan farkli mimariler için image oluşturma:
# Buildx builder olustur
docker buildx create --name multiarch --use
# AMD64 + ARM64 icin build ve push
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t myuser/myapp:latest \
--push .
# Desteklenen platformlari listele
docker buildx ls
# Belirli platform icin yerel build
docker buildx build --platform linux/arm64 -t myapp:arm64 --load ..env Dosyasi Yönetimi
# .env.example olustur (git'e ekle -- sablonu paylas)
# DB_HOST=localhost
# DB_PORT=5432
# DB_PASSWORD= # bos birak, herkes kendi degerini girer
# .env dosyasini .env.example'dan olustur
cp .env.example .env
# .env dosyasini .gitignore'a ekle
echo ".env" >> .gitignore
echo ".env.local" >> .gitignore
echo ".env.*.local" >> .gitignore# docker-compose.yml -- varsayilan deger belirle
services:
app:
environment:
- DB_HOST=${DB_HOST:-localhost}
- DB_PORT=${DB_PORT:-5432}
- NODE_ENV=${NODE_ENV:-development}Container Debug -- exec Kullanimi
# Container icine shell ile gir
docker exec -it my_container bash # Debian/Ubuntu
docker exec -it my_container sh # Alpine
docker exec -it my_container /bin/ash # Bazi Alpine image'lar
# Belirli kullanici ile gir
docker exec -it --user root my_container bash
# Ortam degiskeni ile komut calistir
docker exec -it -e DEBUG=true my_container node debug.js
# Calisan process'leri gor
docker exec my_container ps aux
# Disk kullanimini kontrol et
docker exec my_container df -h
# Network durumunu kontrol et
docker exec my_container cat /etc/hosts
docker exec my_container netstat -tlnp
# Dosya icerigini kontrol et (container icinde)
docker exec my_container cat /app/config.jsonLayer Caching Sirasi
Dockerfile'da satirlarin sirasi cache performansini dogrudan etkiler. Genel kural: az degisenden cok degisene doğru siralama yapin:
FROM node:20-alpine
WORKDIR /app
## 1. Sistem bagimliliklari (neredeyse hic degismez)
RUN apk add --no-cache curl tini
## 2. Paket tanimlari (haftada bir degisir)
COPY package.json package-lock.json ./
## 3. Bagimlilik kurulumu (paket dosyasi degistiginde)
RUN npm ci --only=production
## 4. Yapilandirma dosyalari (ara sira degisir)
COPY tsconfig.json ./
COPY .env.example ./
## 5. Uygulama kodu (her commit'te degisir)
COPY src/ ./src/
## 6. Build (kod degistiginde)
RUN npm run build
ENTRYPOINT ["tini", "--"]
CMD ["node", "dist/server.js"]Bu rehber duzenli olarak guncellenecektir. Onerileriniz için issue acabilirsiniz.
This guide is updated regularly. Feel free to open issues for suggestions.
Ilgili Rehberler
DevOps & Tools
- DevOps Genel Bakış
- Git Notlari
- Kubernetes
- Nginx Rehberi
- Linux CLI
- Deployment & Hosting
- Ubuntu Rehberi
- VS Code Rehberi
- Regex Rehberi