Skip to main content

e24Cloud Struktura skalowalnego serwisu WWW

Przy okazji konkursu chmurowisko (https://chmurowisko.pl/e/) postanowiłem stworzyć przykładowy serwis WWW na chmurze e24cloud.com.

Tworząc złożone serwisy WWW myślimy, że nasz projekt będzie stać zawsze. Nikt ani nic nam nie zagraża. Okazuje się, że serwis może bardzo szybko zniknąć z internetu, i ciężko szybko go przywrócić do działania.

Powody, kiedy serwis może zniknąć z sieci:

  • atak na serwer (np DDOS)
  • nagły wzrost liczby użytkowników (np z 1000 do 100 000 dziennie)
  • złe wdrożenie poprawek na serwerze (czynnik ludzki)
  • awaria serwera
    • administrator coś nabroił, lub…
    • w serwerze popsuły się elementy, które są ważne
  • awaria całego regionu (całej firmy hostingowej)
    • serwer może działać, ale błąd w serwerowni nie pozwala dostać się do niego dostać
    • problemy z łączem do serwerowni (ile to się razy zdarzało, że pan w koparce przerwał światłowód)

Powyżej znajduje się kilka propozycji co może się stać. Powodów, może być mnóstwo. Jak zwiększyć szanse, że nasza strona będzie widoczna zawsze? Czytaj więcej

[xx MyFood] Koniec DSP … a zarazem początek…

Od ostatniego postu minęło 2,5 miesiąca. Nie udało mi się zrealizować projektu.

Czuje smutek z tego powodu.

Każdemu brakuje czasu, brakło i mi.Okazało się, że projekt jest bardzo ambitny, gdzie czekała mnie spora dawka nauki. Pojawiły się inne priorytety i cele.

Ale nie martwcie się :) , projekt nie będzie zarzucony. Planuje go skończyć w przyszłości. Myślę, że zostanie dalej jako Open Source.

Konkurs DSP się skończył. Zapraszam na listę finalistów http://uczestnicy.dajsiepoznac.pl/finalisci

Czy był to stracony czas?

Nie. Od kilku lat myślałem nad blogiem, zawsze się bałem go założyć. Okazało się, że to nic trudnego :) i zawsze jest co napisać.

Znalazłem nowe cele, i priorytety w życiu. Powoli przeorganizowuje swoje życie.

Same plusy.

[06 MyFood] Front hierarchia

Stało się… mam opóźnienie 2 tygodniowe, i można powiedzieć że wykorzystałem regulaminową przerwę w pisaniu.

Tak się zaczytałem w 1 tygodniu, że stwierdziłem, że nic nie umiem jeszcze. I nie napisałem nic :(

Drugi tydzień wolnego zużyłem przez natłok zadań w pracy i życiu.

Poniżej rozpiszę hierarchie z WebClient, która będzie obsługiwała Front aplikacji z wykorzystaniem React JS.

Trochę czasu mi zeszło na przygotowanie serwera JS, miałem problem przygotować wszystko. Co chwile coś mi nie działało albo tworzyłem małego potworka.

Znalazłem jednak artykuł na stronie https://nafrontendzie.pl/podstawy-reactjs-kompletny-tutorial/ i stworzyłem pusty projekt, z podstawowymi ustawieniami.

Projekt się pewnie jeszcze zmieni, ponieważ startowy projekt używa „Karma Mocha” do testów. A ja chciałem użyć „JEST” lub „Cucumber w wersji JS

https://github.com/mfratczak/myfood-generator/tree/master/WebClient

Odpalanie serwera front

# uruchomienie w trybie dev
npm start # lub
npm run serve

# uruchomienie wykorzystując pliki z katalogu dist (wersja produkcyjna)
npm run serve:dist

# generowanie plików do katalogu dist + kopiowanie zasobów statycznych
npm run dist

# urumienie testów
npm test

# uruchomienie testów wraz z re-testem przy zmianie pliku
npm run test:watch

# uruchomienie lintera (dzieje się też automatycznie po testach)
npm run lint

# czyszczenie katalogu dist
npm run clean

# kopiowanie statycznych zasobów
npm run copy
Przy bawieniu się dockerem, testowaniu, wielokrotnym odpalaniu środowisk, zdarza się ze nic nie chce działać.

Czemu?

Odpalanie testowych środowisk powoduje ze ściągamy zcachowane warstwy, lub generujemy nowe. Ponowne generowanie, drobne zmiany itp powodują dwa problemy:

  • ilość miejsca na serwerze maleje
  • obraz środowiska, który chciałbyś odpalić od zera powinieneś usunąć i odpalić jeszcze raz

Gdy odpalamy dockera:

to zostają ściągnięte wszystkie warstwy (layers) potrzebne do zbudowania środowiska. Jeśli budujesz środowisko, to jest ono budowane lokalnie.

Normalnie możesz zatrzymać kontenery:

lub całkowicie je usunać:

Czym to się różni?

Jeśli tworzysz nowy kontener, dla jednego obrazu, prawdopodobnie posiada on skrypty inicjujące, które ustawiają wszystko co trzeba do jakiegoś systemu (np system do zarządzania zadaniami Redmine). Kontenery również zapisują dane wewnątrz siebie dane (jeśli nie wyprowadziłeś ich na zewnątrz).

Aby nie stracić tych ustawień, można zastosować STOP. (np wchodzisz w dany kontener i instalujesz coś ręcznie, i się bawisz poznając nowe rzeczy, dzięki stop tego nie stracisz)

Nie powinniśmy zapisywać jednak danych wewnątrz kontenera. Powinniśmy wyjść z założenia, że cokolwiek w nim jest, można usunąć i zresetować do stanu początkowego.

Dlatego jak nie bawię się, lub nie instaluje ręcznie bibliotek celem jakichś testów, to używam DOWN.

Jednym słowem usuwam kontener, i tworze go znowu.

 

Co gdy nie można usunąć obrazów i kontenerów?

Zdarza się, że w testach tak zamieszamy :) przy tworzeniu multum wersji, zmian itp (standard), że nie można wygenerować nic nowego, lub nie widać zmian.

Wtedy tutaj przychodzą do pomocy polecenia dockerowe.

Zatrzymywanie wszystkich kontenerów dockerowych

Usuwanie wszystkich kontenerów, również które są ukryte na pierwszy rzut oka

Usuwanie wszystkich obrazów dockerowych na serwerze (ściągnięte, lub wygenerowane przez nas)

Usuwanie reszty obrazów,  jeśli nie usuneło wszystkiego a jest na liście docker images

Zdarza się, że nie można usunąć obrazów, ponieważ pojawia się błąd:

Error response from daemon: conflict: unable to delete ba62b42dad38 (cannot be forced) – image has dependent child images

Musimy wtedy skorzystać z flagi Force. (mówimy oczywiście o serwerze developerskim, gdzie możemy wszystko usuwać i niczego się nie obawiać, że stracimy dane :) )

Sprawdzamy czy usuneliśmy wszystko możemy poleceniami

 

Aliasy – czyli jak ułatwić sobie pracę

Sam korzystam z aliasów, które można znaleźć tutaj https://github.com/tcnksm/docker-alias/blob/master/zshrc

Krótkie wyjaśnienie: https://kartar.net/2014/03/useful-docker-bash-functions-and-aliases/

Jednym słowem, używam głównie poleceń:

dstop – zatrzymanie WSZYSTKICH kontenerów

drm – usunięcie wszystkich kontenerów

dri – usunięcie wszystkich obrazów

dalias – spis wszystkich aliasów dockerowych

dex nazwa-kontenera bash – wejście w dany kontener

 

I to tyle :) 

Mogłem dać spis poleceń na usuwanie pojedynczych obrazów lub kontenerów, ale o tym wszędzie piszą :) więc na pewno umiesz to robić, lub znajdziesz rozwiązanie.

Na lokalnym komputerze, korzystam z wszystkich poleceń, usuwam wszystko itp. Na serwerach w internecie, trzeba wsiąść pod uwagę, że możesz posiadać limit transferu. Więc każdorazowe usuwanie obrazów, i zaciąganie ich, spowoduje jego zużywanie. Ja wtedy usuwam, konkretny obraz (jeśli trzeba)

W razie pytań, lub moich błędów, pisz !

 

 

Docker, kilka wskazówek

Przy bawieniu się dockerem, testowaniu, wielokrotnym odpalaniu środowisk, zdarza się ze nic nie chce działać.

Czemu?

Odpalanie testowych środowisk powoduje ze ściągamy zcachowane warstwy, lub generujemy nowe. Ponowne generowanie, drobne zmiany itp powodują dwa problemy:

  • ilość miejsca na serwerze maleje
  • obraz środowiska, który chciałbyś odpalić od zera powinieneś usunąć i odpalić jeszcze raz

Gdy odpalamy dockera:

to zostają ściągnięte wszystkie warstwy (layers) potrzebne do zbudowania środowiska. Jeśli budujesz środowisko, to jest ono budowane lokalnie.

Normalnie możesz zatrzymać kontenery:

lub całkowicie je usunać:

Czym to się różni?

Jeśli tworzysz nowy kontener, dla jednego obrazu, prawdopodobnie posiada on skrypty inicjujące, które ustawiają wszystko co trzeba do jakiegoś systemu (np system do zarządzania zadaniami Redmine). Kontenery również zapisują dane wewnątrz siebie dane (jeśli nie wyprowadziłeś ich na zewnątrz).

Aby nie stracić tych ustawień, można zastosować STOP. (np wchodzisz w dany kontener i instalujesz coś ręcznie, i się bawisz poznając nowe rzeczy, dzięki stop tego nie stracisz)

Nie powinniśmy zapisywać jednak danych wewnątrz kontenera. Powinniśmy wyjść z założenia, że cokolwiek w nim jest, można usunąć i zresetować do stanu początkowego.

Dlatego jak nie bawię się, lub nie instaluje ręcznie bibliotek celem jakichś testów, to używam DOWN.

Jednym słowem usuwam kontener, i tworze go znowu.

 

Co gdy nie można usunąć obrazów i kontenerów?

Zdarza się, że w testach tak zamieszamy :) przy tworzeniu multum wersji, zmian itp (standard), że nie można wygenerować nic nowego, lub nie widać zmian.

Wtedy tutaj przychodzą do pomocy polecenia dockerowe.

Zatrzymywanie wszystkich kontenerów dockerowych

Usuwanie wszystkich kontenerów, również które są ukryte na pierwszy rzut oka

Usuwanie wszystkich obrazów dockerowych na serwerze (ściągnięte, lub wygenerowane przez nas)

Usuwanie reszty obrazów,  jeśli nie usuneło wszystkiego a jest na liście docker images

Zdarza się, że nie można usunąć obrazów, ponieważ pojawia się błąd:

Error response from daemon: conflict: unable to delete ba62b42dad38 (cannot be forced) – image has dependent child images

Musimy wtedy skorzystać z flagi Force. (mówimy oczywiście o serwerze developerskim, gdzie możemy wszystko usuwać i niczego się nie obawiać, że stracimy dane :) )

Sprawdzamy czy usuneliśmy wszystko możemy poleceniami

 

Aliasy – czyli jak ułatwić sobie pracę

Sam korzystam z aliasów, które można znaleźć tutaj https://github.com/tcnksm/docker-alias/blob/master/zshrc

Krótkie wyjaśnienie: https://kartar.net/2014/03/useful-docker-bash-functions-and-aliases/

Jednym słowem, używam głównie poleceń:

dstop – zatrzymanie WSZYSTKICH kontenerów

drm – usunięcie wszystkich kontenerów

dri – usunięcie wszystkich obrazów

dalias – spis wszystkich aliasów dockerowych

dex nazwa-kontenera bash – wejście w dany kontener

 

I to tyle :) 

Mogłem dać spis poleceń na usuwanie pojedynczych obrazów lub kontenerów, ale o tym wszędzie piszą :) więc na pewno umiesz to robić, lub znajdziesz rozwiązanie.

Na lokalnym komputerze, korzystam z wszystkich poleceń, usuwam wszystko itp. Na serwerach w internecie, trzeba wsiąść pod uwagę, że możesz posiadać limit transferu. Więc każdorazowe usuwanie obrazów, i zaciąganie ich, spowoduje jego zużywanie. Ja wtedy usuwam, konkretny obraz (jeśli trzeba)

W razie pytań, lub moich błędów, pisz !

 

 

[MyFood] Docker – api, web, loadbalancing, ssl (darmowy),mysql – pełny config

Nadszedł czas wdrożenia środowiska developerskiego, oraz środowiska produkcyjnego. Od początku moim planem było wykorzystanie dockera. Dzięki niemu łatwo wszystko postawić na nowym serwerze. Najtrudniejsze jak zwykle było stworzenie pierwszy raz kompleksowej konfiguracji, z wszystkimi elementami, które są potrzebne w każdym projekcie.

Co to docker przeczytać możesz tutaj: 1, 23

Spis wszystkich kontenerów

  • serwer api
  • serwer api2 (drugi serwer do testu loadbalancingu – normalnie w swoim projekcie nie używam, dlatego jest to kopiuj / wklej api)
  • serwer web
  • baza danych (mysql)
  • phpmyadmin (tylko dla dev)
  • haproxy
  • letsencrypt (odnawiany 90 dniowy certyfikat SSL)

Dlaczego tyle kontenerów i w czym problem

Zasadą w świecie dockera jest „1 kontener = 1 zadanie” . A więc nie powinno w jednym kontenerze instalować się kilku funkcjonalności: serwer www, skrypty (np php), baza danych. Bardzo ciężko pilnować gdy coś się popsuje , oraz ciężko wgrać aktualizacje do systemu. Dlatego wszystko wydzielamy do kontenerów, która lista jest powyżej.

Problem:

Nie można do kilku kontenerów przydzielić tego samego portu.

Czyli nie można jak niżej:

  • web – nasłuchuje na porcie 80
  • api – nasłuchuje na porcie 80

Przy próbie odpalenia pojawi się błąd:

Co oznacza tyle że port już jest używany i nie można odpalić kontenera. Jest to oczywiście logiczne, bo jak wchodzimy np na localhost, to system by nie wiedział na który kontener przekierować ruch.

Kolejny problem to domeny. Konfiguracja dockera nie używa takiego pojęcia jak domena / subdomena. Każdy kontener sam powinien rozpoznawać domenę, i serwować odpowiednie dane.

W konfiguracji dockera nie możemy podzielić ruchu dla danej domeny i dla danego portu.

Jak to zrobić?

Musimy sami to obsłużyć prz pomocy serwera proxy. Użytkownik wchodzi na stronę w danej domenie, to serwer proxy wyświetla mu dane z odpowiedniego kontenera dockera.

Serwer proxy rozpoznaje domene, oraz port, i odpowiednio serwuje dane.

Rozwiązań jest kilka, np:

  • na serwerze (host) instalujemy proxy i w konfiguracji ustawiamy i przekierowujemy domenę na dany kontener (1)
  • wykorzystujemy tylko kontenery dockerowe, i serwer proxy również jest w nim (2)

Wybieram rozwiązanie 2. – dobrze jest mieć porządek :)

Serwer Proxy – HAProxy – Load Balancing – SSL

Postawienie proxy, pozwala nam zainstalować również certyfikaty SSL, i je odpowiednio skonfigurować. Nie trzeba tego robić w każdym kontenerze. Wystarczy w jednym :)

Wykorzystamy tutaj certyfikaty „Let’s encrypt” https://letsencrypt.org/ – pozwala nam to za DARMO posiadać na swojej domenie ssl.

Certyfikat jest ważny 90 dni. Całe generowanie i pobieranie jest automatyczne, więc nie musimy się o to martwić.  PEŁNA AUTOMATYKA !

Serwer proxy również umożliwia wykorzystanie loadbalancingu. Co to jest? Jeśli ustawimy dla danego adresu np: https://api.myfood.love/ dwa kontenery. To proxy dzieli ruch po połowie i wysyła go to kontenera. Jak wejdziesz na testowy serwer api to po odświeżeniu strony będą się na przemiennie pojawiać informacje:

Ip:xxx.xxx.xxx.xxx Host: 8ca086de8527

oraz

Ip: xxx.xxx.xxx.xxx Host: cccc89c4b35c

Dla przykładu wyświetlam ip oraz host. Host się zmienia w zależności od wybranego kontenera.

Po co load balancing?

Jeśli strona posiada duży ruch i maszyna nie wytrzymuje, to można dodać kolejną maszynę i obsłużyć dwa razy większy ruch. Klient nawet nie zauważy że ruch idzie z dwóch maszyn.

Konfiguracja środowiska – docker-compose.yml

Wszystkie obrazy jakie wykorzystuje znajdują się w pliku docker-compose.yml. Dzięki temu wystarczy odpalić jedno polecenie (docker-compose up -d) i dzieje się magia.

Oddzielnie stworze post z poleceniami, trickami itp, więc tutaj tylko suche fakty na temat pliku konfiguracyjnego :)

Aktualnie cały plik konfiguracyjny jest w wersji „3.1”. Oznacz to, że wersja dockera jaka powinna być to min. 1.13, a wersja docker-compose 1.11

Pełny plik konfiguracyjny (api z load balancingiem)

Pełne wyjaśnienie – hierarchia plików i katalogów https://github.com/mfratczak/myfood-generator

api.myfood.love – load balancing z api i api2

  • build – budowanie kontenera gdzie plik Dockerfile znajduje się w podkatalogu
    • context: Docker/python – katalog kontenera (Docker/python)
    • dockerfile: Dockerfile – nazwa pliku z konfiguracją kontenera, można np zmienic na Dockerfile-dev i będą ustawienia developerskie (jeśli taki plik istnieje)
  • environment: – zmienne systemowe przekazywane do środka kontenera
    • FORCE_SSL=yes – zmienna wykorzystywana w kontenerze haproxy – bardzo ważna zmienna dla haproxy i certyfikatu SSL
    • VIRTUAL_HOST=xxx – spis hostów które kierować mają na dany kontener, można podać kilka  – bardzo ważna zmienna dla haproxy i certyfikatu SSL
  • volumes: – mapowanie katalogów, aby projekt znajdował się poza kontenerem. Dzięki temu można usunąć całkowicie kontenery i utworzyć jeszcze raz a dane zostają
    • ./WebServer:/app – w katalogu WebServer znajduje się cały projekt systemu Api
  • links: – połączenie między kontenerami, kontener API ma dostęp do kontenera MYSQŁ, gdzie znajduje się baza danych
  • command: python server.py – możliwość zadeklarowania polecenia z jakim ma się uruchomić kontener, tutaj odpala serwer pythona, można dla wersji developerskiej zrobić np: python server-dev.py, czyli odpalić serwer pythona z ustawieniami pełnego logowania itp
  • restart: always – deklaracja co ma się stać jak kontener padnie, lub polecenie (python server.py) spowoduje błąd, czyli szybki restart maszyny
  • network_mode: „bridge” – wybór podsieci

Drobne wyjaśnienie odnośnie network_mode. Normalnie wszystkie kontenery z danego katalogu (z jednego pliku dockerfile) znajdują się w osobnej podsieci. Okazuje się, że serwer proxy działa tylko w głównej podsieci o nazwie „bridge”, dlatego wszystkie kontenery są dodane do niej.

Drugie drobne wyjaśnienie to FORCE_SSL. Dla testów lokalnych linijkę tą mam wyłączoną, ponieważ dla lokalnych domen (localhost, itp) nie można utworzyć certyfikatu

Ustawienie: VIRTUAL_HOST w api i w api2 na te same domeny powoduje, że proxy stosuje load balancing i dzieli ruch między te dwa kontenery.

myfood.love – serwer web

W pliku konfiguracyjnym powyżej, tworzę również serwer pythona do testów. Jednak różnicą jest zmiana w VIRTUAL_HOST, co powoduje, że ruch tutaj jest obsługiwany tylko przez jeden kontener.

W przyszłości tutaj będzie zmiana pliku konfiguracyjnego na ten z katalogu Docker/npm/Dockerfile (teraz jest tylko szybka kopia aby sprawdzić działanie haproxy)

– mysql oraz phpmyadmin

  • image: sameersbn/mysql:latest – popularny gotowy obraz mysql (posiadają również postgresql itp)
  • volumes: – ./Data/database:/var/lib/mysql – cała baza została wydzielona do podkatalogu database. Dzięki temu można wyłaczać i włączać kontener bazodanowy bez utraty danych
  • environment – zmienne z danymi do utworzenia pustej bazy

oraz

  • image: phpmyadmin/phpmyadmin – gotowy obraz z phpmyadminem
  • ports: – „9999:80” – kontener dostępny np pod localhost:9999 lokalnie, lub myfood.love:9999 w sieci, w wersji produkcyjnej dostęp do phpmyadmina powinien być WYŁĄCZONY!!!
  • environment: PMA_HOST: mysql – zmienna wskazuje na kontener w której jest baza

Małe wyjaśnienie: Przy tworzeniu bazy (pierwsze odpalenie kontenera mysql) dane są zapisane w katalogu Data/database. Tworzona jest czysta baza o podanej nazwie, loginie i haśle. Restart / Wyłączenie / Usunięcie i ponowne utworzenie kontenera nie powoduje utraty danych bazy. Aby usunąć dane, należy opróżnić katalog. Po opróżnieniu katalogu, ponowne uruchomienie kontenera bazodanowego powoduje utworzenie czystej bazy.

– letsencrypt

  • image: interaction/letsencrypt:master – gotowy obraz
  • environment:
    • DOMAINS=api.myfood.love myfood.love – domeny które powinny mieć ssl, dla nich jest generowany certyfikat, nie mogą to być domeny lokalne lub zmapowane w pliku host systemu
    • [email protected] – email który jest zawarty w certyfikacie, powinien to być istniejący adres email
  • expose: – „80” – port na którym nasłuchuje kontener
  • volumes:
    • ./Data/letsencrypt:/etc/letsencrypt – zmapowany katalog z wygenerowanymi certyfikatami
    • ./Logs/letsencrypt:/var/log/letsencrypt – zmapowany katalog gdzie można przejrzeć logi

– haproxy – serwer proxy przez który przechodzi cały ruch z portu 80 i 443 (każda domena i subdomena)

  • image: interaction/haproxy:master
  • links: – kontener musi być podłączony do letsencrypt oraz do wszystkich kontenerów na który ma być kierowany ruch
  • depends_on: – polecenie to sprawia, że haproxy odpalane jest na końcu, oraz że zależy jego działanie od innych kontenerów
  • ports: – „80:80” – „443:443” – cały ruch przechodzi przez ten kontener, potrzebne są do obsługi dwa porty 80 (zwykły ruch http) oraz 443 (ruch https)
  • volumes: – ./Data/letsencrypt:/etc/letsencrypt – haproxy oraz letsencrypt muszą dzielić ten sam katalog, z wygenerowanymi certyfikatami

Kilka spraw:

Ważną kwestią aby haproxy działał z SSL, to współdzielenie katalogu letsencrypt. Kontener letsencrypt przy odpaleniu oraz co 24h sprawdza certyfikat i generuje nową wersje. Gdy haproxy wykryje że pliki w katalogu się zmieniły, uaktualnia certyfikaty u siebie. Nigdy więc nie wygaśnie certyfikat SSL ponieważ jest on generowany co 24h

Dodatkowo można wydzielić haproxy razem z letsencrypt z pliku konfiguracyjnego dockerfile, i utworzyć 2 kontenery globalne.

Dzięki temu, w przyszłości można utworzyć całkiem nowe domeny, z nowymi kontenerami, i dodać ich obsługę w haproxy. Ale przykład podam następnym razem.

Koniec

Jeśli dotarłeś do końca, to podziwiam, i dziękuję. Jeśli uważasz, że można to rozpisać łatwiej, zostaw komentarz, na pewno zaktualizuje w przyszłości tą rozpiskę.

 

Ważne linki:

  • https://github.com/docker/dockercloud-haproxy – czysty haproxy bez SSL (przykład docker-compose >>)
  • https://github.com/ixc/letsencrypt-dockercloud-haproxy – użyty obraz haproxy z SSL ‚let’s encrypt
  • https://letsencrypt.org/ – darmowy certyfikat SSL
  • https://docs.docker.com/compose/compose-file/#dockerfile – opis dockerfile u źródeł

 

[05 MyFood] Hierarchia i podział projektu (docker, flask, react)

We wcześniejszym poście napisałem, że musiałem zrobić krok wstecz. Okazuje się, że musiałem zrobić kolejny krok wstecz.

Dlaczego?

Moim planem jest stworzenie projektu gdzie backend to flask. Będzie on serwował API, z którym komunikować się będzie front.

Na froncie stanie React, czyli technologia JS. Im więcej o nim czytam, i tworze tutoriale, tym bardziej mi się podoba :)

Moim błędnym podejściem było to, że python będzie odpowiadał za API, oraz serwował statyczną stronę. Na tej statycznej stronie miał być React.

Co tu jest błędnego?

Każda część projektu frontend i backend powinna być całkowicie oddzielnym bytem. Nie powinny być ze sobą powiązane. Front nie powinien być zależny od serwera API. Nie powinien być nawet na tym samym serwerze.

To oznacza że muszę przebudować hierarchie projektu.

Muszę wspomnieć, że mój błąd uświadomił mi kolega Dariusz (może kiedyś przekonam go do blogowania ;d )

Plusy:

  • możliwość łatwiejszego skalowania serwerem (baza, itp), wydzielenie backendu na inny serwer niż frontend
  • w razie potrzeby można zmienić technologię api, bez wpływu na front
  • możliwość łatwej modyfikacji wygładu aplikacji, bez ryzyka że coś popsujemy w danych
  • za rok może się okazać, że pojawi się coś lepszego niż React, dzięki oddzieleniu frontu od backendu nic nie stoi na przeszkodzie
  • łatwe stworzenie aplikacji mobilnej w dowolnej technologii dla dowolnego urządzenia (android, ios, windows) , cała komunikacja odbywać się będzie przez API,

Minusy:

  • konieczność poznania 2 technologii
  • … (jak wyjdzie w praniu to dopiszę :) )

Przebudowa repozytorium – zmiany

https://github.com/mfratczak/myfood-generator – wstępne zmiany

  • Docker
    • server backend
    • server frontend
    • server bazodanowy
  • WebClient
    • aplikacja React
  • WebServer
    • aplikacja Flask Api
  • docker-compose.yml (plik konfiguracyjny dockera)

Wstępna hierarchia jak wyżej. Prawdopodobnie się zmieni o elementy CI (Continuous Integration), Testy automatyczne, i kilka innych.

Do testów lokalnych, docker będzie odpalany na dwóch portach.

  • Port 80 -> localhost -> aplikacja web
  • Port 1025 -> localhost:1025 -> api backend

Docelowo jak już projekt zostanie wrzucony na domenę to podział będzie następujący:

  • http://myfood.love – front na porcie 80 (standardowo)
  • http://api.myfood.love – backend na porcie 80 (standardowo)

W kolejnym poście (mam już nadzieję) przygotuje aplikacje front i backend z „hello world”.

 

[03 MyFood] Stworzenie szablonu HTML

Od czego zacząć jak niczego nie ma

Wpis powiązany z projektem MyFood. Szczegóły tutaj »
  • Stworzenie repozytorium [zrobione] – https://github.com/mfratczak/myfood-generator
  • Stworzenie szablonu szablonu html [w trakcie]
  • Wgranie aktualnej wersji projektu na domenę [wymyślam nazwę domeny, masz propozycje? pisz!]

Github

Przy tworzeniu nowego repozytorium, github automatyzuje tworzenie pliku z licencją (wybrałem licencje MIT). Drugą rzeczą ułatwiającą życie jest utworzenie automatycznie pliku .gitignore na podstawie wybranej technologii projektu. Co daje ten plik?

Git sprawdza plik .gitignore, i przy kolejnym pushu, ignoruje pliki nie powiązane z projektem, lub pliki które są generowane automatycznie (cache, kompilacje itp).

Dzięki temu nie wysyłamy do repo zbędnych plików, oraz trzymamy porządek.

Czytaj więcej

[02 MyFood] Dlaczego nazwa projektu jest ważna?

Nazwa projektu

Zawsze jak tworzę projekt, lubię nadawać im nazwy. Najlepiej aby nazwa mówiła coś o projekcie, np. Food Menu Generator. Brak nazwy męczy mnie psychicznie.

Ciągle o tym myślę :D

Dlaczego najlepsza nazwa jest po angielsku? Bo celuje w cały świat :D. Człowiek jednak chce umieścić swój projekt w sieci, i nagle sobie uświadamia że domena: food-menu-generator.com to nie jest najlepsza nazwa.

Jak to powiedzieć? Czy druga osoba to zapamięta? Czy nie ma czegoś prostszego?

Kilka godzin spędziłem na wymyślaniu nazwy domeny. Wniosek: wszystko co wymyśliłem zajęte. Domeny z reklamami, albo jakieś śmieci. Nazwy miałem fajne (?) np. foodly.com, mealio.com (i tysiące innych końcówek) .

Ale znalazłem. Od dzisiaj, projekt  nazywa się MyFood Generator. Domena: http://myfood.love

W tytule posta będzie zawsze znajdować się będzie nazwa MyFood dla treści powiązanych z projektem.

Nazwa jest, projekt się toczy, w końcu można psychicznie odetchnąć.

[01 MyFood] Geneza projektu, i jego cele

Start Projektu MyFood Generator

Jeśli śledzisz mojego bloga, to wiesz, że startuje w konkursie „Daj się poznać” edycja 2017. Dla tego konkursu wybrałem projekt „MyFood Generator” czyli w skrócie „Generator posiłków”.

Projekt będzie dostępny pod domeną: http://myfood.love

Geneza projektu

Walczę aktualnie z nietolerancją pokarmową, i co miesiąc dostaje pełny jadłospis dla dwóch osób, na 30 dni. Każdy posiłek może posiadać 2 warianty [dla każdej osoby inne ilości].

Przygotowanie listy dań, listy zakupów, oraz następnie gotowanie (5 posiłków) zabiera mnóstwo czasu :) . Samego gotowania nie można usprawnić programistycznie, można za to usprawnić przygotowanie posiłków :).

Cel

  • wrzucenie wszystkich posiłków do systemu (śniadanie, 2 śniadanie, obiad, kolacja, podwieczorek)
    • możliwość przypisania posiłku do diety, grupy, tag’a
  • stworzenie jadłospisu dla x dni, z istniejących dań w systemie
    • użytkownik sam wybiera listę dań
    • użytkownikowi losuje jadłospis (wg kryteriów, wszystkie w systemie)
  • dla każdego jadłospisu stworzenie możliwości generowania listy zakupów
    • pełna lista zakupów dla wybranych dań, lub wybranych dni
    • możliwość zmiany listy zakupów (np posiadamy marchewkę w lodówce, to nie chcemy aby ona była na liście zakupów)
    • generowanie plików w różnych formatach (pdf, txt), możliwość wysłania listy na email
  • wyszukiwarka
    • możliwość wyszukania dania po wybranych składnikach (np. mamy w lodówce 5 składników, i chcemy znaleźć dostępne dania)
    • szukanie po nazwie
    • szukanie po czasie przygotowania posiłku
    • szukanie po rodzaju posiłku
  • opcje socialmedia: dzielenie się posiłkami z innymi użytkownikami systemu, lub udostępnianie postów na fb (itp)
  • kalendarz / pamiętnik posiłków – oznaczanie posiłku (zjedzony, nie zjedzony, itp), możliwosć dodania opisu do dania, zdjęcia, czasu wykonania
  • statystyki i raporty [czas wykonywania posiłku, zjedzone posiłki w miesiącu, zjedzone kalorie, itp]
  • możliwośc wydruku przepisu, jadłospisu, listy zakupów
  • inne (np podpięcie toggl time tracker do mierzenia czasu wykonywania posiłków, …)

Technologie wykorzystywane w projekcie

Na codzień pracuje z PHP i w nim tworze strony i systemy IT. Postanowiłem więc rozpocząć projekt w którym wszystkiego musze nauczyć się prawie od początku :) a więc:

  • backend: python 3(framework flask) w którym napisane będzie api
  • frontend: react (framework js)
  • docker – do odpalenia projektu w izolowanym wirtualnym środowisku, używając jednego polecenia
  • szablon strony napisany przy wykorzystaniu semantic-ui.com (Semantic UI to zestaw komponentów wspomagający tworzenie interfejsu użytkownika)
  • baza danych mysql
  • testy automatyczne
  • zewnętrzna baza składników (? opcja) – użytkownik wpisuje marchewka do dania, i jak jej nie znajduje to pobiera dane z zewn systemu (kalorie, itp)
  • … (wyjdzie w praniu)

Dlaczego python api? Chciałbym w przyszłości stworzyć aplikacje na komórki. Istniejące API pozwoli zrobić to niższym kosztem :) . W czym to napisze, jeszcze nie wiem. Wstępnie będzie to w Electronie -> https://electron.atom.io/

Posty związane z projektem

W regulaminu konkursu, musza pojawiać się dwa posty tygodniowo z tagiem DSP2017

  • minimum raz na tydzień pojawiać się będzie post dotyczący projektu #MyFood
  • drugi post może być powiązany z projektem, ale nie musi

Moim planem jest rozpisanie krok po kroku tworzenia projektu.  Nie będą to jednak szczegółowe posty typu: to skopiuj, tu wklej, tu zrób to i to. Wpisy mają cię nakierować na rozwiązanie istniejącego problemu, rozpisanie działania, linków do bazy wiedzy / tutoriali z których skorzystałem. Przykładowe problemy:

  • postawienie dockera, posiadające skonfigurowane biblioteki python, mysql (itp)
  • stworzenie środowiska dla semantic-ui do stworzenia szablonu projektu (gulp, npm, less)
  • stworzenie testów automatycznych (jestem całkowicie zielony w tym :(  )

I to tyle na starcie :) , sporo pracy przedemną. Nie wiem czy uda mi się skończyć projekt do końca konkursu. Celem jest stworzenie kompleksowo napisanego kodu, którym będę mógł się pochwalić bez wstydu :) . Przy okazji osoby będą mogli skorzystać z postów i wykorzystać części rozwiązań w swoich projektach.


Repozytorium git: https://github.com/mfratczak/myfood-generator – tutaj możesz obejrzeć kody źródłowe, i odpalić projekt na swoim serwerze.

Google Analytics Alternative