# Docker: Geliştirmeden Üretime > Uygulamaları konteynerleştirmek için eksiksiz Docker rehberi. Dockerfile, Docker Compose, multi-stage build ve üretim ortamına dağıtım pratik örneklerle açıklanıyor. - Published: 2026-01-21 - Updated: 2026-04-10 - Author: SharpSkill - Tags: docker, containerization, devops, docker compose, deployment - Reading time: 18 min --- Docker, uygulamaların geliştirilme, test edilme ve dağıtılma şeklini kökten değiştirmektedir. Bir uygulamayı ve bağımlılıklarını taşınabilir bir konteyner içinde kapsülleyerek Docker, meşhur "benim makinemde çalışıyor" sorununu ortadan kaldırır ve tüm ortamlarda tutarlılık sağlar. Bu rehber, ilk Dockerfile'dan üretim ortamına dağıtıma kadar tam yolculuğu kapsamaktadır. > **2026'da Docker** > > Docker Desktop 5.x, yerel containerd desteği, optimize edilmiş kaynak yönetimi ve sorunsuz Kubernetes entegrasyonu dahil önemli performans iyileştirmeleri getirmektedir. Çoklu mimari imajlar (ARM/x86) artık standart uygulama haline gelmiştir. ## Konteynerleştirme Temelleri Bir konteyner, kod, çalışma zamanı, sistem kütüphaneleri ve ayarları paketleyen hafif bir yazılım birimidir. Donanımı sanallaştıran sanal makinelerin aksine, konteynerler ana bilgisayar çekirdeğini paylaşır ve bu da onları daha hızlı başlatılabilir ve daha az kaynak tüketir hale getirir. ```bash # terminal # Docker installation on Ubuntu sudo apt update sudo apt install -y docker.io # Add user to docker group (avoids sudo) sudo usermod -aG docker $USER # Verify installation docker --version # Docker version 26.1.0, build 1234567 # First container: downloads image and runs docker run hello-world ``` Bu komut Docker Hub'dan `hello-world` imajını indirir ve bir onay mesajı görüntüleyen bir konteyner başlatır. ```bash # terminal # List running containers docker ps # List all containers (including stopped) docker ps -a # List downloaded images docker images # Remove a container docker rm # Remove an image docker rmi ``` Bu temel komutlar konteynerlerin ve imajların yaşam döngüsünü yönetir. ## İlk Dockerfile'ın Oluşturulması Bir Dockerfile, Docker imajı oluşturmak için talimatlar içerir. Her talimat son imajda bir katman oluşturur ve böylece önbelleğe alma ve yeniden kullanım mümkün olur. ```dockerfile # Dockerfile # Base image: Node.js 22 on Alpine Linux (lightweight) FROM node:22-alpine # Set working directory in the container WORKDIR /app # Copy dependency files first (cache optimization) COPY package*.json ./ # Install dependencies RUN npm ci --only=production # Copy source code COPY . . # Expose port (documentation) EXPOSE 3000 # Startup command CMD ["node", "server.js"] ``` Talimatların sırası önbellek optimizasyonu için kritik öneme sahiptir. Nadiren değişen dosyalar (package.json) kaynak koddan önce kopyalanmalıdır. ```bash # terminal # Build image with a tag docker build -t my-app:1.0 . # Run the container docker run -d -p 3000:3000 --name my-app-container my-app:1.0 # Check logs docker logs my-app-container # Access container shell docker exec -it my-app-container sh ``` `-d` bayrağı konteyneri arka planda çalıştırır, `-p` konteynerin 3000 portunu ana bilgisayarın 3000 portuna eşler. > **Alpine vs Debian** > > Alpine imajları önemli ölçüde daha küçüktür (Debian için yaklaşık 120 MB'ye karşı 5 MB). Ancak glibc yerine musl libc kullanırlar ve bu bazı yerel bağımlılıklarla uyumsuzluklara neden olabilir. Sorun yaşandığında Debian tabanlı imajların (node:22-slim) tercih edilmesi önerilir. ## Üretim İçin Multi-stage Build Multi-stage build'ler, derleme ortamını çalışma zamanı ortamından ayırarak optimize edilmiş üretim imajları oluşturur. Son imaja yalnızca gerekli bileşenler dahil edilir. ```dockerfile # Dockerfile.production # ============================================ # Stage 1: Build # ============================================ FROM node:22-alpine AS builder WORKDIR /app # Copy and install dependencies (including devDependencies) COPY package*.json ./ RUN npm ci # Copy source code COPY . . # Build the application (TypeScript, bundling, etc.) RUN npm run build # ============================================ # Stage 2: Production # ============================================ FROM node:22-alpine AS production # Non-root user for security RUN addgroup -g 1001 -S nodejs && \ adduser -S nodejs -u 1001 WORKDIR /app # Copy only necessary files from builder stage COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/package.json ./ # Switch to non-root user USER nodejs # Environment variables ENV NODE_ENV=production ENV PORT=3000 EXPOSE 3000 # Startup command CMD ["node", "dist/server.js"] ``` Bu yaklaşım, derleme araçlarını, devDependencies ve kaynak dosyalarını hariç tutarak son imaj boyutunu önemli ölçüde azaltır. ```bash # terminal # Build with specific file docker build -f Dockerfile.production -t my-app:production . # Compare image sizes docker images | grep my-app # my-app production abc123 150MB # my-app 1.0 def456 450MB ``` Boyut azaltma projeye bağlı olarak %60-70'e ulaşabilir ve bu da dağıtım sürelerini iyileştirirken saldırı yüzeyini azaltır. ## Yerel Orkestrasyon İçin Docker Compose Docker Compose, çok konteynerli uygulama yönetimini basitleştirir. Bir YAML dosyası tüm servisleri, yapılandırmalarını ve bağımlılıklarını bildirir. ```yaml # docker-compose.yml version: "3.9" services: # Main application app: build: context: . dockerfile: Dockerfile ports: - "3000:3000" environment: - NODE_ENV=development - DATABASE_URL=postgresql://postgres:secret@db:5432/myapp - REDIS_URL=redis://cache:6379 volumes: # Mount source code for hot-reload - ./src:/app/src - ./package.json:/app/package.json depends_on: db: condition: service_healthy cache: condition: service_started networks: - app-network # PostgreSQL database db: image: postgres:16-alpine environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: secret POSTGRES_DB: myapp volumes: # Data persistence - postgres_data:/var/lib/postgresql/data # Initialization script - ./init.sql:/docker-entrypoint-initdb.d/init.sql ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 networks: - app-network # Redis cache cache: image: redis:7-alpine ports: - "6379:6379" volumes: - redis_data:/data command: redis-server --appendonly yes networks: - app-network # Named volumes for persistence volumes: postgres_data: redis_data: # Dedicated network for isolation networks: app-network: driver: bridge ``` Servisler, dahili Docker ağı üzerinden adlarıyla (db, cache) iletişim kurar. Healthcheck'ler, uygulama başlamadan önce bağımlılıkların hazır olmasını sağlar. ```bash # terminal # Start all services docker compose up -d # View logs from all services docker compose logs -f # Logs from a specific service docker compose logs -f app # Stop and remove containers docker compose down # Removal including volumes (caution: data loss) docker compose down -v # Rebuild after Dockerfile changes docker compose up -d --build ``` ## Gizli Bilgi ve Ortam Değişkeni Yönetimi Gizli bilgilerin güvenli yönetimi üretim ortamında kritik öneme sahiptir. Docker, bağlama göre farklı yaklaşımlar sunar. ```yaml # docker-compose.override.yml (development only) version: "3.9" services: app: env_file: - .env.development environment: - DEBUG=true ``` Üretim ortamı için Docker secrets daha yüksek güvenlik sağlar. ```yaml # docker-compose.production.yml version: "3.9" services: app: build: context: . dockerfile: Dockerfile.production secrets: - db_password - api_key environment: - NODE_ENV=production - DATABASE_PASSWORD_FILE=/run/secrets/db_password - API_KEY_FILE=/run/secrets/api_key secrets: db_password: file: ./secrets/db_password.txt api_key: file: ./secrets/api_key.txt ``` Uygulama kodu gizli bilgileri bağlanmış dosyalardan okur. ```javascript // config/secrets.js const fs = require('fs'); const path = require('path'); // Utility function to read Docker secrets function readSecret(secretName) { const secretPath = `/run/secrets/${secretName}`; // Check if secret file exists if (fs.existsSync(secretPath)) { return fs.readFileSync(secretPath, 'utf8').trim(); } // Fallback to classic environment variables const envVar = secretName.toUpperCase(); return process.env[envVar]; } module.exports = { databasePassword: readSecret('db_password'), apiKey: readSecret('api_key'), }; ``` Bu yaklaşım, gizli bilgilerin ortam değişkenlerinde veya Docker imajlarında açığa çıkmasını önler. ## Docker İmajlarının Optimizasyonu Çeşitli teknikler imaj boyutunu azaltır ve performansı artırır. ```dockerfile # Dockerfile.optimized FROM node:22-alpine AS base # Install necessary tools in a single layer RUN apk add --no-cache \ dumb-init \ && rm -rf /var/cache/apk/* # ============================================ # Stage: Dependencies # ============================================ FROM base AS deps WORKDIR /app # Copy only lock files for caching COPY package.json package-lock.json ./ # Install with mounted npm cache (BuildKit) RUN --mount=type=cache,target=/root/.npm \ npm ci --only=production # ============================================ # Stage: Builder # ============================================ FROM base AS builder WORKDIR /app COPY package.json package-lock.json ./ RUN --mount=type=cache,target=/root/.npm \ npm ci COPY . . RUN npm run build # ============================================ # Stage: Production # ============================================ FROM base AS production # Image metadata LABEL maintainer="team@example.com" LABEL version="1.0" LABEL description="Production-ready Node.js application" # Non-root user RUN addgroup -g 1001 -S nodejs && \ adduser -S nodejs -u 1001 WORKDIR /app # Copy production dependencies COPY --from=deps --chown=nodejs:nodejs /app/node_modules ./node_modules # Copy build output COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist COPY --from=builder --chown=nodejs:nodejs /app/package.json ./ USER nodejs ENV NODE_ENV=production # dumb-init as PID 1 for signal handling ENTRYPOINT ["dumb-init", "--"] CMD ["node", "dist/server.js"] ``` `dumb-init` kullanımı Unix sinyallerinin doğru işlenmesini sağlar ve konteynerin düzgün bir şekilde kapatılmasını mümkün kılar. ```bash # terminal # Enable BuildKit for advanced features export DOCKER_BUILDKIT=1 # Build with cache and detailed output docker build --progress=plain -t my-app:optimized . # Analyze image layers docker history my-app:optimized # Detailed image inspection docker inspect my-app:optimized ``` > **İmaj Güvenliği** > > İmajlar Trivy veya Snyk gibi araçlarla düzenli olarak güvenlik açıkları için taranmalıdır. Temel imajlar güvenlik yamalarını içerecek şekilde düzenli olarak güncellenmelidir. ## Gelişmiş Docker Ağları Docker, farklı kullanım senaryoları için çeşitli ağ sürücüleri sunar. ```yaml # docker-compose.networking.yml version: "3.9" services: # Publicly accessible frontend frontend: build: ./frontend ports: - "80:80" networks: - frontend-network - backend-network # API accessible only from frontend api: build: ./api networks: - backend-network - database-network # No external ports exposed # Isolated database database: image: postgres:16-alpine networks: - database-network # Accessible only by API networks: frontend-network: driver: bridge backend-network: driver: bridge internal: true # No internet access database-network: driver: bridge internal: true ``` Bu yapılandırma en az yetki ilkesini izleyerek servisleri izole eder. Veritabanı yalnızca API tarafından erişilebilir durumdadır. ```bash # terminal # Inspect Docker networks docker network ls # Details of a specific network docker network inspect app-network # Create a custom network docker network create --driver bridge --subnet 172.28.0.0/16 custom-network # Connect a container to an existing network docker network connect custom-network my-container ``` ## Volume'lar ve Veri Kalıcılığı Docker volume'ları verileri konteyner yaşam döngüsünün ötesinde korur. ```yaml # docker-compose.volumes.yml version: "3.9" services: app: image: my-app:latest volumes: # Named volume for persistent data - app_data:/app/data # Bind mount for development - ./uploads:/app/uploads:rw # Read-only mount for configuration - ./config:/app/config:ro backup: image: alpine volumes: # Access same volume for backups - app_data:/data:ro - ./backups:/backups command: | sh -c "tar czf /backups/backup-$$(date +%Y%m%d).tar.gz /data" volumes: app_data: driver: local driver_opts: type: none device: /path/to/host/data o: bind ``` Adlandırılmış volume'lar ve bind mount'lar arasındaki fark önemlidir: volume'lar Docker tarafından yönetilirken, bind mount'lar doğrudan ana bilgisayar dosya sistemini kullanır. ```bash # terminal # List volumes docker volume ls # Inspect a volume docker volume inspect app_data # Remove orphaned volumes docker volume prune # Backup a volume docker run --rm -v app_data:/data -v $(pwd):/backup alpine \ tar czf /backup/volume-backup.tar.gz /data ``` ## Üretim Ortamına Dağıtım Sağlam bir dağıtım iş akışı derleme, test ve registry'ye gönderme işlemlerini içerir. ```bash # deploy.sh #!/bin/bash set -e # Variables REGISTRY="registry.example.com" IMAGE_NAME="my-app" VERSION=$(git describe --tags --always) echo "Building version: $VERSION" # Build production image docker build \ -f Dockerfile.production \ -t $REGISTRY/$IMAGE_NAME:$VERSION \ -t $REGISTRY/$IMAGE_NAME:latest \ --build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \ --build-arg VERSION=$VERSION \ . # Security scan echo "Running security scan..." docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ aquasec/trivy image $REGISTRY/$IMAGE_NAME:$VERSION # Push to registry echo "Pushing to registry..." docker push $REGISTRY/$IMAGE_NAME:$VERSION docker push $REGISTRY/$IMAGE_NAME:latest echo "Deployment complete: $REGISTRY/$IMAGE_NAME:$VERSION" ``` Sunucu dağıtımları için ayrı bir üretim compose dosyası yapılandırmayı uyarlar. ```yaml # docker-compose.prod.yml version: "3.9" services: app: image: registry.example.com/my-app:latest restart: always deploy: replicas: 3 resources: limits: cpus: "0.5" memory: 512M reservations: cpus: "0.25" memory: 256M update_config: parallelism: 1 delay: 10s failure_action: rollback healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s logging: driver: "json-file" options: max-size: "10m" max-file: "3" ``` Bu yapılandırma güvenilir bir dağıtım için kaynak tahsisi, güncelleme stratejisi ve healthcheck'leri tanımlar. ```bash # terminal # Production deployment with Docker Compose docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d # Zero-downtime update (rolling update) docker compose -f docker-compose.yml -f docker-compose.prod.yml pull docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --no-deps app # Rollback if issues occur docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --no-deps \ --scale app=0 && \ docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --no-deps app ``` ## Konteyner İzleme ve Hata Ayıklama Konteyner izleme üretim ortamında vazgeçilmezdir. ```bash # terminal # Real-time statistics for all containers docker stats # Statistics for a specific container with custom format docker stats my-app --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" # Inspect processes in a container docker top my-app # Real-time Docker events docker events --filter container=my-app # Copy files from/to a container docker cp my-app:/app/logs/error.log ./error.log ``` Derinlemesine hata ayıklama için çeşitli teknikler mevcuttur. ```bash # terminal # Interactive shell in a running container docker exec -it my-app sh # Execute a single command docker exec my-app cat /app/config/settings.json # Start a container in debug mode docker run -it --rm --entrypoint sh my-app:latest # Inspect environment variables docker exec my-app printenv # Analyze logs with filters docker logs my-app --since 1h --tail 100 | grep ERROR ``` ```yaml # docker-compose.monitoring.yml version: "3.9" services: app: # ... existing configuration labels: - "prometheus.scrape=true" - "prometheus.port=3000" - "prometheus.path=/metrics" prometheus: image: prom/prometheus:latest ports: - "9090:9090" volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.retention.time=15d' grafana: image: grafana/grafana:latest ports: - "3001:3000" volumes: - grafana_data:/var/lib/grafana environment: - GF_SECURITY_ADMIN_PASSWORD=secret volumes: prometheus_data: grafana_data: ``` Bu izleme yığını konteyner metriklerinin toplanmasını ve görselleştirilmesini sağlar. ## Sonuç Docker, tüm ortamlarda tutarlılık sağlayarak geliştirme döngüsünü dönüştürmektedir. Konteynerleştirme taşınabilirlik, izolasyon ve tekrarlanabilirlik getirir — modern uygulamalar için temel nitelikler. ### Üretim İçin Docker Kontrol Listesi - ✅ Optimize edilmiş imajlar için multi-stage build'ler - ✅ Konteynerlerde root olmayan kullanıcı - ✅ Tüm servisler için healthcheck'ler yapılandırılmış - ✅ Docker secrets veya güvenli ortam değişkenleri ile yönetilen gizli bilgiler - ✅ Kaynak limitleri (CPU, bellek) tanımlanmış - ✅ Kritik veri kalıcılığı için volume'lar - ✅ Dosya rotasyonlu merkezi loglama - ✅ Dağıtım öncesi imaj güvenlik taraması - ✅ Kesintisiz güncelleme stratejisi - ✅ Servisler arası izole ağ Docker'a hakim olmak her modern geliştiricinin temel becerisidir. Yerel ortamdan üretim dağıtımına kadar Docker iş akışlarını standartlaştırır ve operasyonları basitleştirir. Burada sunulan kavramlar, Kubernetes ve büyük ölçekli konteyner orkestrasyonunu keşfetmek için sağlam bir temel oluşturmaktadır. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/tr/blog/devops/docker-from-development-to-production