Ruby: Zaawansowane zastosowania

Dalsze kroki w wdrażaniu Ruby

👋 Witamy w dokumentacji Stackhero!

Stackhero oferuje gotowe do użycia rozwiązanie Ruby cloud, które zapewnia wiele korzyści, w tym:

  • Wdrażaj swoją aplikację w kilka sekund za pomocą prostego git push.
  • Używaj własnej nazwy domeny i korzystaj z automatycznej konfiguracji certyfikatów HTTPS dla zwiększonego bezpieczeństwa.
  • Ciesz się spokojem dzięki automatycznym kopiom zapasowym, aktualizacjom jednym kliknięciem oraz prostemu, przejrzystemu i przewidywalnemu cennikowi.
  • Uzyskaj optymalną wydajność i solidne zabezpieczenia dzięki prywatnej i dedykowanej VM.

Oszczędzaj czas i upraszczaj sobie życie: wypróbowanie rozwiązania Ruby cloud hosting Stackhero zajmuje tylko 5 minut!

Do tej pory wdrażaliśmy naszą aplikację Ruby, przesyłając gałąź main za pomocą:

git push stackhero main

Jeśli chcesz wdrożyć inną gałąź, możesz użyć tej komendy. Zamień <BRANCH> na nazwę gałęzi, którą chcesz wdrożyć:

git push stackhero <BRANCH>:main

Na przykład, aby wdrożyć gałąź o nazwie production, uruchom:

git push stackhero production:main

W niektórych przypadkach możesz chcieć wdrożyć tag zamiast gałęzi. Aby to zrobić, uruchom następującą komendę. Zamień <TAG> na tag, który chcesz wdrożyć:

git push stackhero '<TAG>^{}:main'

Na przykład, aby wdrożyć tag v1.0.0, uruchom:

git push stackhero 'v1.0.0^{}:main'

Składnia ^{} jest używana do odniesienia się do commitu, na który wskazuje tag.

Oprócz gałęzi lub tagów, możesz wdrożyć konkretny commit. Zamień <COMMIT_HASH> w poniższej komendzie na hash żądanego commitu:

git push -f stackhero <COMMIT_HASH>:main

Na przykład, aby wdrożyć commit z hashem abcde, uruchom:

git push -f stackhero abcde:main

Jeśli wdrożenie produkcyjne nie działa zgodnie z oczekiwaniami, możesz cofnąć się, wdrażając starszy commit. Najpierw użyj poniższej komendy, aby zobaczyć historię commitów:

git log

Ta komenda wyświetla datę, hash commitu i opis dla każdego commitu w twoim repozytorium. Na przykład, możesz zobaczyć taki wynik:

commit cccc8b3ebdccb9abc1926ef49ee589dae5c5fe06 (HEAD -> main, stackhero/main)
Author: Developer
Date:   Fri Apr 28 09:36:18 +0000

    Break the code

commit bbbb622301772072c3d82f3cc0d91e29e6e84901
Author: Developer
Date:   Wed Apr 26 12:49:28 +0000

    Update the code

commit aaaa1d8b06535b413e0df8298ccf52339dfef3ff
Author: Developer
Date:   Wed Apr 26 12:44:50 +0000

    Improve the code

Jeśli commit z wiadomością "Break the code" (hash cccc...) działa w produkcji, a zdecydujesz się cofnąć do poprzedniego commitu "Update the code" (hash bbbb...), uruchom:

git push -f stackhero bbbb622301772072c3d82f3cc0d91e29e6e84901:main

Aby uniknąć wdrażania wadliwego kodu i zwiększyć stabilność produkcji, zaleca się posiadanie środowiska "staging".

Umieszczone między środowiskami "development" a "production", środowisko "staging" zapewnia niemal dokładną replikę środowiska produkcyjnego. Pozwala to na testowanie kodu i zapewnienie jego jakości przed wdrożeniem do produkcji.

Korzystając ze środowiska staging, możesz być bardziej pewny funkcjonalności i wydajności swojego kodu, zapewniając bardziej niezawodne i solidne wdrożenie produkcyjne.

Ten typ środowiska zostanie omówiony później w dokumentacji.

Środowisko staging to najlepsza praktyka do użycia obok środowisk development i production. Replikuje twoje środowisko produkcyjne, abyś mógł testować aktualizacje i zmiany przed ich wdrożeniem.

Środowisko staging musi ściśle odzwierciedlać środowisko produkcyjne.

Jednak upewnij się, że środowisko staging używa klonu bazy danych produkcyjnej, a nie samej bazy danych produkcyjnej.

Jeśli twoja usługa Ruby jest powiązana z bazą danych lub innymi usługami, odtwórz je w nowym stosie <Project> - Staging.

Aby skonfigurować środowisko staging na Stackhero, wykonaj następujące kroki:

  1. Na pulpicie nawigacyjnym Stackhero, zmień nazwę istniejącego stosu z <Project> na <Project> - Production. Na przykład, jeśli twój projekt nazywa się Chat Bot, zmień nazwę stosu na Chat Bot - Production.
  2. Utwórz nowy stos o nazwie <Project> - Staging. Korzystając z poprzedniego przykładu, będzie to Chat Bot - Staging.
  3. Uruchom usługę Ruby w stosie staging.
  4. Pobierz wartość komendy git remote i postępuj zgodnie z instrukcjami w sekcji Wdrażanie do środowiska staging.

Postępując zgodnie z tymi krokami, uzyskasz poprawnie skonfigurowane środowisko staging do testowania i weryfikacji aktualizacji przed ich wdrożeniem do produkcji.

Zarządzanie oddzielnymi środowiskami, takimi jak staging i production, jest wysoce zalecane. Jak wyjaśniono w Konfigurowanie środowiska staging, możesz wdrażać do każdego środowiska z różnymi zdalnymi repozytoriami Git.

Zacznij od zmiany nazwy bieżącego zdalnego repozytorium. Na przykład, zmień nazwę zdalnego "stackhero" na "stackhero-production" za pomocą tej komendy:

git remote rename stackhero stackhero-production

Następnie utwórz nową usługę Ruby dla środowiska staging. Użyj dostarczonej komendy "git remote add" i zmodyfikuj ją w następujący sposób (zamień <XXXXXX> na domenę twojej usługi):

  • Oryginalna komenda:

    git remote add stackhero ssh://stackhero@<XXXXXX>.stackhero-network.com:222/project.git
    
  • Zmodyfikowana komenda:

    git remote add stackhero-staging ssh://stackhero@<XXXXXX>.stackhero-network.com:222/project.git
    

Teraz możesz wdrażać do staging za pomocą:

git push stackhero-staging main

Lub wdrażać do produkcji za pomocą:

git push stackhero-production main

Aby jeszcze bardziej usprawnić proces wdrażania, rozważ użycie ulepszonej wersji Makefile.

Dzięki temu ulepszonemu Makefile, wdrażanie do produkcji lub staging może być łatwo wykonane za pomocą make deploy-production lub make deploy-staging.

Poniżej znajduje się ulepszony Makefile, który obsługuje wiele reguł dla typowych zadań:

  • make dev (lub po prostu make): Uruchamia aplikację w trybie deweloperskim.
  • make deploy: Wdraża aplikację do zdalnego o nazwie stackhero (idealne, gdy masz jedną instancję Stackhero).
  • make deploy-production: Wdraża aplikację do zdalnego o nazwie stackhero-production.
  • make deploy-staging: Wdraża aplikację do zdalnego o nazwie stackhero-staging.

Ten Makefile jest zaprojektowany do obsługi przypadków, gdy kod został już wdrożony, unikając błędu "Everything up-to-date".

Skopiuj i wklej poniższą zawartość do nowego Makefile:

# Domyślna reguła do wykonania przy wywołaniu "make" bez argumentu
.DEFAULT_GOAL := dev


# Stackhero dla Ruby wykona regułę "run" na twojej instancji.
# To jest komenda do uruchomienia na platformach produkcyjnych i staging.
run:
  rake assets:precompile
  rake db:migrate RAILS_ENV=production
  RAILS_ENV=production bundle exec puma -C config/puma.rb


# Komenda do uruchomienia w środowisku deweloperskim
dev:
  RAILS_ENV=development rails server -b 0.0.0.0


# Reguła "deploy" wdraża na instancję "stackhero".
# Odpowiednia, gdy masz tylko jedną instancję.
deploy:
  @$(MAKE) -s deploy-script DEPLOY_REMOTE=stackhero DEPLOY_BRANCH=main


# Reguła "deploy-*" wdraża na instancję "stackhero-*".
# Na przykład, uruchom "make deploy-production", aby wdrożyć na "stackhero-production",
# lub "make deploy-staging", aby wdrożyć na "stackhero-staging".
deploy-%:
  @$(MAKE) -s deploy-script DEPLOY_REMOTE=stackhero-$* DEPLOY_BRANCH=main


# Wewnętrzna reguła wdrażania. Nie modyfikować.
deploy-script:
  @echo "Wdrażanie gałęzi \"${DEPLOY_BRANCH}\" do \"${DEPLOY_REMOTE}\"..."
  @echo

  @if [ -n "$$(git status --porcelain)" ]; then \
    echo "Nie można wdrożyć, ponieważ są niezatwierdzone zmiany:"; \
    echo "\e[0m"; \
    git status -s; \
    echo ""; \
    echo "\e[0;31m"; \
    echo "Możesz użyć tej komendy, aby zatwierdzić zmiany:"; \
    echo "git add -A . && git commit -m \"Twoja wiadomość\""; \
    echo "\e[0m"; \
    exit 1; \
  fi

  @git push --dry-run ${DEPLOY_REMOTE} ${DEPLOY_BRANCH} 2>&1 | grep -q -F "Everything up-to-date"; \
  EXIT_CODE=$$?; \
  if [ $$EXIT_CODE -eq 0 ]; then \
    echo -n "Nic nowego do wdrożenia... Wymusić wdrożenie (to stworzy nowy commit)? (y/N) "; \
    read answer && \
    case $$answer in \
      y|Y|yes|YES) \
      git commit --allow-empty -m "Force update for deploy purpose to \"${DEPLOY_REMOTE}\"" ; \
      ;; \
      *) \
      echo "Nic do wdrożenia!"; \
      exit 1; \
      ;; \
    esac \
  fi

  git push ${DEPLOY_REMOTE} ${DEPLOY_BRANCH}

W pewnym momencie będziesz musiał zarządzać sekretami, takimi jak tokeny lub hasła do baz danych i usług zewnętrznych. Ważne jest, aby przechowywać te sekrety w sposób bezpieczny. Unikaj osadzania sekretów bezpośrednio w repozytorium lub kodzie, ponieważ stanowi to poważne zagrożenie bezpieczeństwa.

Zmienne środowiskowe oferują dwa znaczące korzyści:

  1. Twoje sekrety nie będą przechowywane w repozytorium Git, co zmniejsza ryzyko, jeśli ktoś uzyska dostęp do twojego kodu źródłowego.
  2. Możesz używać różnych poświadczeń dla różnych środowisk. Na przykład, połącz się z bazą danych produkcyjną w produkcji, używając bazy danych deweloperskiej podczas rozwoju.

Dla rozwoju, utwórz plik .env w katalogu głównym projektu. Ten plik będzie wykluczony z Git, aby nigdy nie został zatwierdzony. Użyj gemu dotenv, aby automatycznie załadować plik .env.

Najpierw dodaj gem dotenv-rails do swojego Gemfile:

# Gemfile
gem 'dotenv-rails', groups: [:development, :test]

Następnie zainstaluj gem:

bundle install

Następnie utwórz plik .env w katalogu głównym projektu i dodaj swoje zmienne:

RAILS_ENV="development"
DATABASE_PASSWORD="secretPassword"
THIRD_API_PRIVATE_KEY="secretKey"
# ...

Na koniec upewnij się, że plik .env jest ignorowany przez Git:

echo '.env*' >> .gitignore

Dla staging i produkcji, plik .env nie jest bezpieczny ani praktyczny, ponieważ nie może być przechowywany w repozytorium Git. Zamiast tego, Stackhero zapewnia bezpieczne rozwiązanie do zarządzania zmiennymi środowiskowymi bezpośrednio w konfiguracji twojej usługi Ruby.

Możesz ustawić te zmienne za pośrednictwem pulpitu nawigacyjnego Stackhero, wybierając swoją usługę Ruby i klikając przycisk "Configure".

W Ruby, możesz łatwo uzyskać dostęp do zmiennych środowiskowych, używając ENV. Na przykład, aby pobrać DATABASE_PASSWORD, użyj:

ENV['DATABASE_PASSWORD'] # => 'secretPassword'

Oto przykład, jak połączyć się z serwerem RabbitMQ, używając zmiennych środowiskowych:

require 'bunny'

class RabbitMQClient
  def initialize
    @connection = Bunny.new(hostname: ENV['RABBITMQ_HOST'],
                            username: ENV['RABBITMQ_USERNAME'],
                            password: ENV['RABBITMQ_PASSWORD'])
    @connection.start
  end

  def publish(queue_name, message)
    channel = @connection.create_channel
    queue = channel.queue(queue_name)
    channel.default_exchange.publish(message, routing_key: queue.name)
  end

  def close
    @connection.close
  end
end

Na platformie deweloperskiej, twój plik .env może zawierać:

RABBITMQ_HOST='127.0.0.1'
RABBITMQ_USERNAME='developmentUser'
RABBITMQ_PASSWORD='developmentPassword'

Dla produkcji i staging, zdefiniuj swoje zmienne środowiskowe w pulpicie nawigacyjnym Stackhero w konfiguracji usługi Ruby, jak pokazano poniżej:

RABBITMQ_HOST='<XXXXXX>.stackhero-network.com'
RABBITMQ_USERNAME='production'
RABBITMQ_PASSWORD='secretProductionPassword'

Aplikacje Ruby często używają protokołu HTTP na portach 80 (HTTP) i 443 (HTTPS). Jeśli twoja aplikacja potrzebuje dodatkowych portów lub różnych protokołów (TCP lub UDP), skonfiguruj ustawienia "Ports Redirections" w swojej usłudze Ruby za pośrednictwem pulpitu nawigacyjnego Stackhero.

Będziesz musiał określić port wejściowy (otwarty publicznie), port docelowy (otwarty w twojej usłudze Ruby) i protokół (TCP lub UDP).

Do przechowywania plików, takich jak zdjęcia użytkowników lub dokumenty, zaleca się użycie rozwiązania do przechowywania obiektów. Przechowywanie obiektów pozwala na udostępnianie plików między wieloma usługami i instancjami oraz oddziela warstwę przechowywania od twojego kodu. Jest to uważane za najlepszą praktykę.

Polecamy MinIO jako łatwe, szybkie i potężne rozwiązanie kompatybilne z protokołem Amazon S3.

Jeśli wybierzesz lokalne przechowywanie plików, możesz użyć trwałego przechowywania dostarczonego z twoją instancją Ruby. To lokalne przechowywanie jest dostępne w katalogu /persistent/storage/.

Jednak lokalne przechowywanie plików nie jest zalecane, ponieważ może nie być najlepszą praktyką dla długoterminowej skalowalności i niezawodności.

OSTRZEŻENIE: Nigdy nie przechowuj danych poza folderem /persistent/storage/!

Przechowywanie danych w innym miejscu niż folder przechowywania trwałego może prowadzić do utraty danych podczas ponownego uruchamiania, aktualizacji instancji lub przesyłania nowego kodu.

Jeśli używasz macOS, możesz uznać za niewygodne wpisywanie hasła do prywatnego klucza SSH za każdym razem, gdy przesyłasz kod. Chociaż bezpieczeństwo jest kluczowe, możesz poprawić wygodę, bezpiecznie przechowując hasło w Keychain Apple.

Może być kuszące usunięcie hasła z prywatnego klucza SSH, ale nie jest to zalecane.

Zamiast tego, przechowuj hasło klucza w Keychain, używając następującej komendy dla klucza o nazwie id_ed25519:

ssh-add --apple-use-keychain ~/.ssh/id_ed25519

Po uruchomieniu tej komendy nie powinieneś być ponownie proszony o hasło klucza. Jeśli używasz klucza RSA, zamień id_ed25519 na id_rsa, jak pokazano poniżej:

ssh-add --apple-use-keychain ~/.ssh/id_rsa