PHP / Magento Dev Blog

  • Publikacje
  • O autorze
  • Kontakt

Docker od zera – Dockerfile, nginx, docker-compose, Xdebug 3.x

by Henryk Tews / wtorek, 07 kwietnia 2020 / Opublikowano w Środowiska

DDEV świetnie sprawdza się na co dzień, ale co jeśli potrzebujesz niestandardowej konfiguracji, której DDEV nie obsługuje? Albo chcesz rozumieć co dzieje się pod spodem? Pokazuję jak zbudować środowisko PHP od zera z czystym Dockerem i docker-compose – nginx, PHP-FPM, MySQL i Redis bez żadnych narzędzi pośrednich.

Struktura projektu

project/
  docker/
    nginx/
      default.conf
    php/
      Dockerfile
      php.ini
  src/           <- kod aplikacji
  docker-compose.yml

Dockerfile dla PHP-FPM

Bazujemy na oficjalnym obrazie PHP-FPM i doinstalowujemy rozszerzenia potrzebne przy Magento 2:

FROM php:7.4-fpm

# Zależności systemowe
RUN apt-get update && apt-get install -y \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    libzip-dev \
    libicu-dev \
    libxslt-dev \
    libonig-dev \
    git \
    unzip \
    && rm -rf /var/lib/apt/lists/*

# Rozszerzenia PHP
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) \
        gd \
        pdo_mysql \
        zip \
        intl \
        xsl \
        soap \
        bcmath \
        sockets \
        opcache

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

# Composer
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

# Uprawnienia
RUN usermod -u 1000 www-data
USER www-data

Konfiguracja PHP – php.ini

[PHP]
memory_limit = 2G
max_execution_time = 600
upload_max_filesize = 64M
post_max_size = 64M
date.timezone = Europe/Warsaw

[opcache]
opcache.enable = 1
opcache.memory_consumption = 256
opcache.max_accelerated_files = 60000
opcache.validate_timestamps = 1

[xdebug]
xdebug.mode = debug
xdebug.client_host = host.docker.internal
xdebug.client_port = 9003
xdebug.start_with_request = no
xdebug.idekey = PHPSTORM

Konfiguracja nginx

upstream fastcgi_backend {
    server php:9000;
}

server {
    listen 80;
    server_name localhost;
    root /var/www/html/pub;

    index index.php;
    autoindex off;
    charset UTF-8;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ ^/index\.php$ {
        fastcgi_pass   fastcgi_backend;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
        fastcgi_param  MAGE_MODE developer;
    }

    location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
        expires 30d;
    }

    location ~ /\. {
        deny all;
    }
}

docker-compose.yml – składamy całość

version: '3.8'

services:
  nginx:
    image: nginx:1.18-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./src:/var/www/html
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php

  php:
    build:
      context: .
      dockerfile: docker/php/Dockerfile
    volumes:
      - ./src:/var/www/html
      - ./docker/php/php.ini:/usr/local/etc/php/conf.d/custom.ini
    environment:
      - XDEBUG_MODE=off
    depends_on:
      - db
      - redis

  db:
    image: mariadb:10.4
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: magento
      MYSQL_USER: magento
      MYSQL_PASSWORD: magento
    volumes:
      - db_data:/var/lib/mysql
    ports:
      - "3306:3306"

  redis:
    image: redis:6-alpine
    ports:
      - "6379:6379"

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.6.2
    environment:
      - discovery.type=single-node
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ports:
      - "9200:9200"
    volumes:
      - es_data:/usr/share/elasticsearch/data

volumes:
  db_data:
  es_data:

Uruchomienie i podstawowe komendy

# Zbuduj obrazy i uruchom
docker-compose up -d --build

# Wejdź do kontenera PHP
docker-compose exec php bash

# Wykonaj komendę Magento
docker-compose exec php bin/magento setup:upgrade

# Włącz Xdebug na czas sesji
docker-compose exec php bash -c "XDEBUG_MODE=debug php bin/magento ..."

# Logi nginx
docker-compose logs -f nginx

# Zatrzymaj wszystko
docker-compose down

# Zatrzymaj i usuń volumeny (czysty reset)
docker-compose down -v

Xdebug 3.x i PHPStorm – konfiguracja

Xdebug 3.x zmienił nazwy dyrektyw konfiguracyjnych względem 2.x. Zamiast remote_enable mamy teraz xdebug.mode. W PHPStorm ustaw serwer PHP z path mappingiem między lokalnym katalogiem ./src a /var/www/html w kontenerze. Bez tego mapowania breakpointy nie będą trafiać w odpowiednie linie.

Kiedy czysty Docker zamiast DDEV?

Czysty Docker ma sens gdy: potrzebujesz niestandardowych wersji serwisów których DDEV nie wspiera, budujesz środowisko CI/CD które ma być identyczne z lokalnym, chcesz pełnej kontroli nad siecią kontenerów, albo projekt ma specyficzne wymagania infrastrukturalne (np. własny reverse proxy, kilka domen na jednym stosie).

Podsumowanie

Czysty Docker wymaga więcej pracy konfiguracyjnej niż DDEV, ale daje pełną kontrolę i głębsze rozumienie środowiska. Warto przejść przez ten proces przynajmniej raz - wtedy abstrakcja DDEV przestaje być czarną skrzynką i staje się świadomym wyborem wygody.

About Henryk Tews

Co możesz przeczytać następne

OpenTelemetry – distributed tracing, auto-instrumentacja, Jaeger w DDEV
Kubernetes dla PHP developera – kubectl debugging, Deployment YAML, HPA, troubleshooting
XAMPP vs DDEV vs Warden – pełne porównanie w tabeli
  • Publikacje
  • O autorze
  • Kontakt

© 2026 Created by

GÓRA
Zarządzaj zgodą
Aby zapewnić jak najlepsze wrażenia, korzystamy z technologii, takich jak pliki cookie, do przechowywania i/lub uzyskiwania dostępu do informacji o urządzeniu. Zgoda na te technologie pozwoli nam przetwarzać dane, takie jak zachowanie podczas przeglądania lub unikalne identyfikatory na tej stronie. Brak wyrażenia zgody lub wycofanie zgody może niekorzystnie wpłynąć na niektóre cechy i funkcje.
Funkcjonalne Zawsze aktywne
Przechowywanie lub dostęp do danych technicznych jest ściśle konieczny do uzasadnionego celu umożliwienia korzystania z konkretnej usługi wyraźnie żądanej przez subskrybenta lub użytkownika, lub wyłącznie w celu przeprowadzenia transmisji komunikatu przez sieć łączności elektronicznej.
Preferencje
Przechowywanie lub dostęp techniczny jest niezbędny do uzasadnionego celu przechowywania preferencji, o które nie prosi subskrybent lub użytkownik.
Statystyka
Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do celów statystycznych. Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do anonimowych celów statystycznych. Bez wezwania do sądu, dobrowolnego podporządkowania się dostawcy usług internetowych lub dodatkowych zapisów od strony trzeciej, informacje przechowywane lub pobierane wyłącznie w tym celu zwykle nie mogą być wykorzystywane do identyfikacji użytkownika.
Marketing
Przechowywanie lub dostęp techniczny jest wymagany do tworzenia profili użytkowników w celu wysyłania reklam lub śledzenia użytkownika na stronie internetowej lub na kilku stronach internetowych w podobnych celach marketingowych.
  • Zarządzaj opcjami
  • Zarządzaj serwisami
  • Zarządzaj {vendor_count} dostawcami
  • Przeczytaj więcej o tych celach
Zobacz preferencje
  • {title}
  • {title}
  • {title}