Docker dla PrestaShop: Konfiguracja środowiska deweloperskiego
Konfiguracja Dockera do pracy z PrestaShop: testy wielu wersji, praca z modułami, zarządzanie bazą danych, debugowanie Xdebug i wdrożenia produkcyjne.
Dlaczego każdy sklep PrestaShop uruchamiany jest na Dockerze
Cała infrastruktura deweloperska i stagingowa w mypresta.rocks opiera się na Dockerze, jeden host TrueNAS, dedykowane kontenery takie jak ps176-dev, ps178-dev, ps8-dev i ps9-dev, współdzielony ps-redis, a z przodu Nginx Proxy Manager. Każdy błąd opisany na tej stronie popełniliśmy przynajmniej raz.
Problem: PS 1.7 wymaga PHP 7.1, PS 8.x wymaga 8.1, PS 9.x wymaga 8.3+. MySQL 5.7 kontra 8.0 zmienia wtyczkę uwierzytelniania. Natywna instalacja tego wszystkiego to sposób na spędzenie soboty na rozwiązywaniu problemów zamiast na pisaniu modułów. Każdy kontener dostarcza dokładnie to środowisko uruchomieniowe, którego oczekuje dana wersja PrestaShop.
- Testowanie wielu wersji. PS 1.6, 1.7, 8.x i 9.x jednocześnie. Audyt modułu zajmuje popołudnie, a nie tydzień przebudowywania stosów LAMP.
- Izolacja. Każdy sklep ma własne PHP, MySQL i system plików. Nieudana instalacja nie przeniknie do innego.
- Powtarzalność. Wszystko zapisane w
docker-compose.yml. Laptop, staging, maszyna współpracownika, ta sama konfiguracja. - Łatwe sprzątanie.
docker compose down -vi znika.
Na jednej maszynie TrueNAS uruchamiamy oddzielne kontenery PrestaShop od 1.6 aż po 9.1. Opisane poniżej wzorce to wynik dekady doskonalenia.
Wymagania wstępne
Instalacja Dockera
Ubuntu/Debian: curl -fsSL https://get.docker.com | sh, a następnie sudo usermod -aG docker $USER. macOS: Docker Desktop: w ustawieniach należy przełączyć implementację udostępniania plików na VirtioFS. Windows: najpierw WSL2, a potem Docker Desktop z backendem WSL2. Tryb Hyper-V jest wolniejszy; lepiej go unikać.
Cztery pojęcia, które mają znaczenie
- Obraz: szablon tylko do odczytu. Oficjalny to
prestashop/prestashopw Docker Hub. - Kontener: uruchomiona instancja. Z jednego obrazu można uruchomić kilka. Tak właśnie działają konfiguracje wielowersyjne.
- Wolumin: trwałe miejsce zapisu. Bez woluminu nie ma danych po usunięciu kontenera. Zdarzyło nam się stracić dane testowe, zapominając o tym.
- Sieć: sieć wirtualna, dzięki której kontenery mogą się komunikować (PrestaShop ↔ MySQL).
Sprzęt
Na każdą instancję PrestaShop warto przewidzieć 1,5–2 GB RAM. 16 GB wystarcza komfortowo na laptopie dewelopera dla 2–3 wersji. Nasza maszyna deweloperska ma 64 GB i dysk NVMe, ponieważ uruchamiamy jednocześnie kilka kontenerów w różnych wersjach. Dyski talerzowe sprawią, że Docker stanie się udręką, nie warto próbować.
Konfiguracja dwóch kontenerów
Wystarczy umieścić poniższy fragment w pliku docker-compose.yml:
version: '3.8'
services:
prestashop:
image: prestashop/prestashop:8.2
container_name: <your-shop>
ports:
- "8080:80"
environment:
- DB_SERVER=db
- DB_USER=prestashop
- DB_PASSWD=prestashop_password
- DB_NAME=prestashop
- PS_DOMAIN=localhost:8080
- PS_FOLDER_ADMIN=admin-dev
- PS_FOLDER_INSTALL=disabled
- ADMIN_MAIL=admin@yourshop.com
- ADMIN_PASSWD=admin_password_123
volumes:
- shop-data:/var/www/html
depends_on:
- db
db:
image: mysql:8.0
container_name: <your-shop>-db
environment:
- MYSQL_ROOT_PASSWORD=root_password
- MYSQL_DATABASE=prestashop
- MYSQL_USER=prestashop
- MYSQL_PASSWORD=prestashop_password
volumes:
- shop-db-data:/var/lib/mysql
volumes:
shop-data:
shop-db-data:
DB_SERVER musi dokładnie odpowiadać nazwie usługi (db), to najczęstsza pojedyncza przyczyna niepowodzenia świeżego compose. PS_FOLDER_INSTALL=disabled zapobiega ponownemu uruchamianiu instalatora przy każdym restarcie. Po wpisaniu docker compose up -d należy obserwować logi poleceniem docker compose logs -f prestashop; za pierwszym razem warto dać temu 1–2 minuty.
Sklep pod adresem http://localhost:8080, Panel administracyjny pod http://localhost:8080/admin-dev.
Dla bazy danych zawsze należy używać nazwanych woluminów. Bez takiego woluminu usunięcie kontenera niszczy każdy produkt, zamówienie i klienta. Zdarzyło nam się stracić pół dnia danych testowych, zapominając o tym przy „szybkim”, jednorazowym kontenerze.
Testowanie wielu wersji
To przypadek, do którego Docker został stworzony. Trzy wersje PrestaShop obok siebie, każda na własnym porcie i własnej bazie danych:
version: '3.8'
services:
ps176-dev:
image: prestashop/prestashop:1.7.6
container_name: ps176-dev
ports: ["8076:80"]
environment:
- DB_SERVER=<your-db-176>
- PS_DOMAIN=localhost:8076
# ... ten sam wzorzec co powyżej
volumes:
- ps176-data:/var/www/html
networks: [ps-network]
<your-db-176>:
image: mysql:5.7
volumes: [your-db-176-data:/var/lib/mysql]
networks: [ps-network]
ps8-dev:
image: prestashop/prestashop:8.2
container_name: ps8-dev
ports: ["8082:80"]
environment:
- DB_SERVER=<your-db-8>
- PS_DOMAIN=localhost:8082
volumes:
- ps8-data:/var/www/html
networks: [ps-network]
<your-db-8>:
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
volumes: [your-db-8-data:/var/lib/mysql]
networks: [ps-network]
ps9-dev:
image: prestashop/prestashop:9.0
container_name: ps9-dev
ports: ["8083:80"]
environment:
- DB_SERVER=<your-db-9>
- PS_DOMAIN=localhost:8083
volumes:
- ps9-data:/var/www/html
networks: [ps-network]
<your-db-9>:
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
volumes: [your-db-9-data:/var/lib/mysql]
networks: [ps-network]
networks:
ps-network:
driver: bridge
Należy wybrać schemat portów, nasz to 8178 dla PS 1.7.8, 8082 dla 8.2, 8090 dla 9.0. Powyżej dziesięciu kontenerów numery portów przestają być możliwe do zapamiętania; wtedy właśnie ustawiamy z przodu Nginx Proxy Manager i nadajemy każdemu sklepowi nazwę hosta w rodzaju ps8-dev.mypresta.rocks. Warto zrobić to od pierwszego dnia, jeśli planuje się więcej niż kilka kontenerów.
Zawsze należy oddzielać bazy danych. Schemat różni się między wersjami głównymi; migracje wzajemnie uszkodzą sobie dane.
Ostrzeżenie: docker network connect / disconnect na działającym kontenerze przepisuje mapowanie portów. Widzieliśmy, jak po cichu wyłączyło to port 443 na naszym kontenerze NPM, kładąc jednocześnie wszystkie witryny. Sieć należy definiować w compose i ponownie utworzyć kontener, jeśli zachodzi potrzeba jej zmiany.
Proces pracy nad modułem
Warto zamontować katalog modułu (bind-mount). Każda edycja od razu jest aktywna. To największa pojedyncza korzyść, jaką Docker daje przy pracy nad modułami:
volumes:
- ps8-data:/var/www/html
- /home/user/modules/my_module:/var/www/html/modules/my_module
Przy testowaniu wielu wersji ten sam katalog hosta należy zamontować do każdego kontenera. Edycja jednego pliku, odświeżenie trzech kart. Montujemy każdy katalog ~/modules/mpr* do wszystkich ps178-dev, ps8-dev i ps9-dev właśnie w tym celu.
Uprawnienia: powracająca pułapka
Pliki hosta należą do bieżącego użytkownika (UID 1000); Apache działa jako www-data (UID 33). PrestaShop próbuje zapisać do var/cache, img, modules i otrzymuje odmowę, to dlatego wgrywanie modułów zawodzi na świeżych konfiguracjach.
# Interaktywna sesja MySQL
docker exec -it <your-shop>-db mysql -u root -p'root' prestashop
# Wykonanie pojedynczego zapytania
docker exec <your-shop>-db mysql -u root -p'root' -e "SELECT COUNT(*) FROM ps_product;" prestashop
Warto trzymać pod ręką skrypt fix-container-perms.sh. My uruchamiamy nasz częściej, niżbyśmy chcieli, zwłaszcza po wgraniu modułów przez rsync.
Pamięć podręczna
docker exec ps8-dev rm -rf /var/www/html/var/cache/*
Można też wyłączyć pamięć podręczną szablonów w Parametry zaawansowane → Wydajność na czas aktywnej pracy. Należy ją włączyć ponownie przed uznaniem pracy za zakończoną, błędy związane z pamięcią podręczną ujawniają się dopiero przy jej włączeniu. Jeśli produkcja korzysta z Redis, ten sam serwis warto dodać lokalnie; Redis Dashboard & Key Manager przydaje się, gdy zależy nam na tym, by konfiguracja pamięci podręcznej po stronie PrestaShop odpowiadała produkcji, a nie udawać tego pamięcią podręczną na systemie plików.
Zarządzanie bazą danych
Bazy testowe warto utrzymywać na tyle małe, by dało się je łatwo przenosić. Przed wyeksportowaniem działającego sklepu do Dockera należy przyciąć nieaktualne koszyki, logi i dane tymczasowe za pomocą Database Cleanup lub równoważnego przejścia czyszczącego w SQL, a dopiero potem wykonać zrzut.
phpmyadmin:
image: phpmyadmin:latest
ports: ["9090:80"]
environment:
- PMA_HOSTS=<your-db-176>,<your-db-8>,<your-db-9>
- PMA_USER=root
- PMA_PASSWORD=root
networks: [ps-network]
phpMyAdmin
Powyższa usługa phpMyAdmin łączy się z każdą bazą danych w sieci; poniższe polecenia służą do eksportu i importu bazy danych:
# Eksport
docker exec <your-shop>-db mysqldump -u root -p'root' prestashop > backup.sql
# Import
docker exec -i <your-shop>-db mysql -u root -p'root' prestashop < backup.sql
Import i eksport
mailpit:
image: axllent/mailpit
ports:
- "8025:8025" # Interfejs webowy
- "1025:1025" # SMTP
networks: [ps-network]
Dwie produkcyjne pułapki: skompresowane zrzuty należy przepuścić przez gunzip oraz zawsze przekazywać SET NAMES utf8mb4 na początku każdego przywracania przez docker exec, w przeciwnym razie nazwy produktów w UTF-8 trafią zakodowane podwójnie, a naprawa jest brzydsza niż zapobieganie.
Trwałe czy tymczasowe
Trwałe (nazwane woluminy): wszystko, czego utrata byłaby przykra. Tymczasowe: testy instalatora. Utrzymujemy tymczasowy kontener PS 9.0 do pytania „czy ten moduł instaluje się czysto na pustym sklepie?”, świeży przy każdym uruchomieniu.
Testowanie poczty e-mail za pomocą Mailpit
Mailpit przechwytuje wychodzące wiadomości e-mail wysyłane za jego pośrednictwem i wyświetla je w interfejsie webowym, korzystając z powyższej konfiguracji usługi. Poniższy Dockerfile dodaje Xdebug do PrestaShop:
FROM prestashop/prestashop:8.2
RUN pecl install xdebug && docker-php-ext-enable xdebug
COPY xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
Panel administracyjny → Parametry zaawansowane → E-mail: SMTP mailpit, port 1025, bez szyfrowania, bez uwierzytelniania. Przechwycona poczta pod http://localhost:8025. Jeden współdzielony Mailpit obsługuje każdy sklep deweloperski w naszej sieci.
Debugowanie za pomocą Xdebug
Oficjalny obraz nie zawiera Xdebug. Należy zbudować nakładkę przy użyciu powyższego pliku Dockerfile, a następnie skonfigurować xdebug.ini i VS Code zgodnie z poniższymi przykładami:
[xdebug]
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
xdebug.idekey=VSCODE
{
"version": "0.2.0",
"configurations": [{
"name": "Listen for Xdebug (Docker)",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/var/www/html/modules/my_module": "${workspaceFolder}"
}
}]
}
W systemie Linux host.docker.internal domyślnie nie istnieje, należy dodać extra_hosts: ["host.docker.internal:host-gateway"]. Straciliśmy na tym pół godziny.
VS Code
Należy zainstalować PHP Debug i dodać pokazaną wyżej konfigurację JSON do .vscode/launch.json. Poniższe polecenia poprawiają uprawnienia w kontenerze:
docker exec <your-shop> chown -R www-data:www-data /var/www/html/var
docker exec <your-shop> chown -R www-data:www-data /var/www/html/img
docker exec <your-shop> chown -R www-data:www-data /var/www/html/modules
To właśnie pathMappings sprawia, że punkt przerwania zadziała. Bez niego VS Code po cichu nic nie robi.
PHPStorm
Ustawienia → PHP → Serwery: localhost + port kontenera, mapowanie /var/www/html na projekt. Port Xdebug 9003 w PHP → Debug, „Rozpocznij nasłuchiwanie”.
Przydatne polecenia
| Zadanie | Polecenie |
|---|---|
| Uruchomienie wszystkich kontenerów | docker compose up -d |
| Zatrzymanie wszystkich kontenerów | docker compose down |
| Zatrzymanie i usunięcie wszystkich danych | docker compose down -v |
| Podgląd logów | docker compose logs -f |
| Czyszczenie pamięci podręcznej PS | docker exec CONTAINER rm -rf /var/www/html/var/cache/* |
| Wiersz poleceń MySQL | docker exec -it CONTAINER-db mysql -u root -p'PASS' prestashop |
| Eksport bazy danych | docker exec CONTAINER-db mysqldump -u root -p'PASS' prestashop > backup.sql |
| Import bazy danych | docker exec -i CONTAINER-db mysql -u root -p'PASS' prestashop < backup.sql |
| Powłoka w kontenerze | docker exec -it CONTAINER bash |
| Sprawdzenie zużycia zasobów | docker stats --no-stream |
| Przebudowa po zmianach w Dockerfile | docker compose up -d --build |
| Uruchomienie konsoli PrestaShop | docker exec CONTAINER php bin/console cache:clear --env=prod |
| Uruchomienie Composera w module | docker exec -w /var/www/html/modules/my_module CONTAINER composer install |
Produkcja: nasza szczera opinia
Dla większości sprzedawców Docker jest narzędziem deweloperskim. Produkcja zwykle działa lepiej na tradycyjnym hostingu, pojedynczy stos LAMP łatwiej monitorować i przekazać, natywne wejście/wyjście plików bije woluminy Dockera (PrestaShop wczytuje tysiące plików PHP na każde żądanie), a większość hostingów przyjaznych PrestaShop daje cPanel, a nie demona Dockera.
Docker w produkcji zarabia na siebie przy CI/CD, skokach przepustowości na czas wydarzeń sprzedażowych, dziesięciu i więcej sklepach lub wdrożeniach bez przestojów.
Compose kontra Kubernetes kontra Swarm. Compose obsługuje 20–30 kontenerów na jednym hoście. Tyle u nas działa i to w zupełności wystarcza. Kubernetes dokłada automatyczne skalowanie i orkiestrację wielowęzłową kosztem prawdziwego zespołu infrastrukturalnego; w przypadku PrestaShop nie spotkaliśmy jeszcze sytuacji, w której byłby właściwym wyborem. Docker Swarm to niewygodny środek, który pominęlibyśmy, społeczność poszła dalej. A kompose (narzędzie do „konwersji compose na k8s”) brzmi świetnie, dopóki się go nie wypróbuje i nie okaże się, że wynik wymaga tyle samo ręcznej obróbki co napisanie wszystkiego od nowa.
Dwa ustawienia hosta warte ustawienia
live-restore: truew/etc/docker/daemon.json. Restarty demona przestają zabijać działające kontenery.- Niestandardowy
data-rootna szybkiej puli SSD, a nie na dysku systemowym. Obrazy i woluminy MySQL rosną; dyski systemowe zapełniają się po cichu.
Co bywa nie tak
„Nie można połączyć się z bazą danych”
DB_SERVERnie odpowiada nazwie usługi MySQL (identyczna, łącznie z myślnikami).- MySQL nie zakończył uruchamiania. Należy użyć healthcheck i
depends_on: condition: service_healthy. - Kontenery w różnych sieciach: oba należy umieścić w nazwanym mostku (bridge).
- MySQL 8.0 domyślnie używa
caching_sha2_password; mysqli w PrestaShop wymagamysql_native_password. Należy dodaćcommand: --default-authentication-plugin=mysql_native_password.
Wolne wejście/wyjście na macOS
Montowania bind na macOS bywały ślimacze (10–30 s na wczytanie strony). Trzy rozwiązania: VirtioFS w ustawieniach Docker Desktop (największa pojedyncza korzyść), mniej montowania (tylko katalog modułu, reszta na nazwanym woluminie), Mutagen (dwukierunkowa synchronizacja plików, która omija warstwę montowania. Rozwiązanie siłowe, ale działa).
SSL w środowisku deweloperskim
Moduły płatności i logowanie społecznościowe odmawiają działania na zwykłym HTTP. Nginx Proxy Manager obsługuje terminację SSL dla każdego kontenera, tego używamy, najczystsza opcja. mkcert do lokalnie zaufanych certyfikatów. Traefik do automatycznego wykrywania i provisioningu.
MySQL pożerający cały RAM
command: >
--innodb-buffer-pool-size=128M
--max-connections=50
W Docker Desktop limit pamięci w Ustawienia → Zasoby warto podnieść do co najmniej 6 GB, gdy ma się już kilka kontenerów. Te, których się nie używa, należy zatrzymywać: docker stop ps178-dev.
Pętle ponownej instalacji
Jeśli PrestaShop instaluje się ponownie przy każdym restarcie, wolumin /var/www/html nie zachowuje danych albo PS_FOLDER_INSTALL=disabled nie jest odczytywane. Należy sprawdzić, czy docker volume ls pokazuje prawdziwy (a nie anonimowy) wolumin.
Mieszana zawartość po zmianie portu
docker exec <your-shop>-db mysql -u root -p'root' -e "
UPDATE ps_configuration SET value='localhost:8080'
WHERE name IN ('PS_SHOP_DOMAIN','PS_SHOP_DOMAIN_SSL');
UPDATE ps_shop_url SET domain='localhost:8080', domain_ssl='localhost:8080';
" prestashop
Jedno ostrzeżenie: nigdy nie należy uruchamiać tego zapytania na działającym sklepie klienta bez kopii zapasowej. Widzieliśmy, jak zablokowało frontend produkcyjny w środku popołudnia.
Powiązane lektury
- Lokalne środowisko deweloperskie PrestaShop: konfiguracja XAMPP, WAMP, Docker i Linux: Docker na tle alternatyw
- Niezbędne narzędzia do programowania w PrestaShop: czego używamy obok Dockera
- Jak utworzyć witrynę stagingową PrestaShop: rozszerzanie tych wzorców na staging
- Przewodnik rozwiązywania problemów: gdy kontener działa, ale sklep nadal zachowuje się niewłaściwie
- Optymalizacja wydajności i Performance Revolution: kolejny przystanek po „działa”
- Oficjalne repozytorium Docker PrestaShop