Poradniki Poradnik

Jak stworzyć stronę staging PrestaShop

Kompletny przewodnik po konfiguracji środowiska testowego PrestaShop: Docker, hosting współdzielony i opcje lokalne. Aktualizacje psują staging, nie sklep.

Dlaczego przy każdym projekcie prowadzimy sklep staging

W mypresta.rocks równolegle utrzymujemy kilka środowisk staging, w tym ps9-dev, ps8-dev, ps178-dev oraz ps176-dev, a do tego sklepy dedykowane klientom, gdy dany projekt potrzebuje własnego klona. Nie są one luksusem. To dzięki nim testujemy każdą aktualizację modułu, każdą aktualizację PrestaShop i każdą zmianę motywu, zanim zobaczy je jakikolwiek klient. Po dekadzie dostarczania modułów nie spotkaliśmy ani jednego sprzedawcy, który żałowałby skonfigurowania takiego środowiska, za to wielu żałowało jego pominięcia.

Schemat jest zawsze ten sam: nieprzetestowana aktualizacja modułu trafia na produkcję, o 9:00 psuje się strona główna, o 9:05 pojawia się zgłoszenie do wsparcia, a kolejną godzinę spędza się na debugowaniu na oczach prawdziwych klientów. Zbudowanie sklepu staging zajmuje godzinę i zamienia ten scenariusz w 20-minutową naprawę pod adresem, którego nikt nie widzi.

Koszt jednej godziny przestoju podczas wyprzedaży przewyższa koszt utrzymania środowiska testowego o dwa rzędy wielkości. Jeśli sprzedaż w internecie jest źródłem utrzymania, sklep staging jest niezbędny.

Czym właściwie jest sklep staging

To pełny klon sklepu produkcyjnego (te same pliki, ta sama baza danych, ten sam zestaw modułów) serwowany pod adresem, do którego dostęp ma wyłącznie właściciel sklepu i jego zespół. Te same ścieżki kodu, którymi przechodzą klienci, ta sama logika biznesowa, te same przypadki brzegowe. Jedyne różnice to nazwa hosta, dane logowania oraz, przy poprawnej konfiguracji, fakt, że nie wychodzą żadne prawdziwe wiadomości e-mail i nie są obciążane żadne prawdziwe karty.

To nie jest środowisko deweloperskie do pracy od zera ani kopia zapasowa. Oba te nieporozumienia kosztowały sprzedawców prawdziwe pieniądze: staging zostaje nadpisany w momencie odświeżenia, więc wszystko, co tam zbudowano i czego nie wdrożono na produkcję, przepada.

Czym jest staging

  • Działającą kopią plików i bazy danych z produkcji
  • Na osobnej domenie lub subdomenie (stosujemy staging.yourshop.com lub dev.yourshop.com)
  • Zabezpieczoną listą dozwolonych adresów IP lub uwierzytelnianiem basic, tak aby dostęp miał wyłącznie zespół
  • Miejscem, w którym ćwiczy się aktualizacje modułów, zmiany motywu i aktualizacje PHP

Czym nie jest

  • Piaskownicą deweloperską do budowania nowego kodu od podstaw, to osobny sklep dev
  • Kopią zapasową. Kopie zapasowe są niezmienne. Staging jest nadpisywany przy każdym odświeżeniu.
  • Konfiguracją typu „ustaw i zapomnij”. Sklep staging niezsynchronizowany z produkcją od pół roku nie wychwyci niczego.

Opcja 1: staging oparty na Dockerze (z tego korzystamy)

Wszystkie nasze sklepy staging działają w Dockerze na pojedynczej maszynie TrueNAS. Każdy sklep to jeden stos docker-compose we wspólnej sieci Docker, kontener PrestaShop, kontener MySQL, współdzielony Redis, jeden bind mount dla katalogu html i jeden dla danych MySQL. Nową wersję PS możemy uruchomić w niecałe pięć minut, a po zakończeniu pracy usunąć ją, aby zwolnić pamięć RAM. Po jednorazowym przejściu tej drogi nie wraca się już do „po prostu zainstaluję to w podkatalogu cPanel”.

Wymagania wstępne

  • Host z systemem Linux z co najmniej 2 GB RAM na każdy sklep staging (4 GB, jeśli panel administracyjny ma działać płynnie)
  • Zainstalowane i działające Docker oraz Docker Compose
  • Dostęp SSH zarówno do produkcji, jak i do stagingu
  • Swoboda w kopiowaniu i wklejaniu poleceń powłoki

Krok 1: plik compose

Należy utworzyć katalog oraz plik docker-compose.yml:

mkdir ~/your-shop-staging && cd ~/your-shop-staging

cat > docker-compose.yml <<'EOF'
version: '3.8'
services:
  prestashop:
    image: prestashop/prestashop:8.2
    container_name: <your-shop>
    ports:
      - "8080:80"
    environment:
      - DB_SERVER=db
      - DB_NAME=prestashop
      - DB_USER=root
      - DB_PASSWD=your_secure_password
    volumes:
      - ./html:/var/www/html
    depends_on:
      - db
    restart: unless-stopped

  db:
    image: mysql:5.7
    container_name: <your-shop>-db
    environment:
      - MYSQL_ROOT_PASSWORD=your_secure_password
      - MYSQL_DATABASE=prestashop
    volumes:
      - ./mysql:/var/lib/mysql
    restart: unless-stopped
EOF

Tag obrazu PrestaShop musi dokładnie odpowiadać wersji produkcyjnej. Jeśli produkcja działa na 1.7.8.11, należy użyć prestashop/prestashop:1.7.8.11, a nie 1.7. Widzieliśmy, jak sprzedawcy godzinami gonili widmowe błędy, ponieważ staging był na 1.7.8.10, a produkcja na 1.7.8.11, różnica na tyle mała, że wygląda identycznie, ale na tyle duża, że zachowanie jest inne.

Krok 2: zrzut produkcji

Należy połączyć się przez SSH z produkcją i uruchomić mysqldump. Na działającym sklepie warto użyć --single-transaction, aby nie zablokować tabeli zamówień, gdy klienci finalizują zakupy:

# Na serwerze produkcyjnym
mysqldump -u root -p prestashop > ~/prestashop_backup.sql

# Pobrać na komputer lokalny / serwer staging
scp user@production-server:~/prestashop_backup.sql ./

Krok 3: import do stagingu

# Uruchomić kontenery
docker compose up -d

# Odczekać ~30 sekund na inicjalizację MySQL, następnie zaimportować
docker exec -i <your-shop>-db mysql -u root -pyour_secure_password prestashop < prestashop_backup.sql

Jeśli MySQL zgłosi problem z zestawem znaków podczas importu, należy dodać SET NAMES utf8mb4; na początku pliku SQL. Spędziliśmy więcej czasu, niż chcielibyśmy przyznać, debugując podwójnie zakodowane UTF-8 na stagingu, którego na produkcji nie było.

Krok 4: kopiowanie plików produkcyjnych

# Zsynchronizować pliki produkcyjne z katalogiem html stagingu
rsync -avz --delete \\
  user@production-server:/var/www/html/ \\
  ./html/ \\
  --exclude='var/cache/*' \\
  --exclude='var/logs/*' \\
  --exclude='app/config/parameters.php'

Z rsync należy zawsze wykluczać parameters.php. Dane logowania do bazy w tym pliku należą do produkcji, jeśli pozwoli się rsync je nadpisać, sklep staging spróbuje połączyć się z produkcyjną bazą danych, co jest najgorszym możliwym skutkiem „konfigurowania stagingu”. Nauczyliśmy się tego boleśnie przy projekcie klienta w 2017 roku i od tego czasu automatycznie dopisujemy ten przełącznik wykluczenia.

Należy też wykluczyć wszelkie katalogi runtime, do których sklep zapisuje na produkcji. Sitemapy, generowane obrazy, które nie są potrzebne, katalogi kopii zapasowych, klucze licencyjne. rsync --delete czyści stronę docelową, a nadgorliwe użycie rsync nieraz na naszych oczach usuwało wygenerowane sitemapy i psuło Google Search Console.

Krok 5: przepisanie adresów URL i wyczyszczenie cache

Najczęstsza przyczyna pytania „dlaczego mój sklep staging nie działa”: ps_shop_url nadal wskazuje na produkcję. Należy to naprawić:

docker exec -i <your-shop>-db mysql -u root -pyour_secure_password prestashop -e "
  UPDATE ps_shop_url SET domain='staging.yourshop.com', domain_ssl='staging.yourshop.com' WHERE id_shop=1;
  UPDATE ps_configuration SET value='staging.yourshop.com' WHERE name IN ('PS_SHOP_DOMAIN','PS_SHOP_DOMAIN_SSL');
"

Należy zaktualizować html/app/config/parameters.php, wpisując dane logowania do bazy staging z pliku compose. Następnie trzeba wyczyścić cache:

docker exec <your-shop> rm -rf /var/www/html/var/cache/*

Pominięcie czyszczenia cache sprawia, że skompilowane szablony Smarty nadal zawierają adres URL produkcji, co skutkuje pętlami przekierowań z powrotem do sklepu produkcyjnego. Na każdym sklepie używającym OPcache (czyli na wszystkim, co jest na produkcji) należy dodatkowo zrestartować PHP-FPM lub wywołać endpoint resetujący OPcache.

Opcja 2: subdomena na hostingu współdzielonym

Docker nie jest dostępny na cPanel, Plesk ani DirectAdmin. Ten sam efekt można uzyskać dzięki subdomenie, drugiej bazie danych i kopii plików.

Utworzenie subdomeny

  1. W panelu hostingu należy przejść do Subdomeny lub Domeny
  2. Należy dodać staging.yourshop.com
  3. Należy skierować ją do nowego katalogu, np. /home/user/staging.yourshop.com

Utworzenie osobnej bazy danych

  1. Należy otworzyć Bazy danych MySQL
  2. Należy utworzyć bazę o nazwie np. user_staging
  3. Należy utworzyć lub przypisać użytkownika z pełnymi uprawnieniami do tej bazy

Kopiowanie plików i import zrzutu

Przez SSH:

cp -r /home/user/public_html/* /home/user/staging.yourshop.com/
# Eksport produkcji
mysqldump -u user -p production_db > ~/staging_import.sql

# Import do stagingu
mysql -u user -p staging_db < ~/staging_import.sql

Należy zedytować app/config/parameters.php (lub config/settings.inc.php na 1.6), aby wskazywał nową bazę danych, a następnie uruchomić to samo SQL przepisujące adresy URL z opcji 1, krok 5. Nie wolno zapomnieć o usunięciu var/cache/ na koniec.

Opcja 3: lokalne środowisko deweloperskie z XAMPP/MAMP

Sprawdza się przy pracy typu „szybkie sprawdzenie ekranu administracyjnego tego modułu przez dziesięć minut”, ale do czegokolwiek innego jest bezużyteczne. Wersja PHP, wersja MySQL, model uprawnień plików oraz rozszerzenia na poziomie systemu operacyjnego będą się różnić od serwera produkcyjnego. Sami korzystamy z lokalnych stosów, lecz nigdy jako ostatniego testu przed wdrożeniem: wszystko, co ma wkrótce trafić na produkcję, jest ponownie testowane na serwerowym stagingu odwzorowującym środowisko produkcyjne.

Po konfiguracji: rzeczy, które dają się we znaki, jeśli się o nich zapomni

Natychmiast zablokować wychodzące wiadomości e-mail

Baza danych stagingu zawiera każdy prawdziwy adres e-mail klienta. Wyzwolenie resetu hasła, potwierdzenia zamówienia lub crona z powiadomieniami o stanie magazynowym sprawia, że te wiadomości trafiają do prawdziwych klientów. Widzieliśmy, jak sprzedawcy publicznie przepraszali, ponieważ ich cron na stagingu wysłał „Zamówienie zostało wysłane” do tysiąca prawdziwych klientów, których zamówienia w rzeczywistości nie zostały wysłane.

Należy przejść do Parametry zaawansowane → E-mail i wybrać jedną z opcji:

  • Ustawić metodę na „Nigdy nie wysyłaj wiadomości e-mail”: jedyną w pełni bezpieczną opcję
  • Przekierować całość przez Mailtrap, aby nadal można było sprawdzać wyrenderowane wiadomości bez ich dostarczania

Wyłączyć moduły płatności

Stripe, PayPal, Klarna, Adyen: wszystko, co jest połączone z aktywnym kontem rozliczeniowym. Na stagingu należy albo całkowicie wyłączyć te moduły, albo przełączyć każdy z nich w tryb sandbox/test. To samo dotyczy interfejsów API przewoźników (etykiety UPS, DHL, GLS) oraz każdego modułu wywołującego usługę zewnętrzną o płatnych skutkach ubocznych.

Zablokować wyszukiwarki

Sklep staging zaindeksowany przez Google to katastrofa duplikacji treści. Dla pewności należy zadbać o trzy rzeczy:

  • Wyłączyć mapę witryny XML w Parametry sklepu → Ruch i SEO
  • Umieścić w katalogu głównym plik robots.txt z User-agent: * oraz Disallow: /
  • Jeszcze lepiej całkowicie zablokować dostęp publiczny (następna sekcja), aby Google w ogóle nie dotarło do sklepu

Zabezpieczyć sklep listą dozwolonych adresów IP

Najbardziej niezawodnym podejściem jest ograniczenie dostępu po adresie IP na poziomie Apache lub Nginx. Tryb konserwacji można obejść, jeśli ustawienie listy dozwolonych adresów IP zawiera błąd, a uwierzytelnianie HTTP Basic Auth czasem psuje moduły intensywnie korzystające z AJAX-a (widzieliśmy, jak rozkłada nasze własne panele administracyjne, gdy przeglądarka nie potrafiła przenieść nagłówka uwierzytelniania przez XHR). Lista dozwolonych adresów IP na poziomie serwera WWW przechwytuje wszystko, zanim PrestaShop w ogóle się uruchomi.

Ustawienia trybu konserwacji PrestaShop z przełącznikiem sklepu, polem IP konserwacji i własnym komunikatem

Utrzymywanie stagingu w synchronizacji z produkcją

Sklep staging przestarzały o trzy miesiące jest gorszy niż brak stagingu, daje fałszywe poczucie pewności. My odświeżamy swoje według harmonogramu oraz przed każdym istotnym wdrożeniem.

Kiedy odświeżać

  • Przed każdą znaczącą zmianą: aktualizacją modułu, aktualizacją rdzenia, podbiciem wersji PHP, przeróbką motywu
  • Co najmniej raz w miesiącu w przypadku aktywnego rozwoju
  • Po każdej dużej zmianie w katalogu na produkcji, nowych drzewach kategorii, strukturalnych zmianach produktów, przetasowaniach cech/atrybutów

Skrypt odświeżający (Docker)

#!/bin/bash
# refresh-staging.sh: Pobrać najnowsze dane produkcyjne do stagingu

# 1. Zrzucić bazę danych produkcji
ssh production "mysqldump -u root -p'PASS' prestashop" > /tmp/staging_refresh.sql

# 2. Zaimportować do stagingu
docker exec -i <your-shop>-db mysql -u root -p'your_secure_password' prestashop < /tmp/staging_refresh.sql

# 3. Naprawić adresy URL
docker exec -i <your-shop>-db mysql -u root -p'your_secure_password' prestashop -e "
  UPDATE ps_shop_url SET domain='staging.yourshop.com', domain_ssl='staging.yourshop.com' WHERE id_shop=1;
  UPDATE ps_configuration SET value='staging.yourshop.com' WHERE name IN ('PS_SHOP_DOMAIN','PS_SHOP_DOMAIN_SSL');
"

# 4. Zsynchronizować pliki
rsync -avz --delete production:/var/www/html/ ./html/ --exclude='var/cache/*' --exclude='app/config/parameters.php'

# 5. Wyczyścić cache
docker exec <your-shop> rm -rf /var/www/html/var/cache/*

echo "Staging refreshed."

Błędy, które nadal widzimy u sprzedawców

Pozostawione klucze API produkcji

Liczba sklepów staging, które audytowaliśmy, a które po cichu wysyłały prawdziwe obciążenia Stripe, odpytywały prawdziwe API przewoźników o etykiety śledzenia na żywo lub zjadały limity prawdziwego API, ponieważ klucze przyszły razem z bazą danych, jest niepoliczalna. Każde zewnętrzne dane uwierzytelniające należy zmienić na klucz sandbox na stagingu w chwili, gdy baza danych trafi na miejsce, jeszcze przed otwarciem panelu administracyjnego.

Wciąż uruchamiające się crony

Jeśli na produkcji skonfigurowano zadania cron (przypomnienia o porzuconych koszykach, synchronizacja stanów magazynowych, generowanie feedów, odnawianie licencji), należy sprawdzić, czy panel hostingu lub timery systemd nie uruchamiają tych samych zadań na nazwie hosta stagingu. Mieliśmy klienta, którego sklep staging przez dwa tygodnie radośnie wysyłał prawdziwe aktualizacje stanów magazynowych Allegro, zanim ktokolwiek to zauważył.

Oba panele administracyjne otwarte w tej samej przeglądarce

Ciasteczka panelu administracyjnego PrestaShop są ograniczone do domeny, ale konflikty sesji i tak się zdarzają, gdy oba sklepy są zalogowane w tej samej przeglądarce. Do stagingu należy używać osobnej przeglądarki, osobnego profilu lub okna incognito. Każdy członek naszego zespołu ma dedykowany profil Firefox do sklepów staging klientów.

Kiedy testować na stagingu, a kiedy produkcja wystarczy

Zawsze najpierw na staginguBezpiecznie bezpośrednio na produkcji
Aktualizacje rdzenia PrestaShop (1.7 → 8, 8 → 9)Edycje treści, strony CMS, opisy produktów
Instalacje modułów lub podbicia wersji głównejZmiany cen
Aktualizacje motywu lub praca nad motywem potomnymWłączanie/wyłączanie już przetestowanych modułów
Podbicia wersji PHPDodawanie nowych produktów, kategorii, tagów
Własny kod, nadpisania, dekoratory usługEdycje reguł wysyłki lub podatków
Migracje bazy danych lub strukturalne SQLDrobne korekty tłumaczeń

Warte tej godziny

Pierwsza konfiguracja stagingu zajmuje około godziny. Odświeżenie, gdy skrypt jest już gotowy, to pięć minut. Za pierwszym razem, gdy staging wychwyci aktualizację modułu, która zepsułaby proces realizacji zakupu, inwestycja zwróci się dziesięciokrotnie, i widzieliśmy, jak dzieje się to na prawdziwych sklepach, które prowadzimy. Po Docker sięgnęlibyśmy w przypadku posiadania VPS-a lub dedykowanej maszyny; klonowanie na subdomenie to właściwy wybór na hostingu współdzielonym. Tak czy inaczej, cel jest ten sam: nic nieprzetestowanego nie dotyka klientów.

Jeśli staging jest konfigurowany właśnie po to, by testować nasze moduły, nasz program Wypróbuj przed zakupem daje pełne 30-dniowe demo dowolnego modułu. Można go zainstalować na stagingu, przetestować w boju i zdecydować przed zapłatą.

Powiązane materiały

Powiązane moduły

Powiązane pytania

Ładowanie...
Do góry