Skip to content
intermediate Phase 94 · Docker

Docker Debugging

Docker debugging - container logs, Xdebug in Docker, performance tuning

45m
0 problems
Topic Progress 0%

Container Logs

Log Viewing Commands

# View all container logs
docker-compose logs

# View specific service logs
docker-compose logs nginx
docker-compose logs php-fpm

# Follow logs in real-time
docker-compose logs -f

# View last 100 lines
docker-compose logs --tail=100

# View logs since specific time
docker-compose logs --since=2024-01-15T10:00:00

# View logs with timestamps
docker-compose logs -t

Magento Log Files

namespace Vendor\Docker\Log\Debug;

class MagentoLogViewer
{
    public function getLogPaths(): array
    {
        return [
            'system' => '/var/www/html/var/log/system.log',
            'exception' => '/var/www/html/var/log/exception.log',
            'debug' => '/var/www/html/var/log/debug.log',
            'payment' => '/var/www/html/var/log/payment.log',
            'sql' => '/var/www/html/var/log/sql.log',
        ];
    }

    public function tailLog(string $logFile): string
    {
        $command = sprintf(
            'docker exec php-fpm tail -f %s',
            $logFile
        );

        exec($command, $output);
        return implode("\n", $output);
    }
}

Structured Logging

namespace Vendor\Docker\Log\Structure;

class StructuredLogReader
{
    public function parseJsonLog(string $logFile): array
    {
        $logs = [];
        $handle = fopen($logFile, 'r');

        while (($line = fgets($handle)) !== false) {
            $decoded = json_decode($line, true);
            if ($decoded) {
                $logs[] = $decoded;
            }
        }

        fclose($handle);
        return $logs;
    }
}

Xdebug in Docker

Xdebug Configuration

# docker/php/Dockerfile.dev
FROM php:8.2-fpm-alpine

# Install Xdebug
RUN pecl install xdebug && docker-php-ext-enable xdebug

# Copy Xdebug config
COPY xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini

xdebug.ini

; Docker Xdebug configuration
zend_extension=xdebug

xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
xdebug.idekey=DOCKER
xdebug.discover_client_host=true
xdebug.log=/var/log/xdebug.log

; Performance
xdebug.max_nesting_level=512
xdebug.show_error_trace=1
xdebug.show_exception_trace=1

Docker Compose Xdebug

services:
  php-fpm:
    build:
      context: ./docker/php
      dockerfile: Dockerfile.dev
    volumes:
      - ./src:/var/www/html
    environment:
      - PHP_IDE_CONFIG=serverName=docker
      - XDEBUG_CONFIG=client_host=host.docker.internal
    extra_hosts:
      - "host.docker.internal:host-gateway"

IDE Configuration

// .idea/phpServers.json (PhpStorm)
{
    "servers": [
        {
            "name": "Docker Magento",
            "host": "localhost",
            "port": 80,
            "ideKey": "DOCKER",
            "pathMappings": {
                "/var/www/html": "$PROJECT_DIR$"
            }
        }
    ]
}

Xdebug Connection Test

<?php
// Test Xdebug connection
echo 'Xdebug is ' . (extension_loaded('xdebug') ? 'loaded' : 'not loaded');
echo PHP_EOL;
echo 'Mode: ' . ini_get('xdebug.mode');
echo PHP_EOL;
echo 'Client: ' . ini_get('xdebug.client_host');
echo PHP_EOL;

Performance Tuning

Container Performance

services:
  php-fpm:
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 2G
        reservations:
          cpus: '1.0'
          memory: 1G
    environment:
      - PHP_OPCACHE_ENABLE=1
      - PHP_OPCACHE_MEMORY_CONSUMPTION=512
      - PHP_OPCACHE_MAX_ACCELERATED_FILES=10000

OPcache Tuning

; docker/php/opcache.ini
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=512
opcache.interned_strings_buffer=64
opcache.max_accelerated_files=10000
opcache.revalidate_freq=0
opcache.save_comments=1
opcache.fast_shutdown=1

MySQL Performance

services:
  mysql:
    command:>
      --innodb-buffer-pool-size=1G
      --innodb-log-file-size=256M
      --max-connections=500
      --innodb-flush-log-at-trx-commit=2
      --innodb-flush-method=O_DIRECT

Redis Performance

services:
  redis:
    command:>
      redis-server
      --appendonly yes
      --maxmemory 256mb
      --maxmemory-policy allkeys-lru
      --save 900 1
      --save 300 10

Docker Stats

# Monitor resource usage
docker stats

# Specific container
docker stats php-fpm

# One-time snapshot
docker stats --no-stream

Performance Profiling

namespace Vendor\Docker\Performance;

class PerformanceProfiler
{
    public function profile(string $command): ProfileResult
    {
        $start = microtime(true);

        exec($command, $output, $returnCode);

        $duration = microtime(true) - $start;

        return new ProfileResult([
            'command' => $command,
            'duration' => $duration,
            'memory_usage' => memory_get_peak_usage(true),
            'return_code' => $returnCode,
        ]);
    }
}

Troubleshooting

Common Issues

# Container won't start
docker-compose logs <service>

# Permission denied
docker exec php-fpm ls -la /var/www/html
docker exec php-fpm chown -R www-data:www-data /var/www/html

# Port already in use
lsof -i :80
docker-compose down

# MySQL connection refused
docker exec mysql mysqladmin ping -h localhost

# Redis connection refused
docker exec redis redis-cli ping

# Out of memory
docker system df
docker system prune

Debugging Commands

# Enter container shell
docker exec -it php-fpm bash

# Check running processes
docker exec php-fpm ps aux

# Check network connectivity
docker exec php-fpm ping mysql
docker exec php-fpm ping redis

# Check disk usage
docker exec php-fpm df -h

# Check PHP modules
docker exec php-fpm php -m

# Check PHP info
docker exec php-fpm php -i

# Check environment variables
docker exec php-fpm env

Health Check Script

#!/bin/bash
# scripts/healthcheck.sh

echo "Checking services..."

# MySQL
if docker exec mysql mysqladmin ping -h localhost > /dev/null 2>&1; then
    echo "✓ MySQL is running"
else
    echo "✗ MySQL is not responding"
fi

# Redis
if docker exec redis redis-cli ping > /dev/null 2>&1; then
    echo "✓ Redis is running"
else
    echo "✗ Redis is not responding"
fi

# PHP-FPM
if docker exec php-fpm php-fpm-healthcheck > /dev/null 2>&1; then
    echo "✓ PHP-FPM is running"
else
    echo "✗ PHP-FPM is not responding"
fi

# Nginx
if curl -s http://localhost > /dev/null 2>&1; then
    echo "✓ Nginx is running"
else
    echo "✗ Nginx is not responding"
fi

Reset Environment

# Full reset
docker-compose down -v
rm -rf src/vendor
rm -rf src/var
docker-compose build --no-cache
docker-compose up -d

# Reset specific service
docker-compose restart php-fpm

# Force rebuild
docker-compose build --no-cache php-fpm
docker-compose up -d php-fpm

Quiz

1. How do you view Docker container logs?

Question 1 options

2. How does Xdebug connect to the IDE in Docker?

Question 2 options

3. What does docker stats show?

Question 3 options

Flashcards

Question

How to view container logs?

Answer

docker-compose logs or docker logs container

Question

How does Xdebug connect in Docker?

Answer

Uses host.docker.internal to reach host IDE

Question

What is docker stats?

Answer

Shows real-time CPU/memory usage per container

Question

How to enter a container shell?

Answer

docker exec -it container bash

Revision Notes

Key Takeaways

  • 1. docker-compose logs views service logs
  • 2. Xdebug connects via host.docker.internal
  • 3. docker stats monitors resource usage
  • 4. Health checks verify service availability
  • 5. Reset with docker-compose down -v for clean slate

Interview Tips

  • Explain Docker log viewing strategies
  • Discuss Xdebug configuration in Docker
  • Describe container performance monitoring
  • Talk about common Docker troubleshooting

Cheat Sheet

Debugging:
  docker-compose logs → view logs
  docker exec -it → enter container
  docker stats → resource usage

Xdebug:
  client_host=host.docker.internal
  client_port=9003
  mode=debug

Troubleshooting:
  Container won't start → check logs
  Permission denied → chown
  Port conflict → lsof -i :port
  Connection refused → check service

Reset:
  docker-compose down -v
  docker-compose build --no-cache
  docker-compose up -d