Napisałam swoje pierwsze strony pod koniec lat 90. Wtedy była to bardzo prosta sprawa. Miałam serwer Apache na jakimś wspólnym hostingu, do którego można było się dostać przez FTP, wpisując w przeglądarkę coś takiego jak ftp://ftp.example.com. Potem trzeba było wprowadzić nazwę i hasło, a następnie przesłać pliki na serwer. To były inne czasy, wszystko wtedy było prostsze niż teraz.
Przez te dwa dziesięciolecia wiele się zmieniło. Strony stały się bardziej złożone, przed wdrożeniem trzeba je budować. Jeden serwer przekształcił się w wiele serwerów działających za równoważnikami obciążenia, a korzystanie z systemów kontroli wersji stało się powszechne.
W przypadku mojego osobistego projektu miałam szczególną konfigurację. Wiedziałam, że potrzebuję możliwości wdrożenia strony na produkcję przy jednym działaniu: zapisywaniu kodu w gałęzi master na GitHubie. Poza tym wiedziałam, że nie chcę zajmować się zarządzaniem ogromnym klastrem Kubernetes ani korzystać z technologii Docker Swarm, ani utrzymywać parku serwerów z podami, agentami i innymi złożonościami. Aby osiągnąć cel maksymalnego uproszczenia pracy, musiałam zapoznać się z CI/CD.
Jeśli masz mały projekt (nasz przypadek dotyczy projektu Node.js) i chcesz dowiedzieć się, jak zautomatyzować wdrożenie tego projektu, tak aby to, co jest w repozytorium, odpowiadało temu, co działa w produkcji, to sądzę, że ta artykuł może Cię zainteresować.
Wymagania wstępne
Oczekuje się, że czytelnik tego artykułu ma podstawową wiedzę na temat pracy z wierszem poleceń i pisania skryptów Bash. Ponadto będzie potrzebować kont i .
Cele
Nie powiem, że ten artykuł można bezwarunkowo nazwać „podręcznikiem”. To raczej dokument, w którym opisuję, co się nauczyłam, i przedstawiam proces testowania i wdrażania kodu w produkcji, realizowany w jednej zautomatyzowanej serii.
Oto jak wyglądał mój końcowy proces pracy.
Dla kodu wysłanego do dowolnej gałęzi repozytorium, z wyjątkiem master, wykonuje się następujące działania:
- Uruchamiana jest budowa projektu na Travis CI.
- Wykonywane są wszystkie testy jednostkowe, integracyjne i end-to-end.
Tylko dla kodu, który trafia do master, wykonuje się następujące:
- Wszystko, co powiedziano powyżej, plus...
- Budowa obrazu Docker na podstawie aktualnego kodu, ustawień i środowiska.
- Umieszczenie obrazu na Docker Hub.
- Podłączenie do serwera produkcyjnego.
- Pobranie obrazu z Docker Hub na serwer.
- Zatrzymanie bieżącego kontenera i uruchomienie nowego, opartego na nowym obrazie.
Jeśli nie wiesz nic o Dockerze, obrazach i kontenerach — nie martw się. Wszystkiego ci o tym opowiem.
Czym jest CI/CD?
Skrót CI/CD oznacza „continuous integration/continuous deployment” — „ciągła integracja/ciągłe wdrażanie”.
▍Ciągła integracja
Ciągła integracja to proces, podczas którego programiści dokonują commitów w głównym repozytorium kodu źródłowego projektu (zwykle w gałęzi master). Jakość kodu jest zapewniana poprzez przeprowadzanie automatyzowanych testów.
▍Ciągłe wdrażanie
Ciągłe wdrażanie to częste automatyzowane wdrażanie kodu na produkcji. Druga część skrótu CI/CD czasami rozwija się jako „continuous delivery” („ciągła dostawa”). To w zasadzie to samo, co „ciągłe wdrażanie”, ale „ciągła dostawa” oznacza konieczność ręcznego potwierdzenia zmian przed rozpoczęciem procesu wdrażania projektu.
Rozpoczęcie pracy
Aplikacja, na której to wszystko opanowałam, nazywa się . To projekt internetowy, nad którym pracuję, przeznaczony do robienia notatek. Na początku próbowałam zrobić -projekt lub tylko aplikację frontendową bez serwera, aby skorzystać z standardowych możliwości hostingu i wdrażania projektów, które oferuje . W miarę jak rosła złożoność aplikacji, potrzebowałam stworzyć i jej część serwerową, co oznaczało, że musiałam opracować własną strategię automatycznej integracji i automatycznego wdrażania projektu.
W moim przypadku aplikacja to serwer Express działający w środowisku Node.js, obsługujący jednoplakowym aplikację React i wspierający zabezpieczone API serwerowe. Ta architektura podąża za strategią, którą można znaleźć w przewodniku po pełnostekowej autoryzacji.
Skonsultowałam się z , który jest ekspertem w automatyzacji, i zapytałem go, co muszę zrobić, aby wszystko działało tak, jak potrzebuję. Podsunął mi pomysł na to, jak powinien wyglądać zautomatyzowany proces pracy, opisany w sekcji «Cele» tego artykułu. To, że wyznaczyłem sobie takie cele, oznaczało, że muszę zrozumieć, jak używać Dockera.
Docker
Docker to narzędzie, które dzięki technologii konteneryzacji ułatwia dystrybucję aplikacji oraz ich wdrażanie i uruchamianie w tym samym środowisku, nawet jeśli sama platforma Docker działa w różnych środowiskach. Na początek musiałem zdobyć narzędzia interfejsu wiersza poleceń (CLI) Dockera. instalacji Dockera nie jest bardzo jasna i zrozumiała, ale można z niej dowiedzieć się, że aby wykonać pierwszy krok instalacji, należy pobrać Docker Desktop (na Mac lub Windows).
Docker Hub to mniej więcej to samo, co dla repozytoriów git lub rejestr dla pakietów JavaScript. To internetowe repozytorium dla obrazów Dockera. To właśnie do niego łączy się Docker Desktop.
Zatem, aby rozpocząć pracę z Dockerem, musisz zrobić dwie rzeczy:
- Zainstaluj .
- Zarejestruj się na .
Po tym możesz sprawdzić działanie Docker CLI, wykonując następujące polecenie, aby sprawdzić wersję Dockera:
docker -vNastępnie zaloguj się do Docker Huba, wpisując, gdy zostaniesz o to poproszony, swoją nazwę użytkownika i hasło:
docker loginAby korzystać z Dockera, musisz zrozumieć koncepcje obrazów i kontenerów.
▍Obrazy
Obraz to coś w rodzaju planu, zawierającego instrukcje dotyczące budowy kontenera. To niezmienna kopia systemu plików i ustawień aplikacji. Programiści mogą łatwo wymieniać się obrazami.
# Вывод сведений обо всех образах
docker imagesTo polecenie wyświetli tabelę z następującym nagłówkiem:
REPOSITORY TAG IMAGE ID CREATED SIZE
---Następnie przeanalizujemy kilka przykładów poleceń w takim samym formacie — najpierw polecenie z komentarzem, a potem przykład tego, co może zwrócić.
▍Kontenery
Kontener to pakiet wykonawczy, który zawiera wszystko, co potrzebne do uruchomienia aplikacji. Dzięki temu podejściu aplikacja zawsze będzie działać w ten sam sposób, niezależnie od infrastruktury: w izolowanym środowisku i w tym samym środowisku. Mówi się o tym, że w różnych środowiskach uruchamiane są instancje tego samego obrazu.
# Перечисление всех контейнеров
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
---▍Tagi
Tag to wskazanie konkretnej wersji obrazu.
▍Krótka informacja o poleceniach Docker
Oto przegląd niektórych często używanych poleceń Docker.
Zespół
Kontekst
Akcja
Obraz
Budowanie obrazu z Dockerfile
Obraz
Oznaczanie obrazu
Obraz
Wyświetlanie listy obrazów
Kontener
Uruchamianie kontenera na podstawie obrazu
Obraz
Wysyłanie obrazu do rejestru
Obraz
Pobieranie obrazu z rejestru
Kontener
Wyświetlanie listy kontenerów
Obraz/Kontener
Usuwanie nieużywanych kontenerów i obrazów
▍Plik Dockerfile
Wiem, jak lokalnie uruchomić aplikację do produkcji. Mam konfigurację Webpack, przeznaczoną do budowy gotowej aplikacji React. Następnie mam polecenie uruchamiające serwer oparty na Node.js, na porcie 5000. Wygląda to tak:
npm i # instalacja zależności
npm run build # budowanie aplikacji React
npm run start # uruchamianie serwera NodeNależy zauważyć, że nie mam aplikacji przykładowej na ten materiał. Jednak tutaj, do eksperymentów, nada się każda prosta aplikacja Node.
Aby skorzystać z kontenera, musisz dać instrukcje Docker. Robi się to za pomocą pliku, który nazywa się Dockerfile, znajdującego się w katalogu głównym projektu. Ten plik na początku wydaje się dość niezrozumiały.
Ale to, co się w nim znajduje, jedynie opisuje, za pomocą specjalnych poleceń, coś podobnego do konfiguracji środowiska roboczego. Oto niektóre z tych poleceń:
- — To polecenie rozpoczyna plik. Określa bazowy obraz, na podstawie którego budowany jest kontener.
- — Kopiowanie plików z lokalnego źródła do kontenera.
- — Ustawienie katalogu roboczego dla następnych poleceń.
- — Uruchamianie poleceń.
- — Konfiguracja portu.
- — Wskazanie polecenia do wykonania.
Dockerfile może wyglądać mniej więcej tak:
# Загрузить базовый образ
FROM node:12-alpine
# Скопировать файлы из текущей директории в директорию app/
COPY . app/
# Использовать app/ в роли рабочей директории
WORKDIR app/
# Установить зависимости (команда npm ci похожа npm i, но используется для автоматизированных сборок)
RUN npm ci --only-production
# Собрать клиентское React-приложение для продакшна
RUN npm run build
# Прослушивать указанный порт
EXPOSE 5000
# Запустить Node-сервер
ENTRYPOINT npm run startW zależności od wybranego bazowego obrazu, może być konieczne zainstalowanie dodatkowych zależności. Niektóre obrazy bazowe (takie jak Node Alpine Linux) zostały zaprojektowane, aby były jak najbardziej kompaktowe. W związku z tym mogą nie zawierać niektórych programów, na które liczysz.
▍Budowanie, tagowanie i uruchamianie kontenera
Lokalne budowanie i uruchamianie kontenera — to, po tym jak mamy Dockerfile, zadania są dość proste. Zanim wyślesz obraz na Docker Hub, należy go przetestować lokalnie.
▍Budowanie
Najpierw musisz zbudować , podając nazwę oraz, co nie jest obowiązkowe, tag (jeśli tag nie zostanie podany, system automatycznie przypisze obrazowi tag latest).
# Сборка образа
docker build -t <image>:<tag> .Po wykonaniu tej komendy można obserwować, jak Docker wykonuje budowę obrazu.
Wysyłanie kontekstu budowy do demona Dockera 2.88MB
Krok 1/9 : FROM node:12-alpine
---> ...wykonywanie etapów budowy...
Pomyślnie zbudowano 123456789123
Pomyślnie otagowano <obraz>:<tag> Budowa może zająć kilka minut — wszystko zależy od tego, ile masz zależności. Po zakończeniu budowy możesz wykonać komendę docker images i spojrzeć na opis swojego nowego obrazu.
REPOZYTORIUM TAG ID OBRAZU UTWORZONY ROZMIAR
<obraz> latest 123456789123 Około minuty temu x.xxGB▍Uruchamianie
Obraz został utworzony. Oznacza to, że na jego podstawie można uruchomić kontener. Ponieważ chcę mieć możliwość dostępu do aplikacji działającej w kontenerze pod adresem localhost:5000, w lewej części pary 5000:5000 w następnej komendzie ustawiłam 5000. W prawej części znajduje się port kontenera.
# Запуск с использованием локального порта 5000 и порта контейнера 5000
docker run -p 5000:5000 <image>:<tag> Teraz, gdy kontener został utworzony i uruchomiony, możesz skorzystać z komendy docker ps aby zobaczyć informacje o tym kontenerze (lub możesz użyć komendy docker ps -a, która wyświetla informacje o wszystkich kontenerach, a nie tylko o działających).
ID KONTENERA OBRAZ KOMENDA UTWORZONY STATUS PORTY NAZWY
987654321234 <obraz> "'/bin/sh -c 'npm run…" 6 sekund temu Włączony 6 sekund 0.0.0.0:5000->5000/tcp stoic_darwin Jeśli teraz przejdziesz pod adres localhost:5000 — możesz zobaczyć stronę działającej aplikacji, która wygląda dokładnie tak samo jak strona aplikacji działającej w środowisku produkcyjnym.
▍Przypisanie tagu i publikacja
Aby skorzystać z jednego z utworzonych obrazów na serwerze produkcyjnym, musimy mieć możliwość załadowania tego obrazu z Docker Hub. Oznacza to, że najpierw musimy stworzyć repozytorium na Docker Hub dla projektu. Następnie będziemy mieli miejsce, gdzie możemy wysłać obraz. Obraz trzeba nazwać tak, aby jego nazwa zaczynała się od naszej nazwy użytkownika na Docker Hub. Następnie powinno się pojawić nazwa repozytorium. Na końcu nazwy może znajdować się dowolny tag. Poniżej przedstawiono przykład nazewnictwa obrazów według tej zasady.
Teraz można zbudować obraz, nadając mu nową nazwę i wykonać polecenie docker push aby wysłać go do repozytorium Docker Hub.
docker build -t / : .
docker tag / : / :latest
docker push / :
# W praktyce może to wyglądać na przykład tak:
docker build -t user / app:v1.0.0 .
docker tag user / app:v1.0.0 user / app:latest
docker push user / app:v1.0.0Jeśli wszystko pójdzie zgodnie z planem, obraz będzie dostępny na Docker Hub i będzie można go łatwo załadować na serwer lub przekazać innym deweloperom.
Następne kroki
Do tej pory upewniliśmy się, że aplikacja działająca w kontenerze Docker działa lokalnie. Załadowaliśmy kontener na Docker Hub. Wszystko to oznacza, że już naprawdę bardzo dobrze posunęliśmy się do celu. Teraz musimy rozwiązać jeszcze dwa kwestie:
- Konfiguracja narzędzia CI do testowania i wdrażania kodu.
- Konfiguracja serwera produkcyjnego, aby mógł ładować i uruchamiać nasz kod.
W naszym przypadku jako rozwiązanie CI/CD używane jest . Jako serwer — .
Należy zauważyć, że można również skorzystać z innej kombinacji usług. Na przykład, zamiast Travis CI można użyć CircleCI lub Github Actions. A zamiast DigitalOcean — AWS lub Linode.
Postanowiliśmy pracować z Travis CI, a w tym serwisie mam już coś skonfigurowane. Dlatego teraz krótko opowiem o tym, jak go przygotować do pracy.
Travis CI
Travis CI to narzędzie do testowania i wdrażania kodu. Nie chciałbym wchodzić w szczegóły konfiguracji Travis CI, ponieważ każdy projekt jest unikalny i nie przyniesie to szczególnej korzyści. Ale opowiem o podstawach, które pozwolą wam zacząć pracę w przypadku, gdy zdecydujecie się korzystać z Travis CI. Cokolwiek wybierzecie — Travis CI, CircleCI, Jenkins czy coś innego, wszędzie będą miały zastosowanie podobne metody konfiguracji.
Aby rozpocząć pracę z Travis CI, przejdź do i załóż konto. Następnie zintegruj Travis CI ze swoim kontem GitHub. Podczas konfiguracji systemu będziesz musiał wskazać repozytorium, którego automatyzacją chcesz się zająć, oraz nadać dostęp do niego. (Korzystam z GitHub, ale jestem pewna, że Travis CI może również integrować się z BitBucket, GitLab i innymi podobnymi usługami).
Za każdym razem, gdy Travis CI zaczyna pracę, uruchamiany jest serwer, który wykonuje polecenia określone w pliku konfiguracyjnym, w tym wdrażanie odpowiednich gałęzi repozytorium.
▍Cykl życia zadania
Plik konfiguracyjny Travis CI, nazywany .travis.yml i przechowywany w głównym katalogu projektu, wspiera koncepcję zdarzeń zadania. Oto te zdarzenia, przedstawione w kolejności, w jakiej występują:
apt addonscache componentsbefore_installinstallbefore_scriptscriptbefore_cacheafter_success lub after_failurebefore_deploydeployafter_deployafter_script
▍Testowanie
W pliku konfiguracyjnym zamierzam skonfigurować lokalny serwer Travis CI. Wybrałam wersję Node 12 jako język i poinformowałam system, że musi zainstalować zależności potrzebne do użycia Dockera.
Wszystko, co wymieniono w .travis.yml, zostanie wykonane przy wykonywaniu wszystkich pull requestów do wszystkich gałęzi repozytorium, chyba że zaznaczone jest inaczej. To przydatna funkcja, ponieważ oznacza, że możemy testować cały kod, który trafia do repozytorium. Pozwala to sprawdzić, czy kod jest gotowy do zapisania w gałęzi master, i nie zakłóci on procesu budowania projektu. W tej globalnej konfiguracji wszystko instaluję lokalnie, uruchamiam serwer dewelopera Webpack w tle (to jest cecha mojego środowiska pracy) i wykonuję testy.
Jeśli chcesz, aby w Twoim repozytorium pojawiały się insignie z informacjami o pokryciu kodu testami, możesz znaleźć krótki przewodnik po użyciu Jest, Travis CI i Coveralls do zbierania i wyświetlania tych informacji.
Oto zawartość pliku .travis.yml:
# Установить язык
language: node_js
# Установить версию Node.js
node_js:
- '12'
services:
# Использовать командную строку Docker
- docker
install:
# Установить зависимости для тестов
- npm ci
before_script:
# Запустить сервер и клиент для тестов
- npm run dev &
script:
# Запустить тесты
- npm run testNa tym kończą się te działania, które są wykonywane dla wszystkich gałęzi repozytorium i dla pull requestów.
▍Wdrażanie
Zakładając, że wszystkie zautomatyzowane testy zakończyły się pomyślnie, możemy, co nie jest konieczne, wdrożyć kod na serwerze produkcyjnym. Ponieważ chcemy robić to tylko dla kodu z gałęzi master, wydajemy odpowiednie polecenia systemowi w ustawieniach wdrożenia. Zanim spróbujesz użyć w swoim projekcie kodu, który omówimy dalej, chciałabym Cię ostrzec, że musisz mieć rzeczywisty skrypt wywoływany do wdrożenia.
deploy:
# Budowanie kontenera Docker i wysyłanie go na Docker Hub
provider: script
script: bash deploy.sh
on:
branch: masterSkrypt wdrożeniowy realizuje dwa zadania:
- Budowanie, tagowanie i przesyłanie obrazu na Docker Hub za pomocą narzędzia CI (w naszym przypadku jest to Travis CI).
- Pobranie obrazu na serwer, zatrzymanie starego kontenera i uruchomienie nowego (w naszym przypadku serwer działa na platformie DigitalOcean).
Najpierw musisz skonfigurować automatyczny proces budowania, tagowania i przesyłania obrazu na Docker Hub. Wszystko to wygląda bardzo podobnie do tego, co już robiliśmy ręcznie, z wyjątkiem tego, że tutaj potrzebujemy strategii nadawania obrazom unikalnych tagów oraz automatyzacji logowania. Miałam trudności z niektórymi szczegółami skryptu wdrożenia, jak strategia tagowania, logowanie, kodowanie kluczy SSH, ustanawianie połączenia SSH. Na szczęście, mój chłopak doskonale radzi sobie z bashem, jak i wieloma innymi rzeczami. Pomógł mi napisać ten skrypt.
Zatem pierwsza część skryptu to wysyłanie obrazu na Docker Hub. Zrobienie tego jest dość proste. Użyty przeze mnie schemat tagowania polega na łączeniu hasha git z tagiem git, jeśli taki istnieje. To pozwala na stworzenie unikalnego tagu i ułatwia identyfikację budowy, na której jest oparty. DOCKER_USERNAME i DOCKER_PASSWORD — to zmienne środowiskowe użytkownika, które można ustawić za pomocą interfejsu Travis CI. Travis CI automatycznie zajmie się danymi wrażliwymi, aby nie wpadły w niepowołane ręce.
Oto pierwsza część skryptu deploy.sh.
#!/bin/sh
set -e # Остановить скрипт при наличии ошибок
IMAGE="<username>/<repository>" # Образ Docker
GIT_VERSION=$(git describe --always --abbrev --tags --long) # Git-хэш и теги
# Сборка и тегирование образа
docker build -t ${IMAGE}:${GIT_VERSION} .
docker tag ${IMAGE}:${GIT_VERSION} ${IMAGE}:latest
# Вход в Docker Hub и выгрузка образа
echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USERNAME}" --password-stdin
docker push ${IMAGE}:${GIT_VERSION} To, jak będzie wyglądała druga część skryptu, w pełni zależy od tego, jakiego hosta używasz oraz jak zorganizowane jest połączenie z nim. W moim przypadku, ponieważ korzystam z Digital Ocean, do połączenia z serwerem używane są polecenia . W przypadku pracy z AWS używana będzie narzędzie aws, i tak dalej.
Konfiguracja serwera nie była szczególnie trudna. Stworzyłam droplet oparty na podstawowym obrazie. Należy zauważyć, że wybrany przeze mnie system wymaga jednorazowej ręcznej instalacji Docker oraz jednorazowego ręcznego uruchomienia Docker. Do instalacji Docker użyłam Ubuntu 18.04, dlatego jeśli również używasz Ubuntu, aby zrobić to samo, możesz po prostu postępować zgodnie z prosty przewodnik.
Nie mówię tu o konkretnych komendach dla usługi, ponieważ ten aspekt może się znacznie różnić w różnych przypadkach. Przedstawię jedynie ogólny plan działania, który wykonuje się po połączeniu przez SSH z serwerem, na którym zostanie wdrożony projekt:
- Należy znaleźć kontener, który aktualnie działa, i go zatrzymać.
- Następnie trzeba w tle uruchomić nowy kontener.
- Będziesz musiał ustawić lokalny port serwera na wartość
80— to pozwoli na dostęp do witryny pod adresem w formacieexample.com, bez podawania portu, a nie korzystać z adresu typuexample.com:5000. - I wreszcie, musisz usunąć wszystkie stare kontenery i obrazy.
Oto kontynuacja skryptu.
# Найти ID работающего контейнера
CONTAINER_ID=$(docker ps | grep takenote | cut -d" " -f1)
# Остановить старый контейнер, запустить новый, очистить систему
docker stop ${CONTAINER_ID}
docker run --restart unless-stopped -d -p 80:5000 ${IMAGE}:${GIT_VERSION}
docker system prune -a -fNiektóre rzeczy, na które warto zwrócić uwagę
Możliwe, że kiedy połączysz się z serwerem przez SSH z Travis CI, zobaczysz ostrzeżenie, które uniemożliwi kontynuowanie instalacji, ponieważ system będzie czekać na reakcję użytkownika.
Autentyczność hosta '<hostname> (<IP address>)' nie może zostać potwierdzona.
Odcisk palca klucza RSA to <key fingerprint>.
Czy na pewno chcesz kontynuować połączenie (tak/nie)? Dowiedziałam się, że klucz tekstowy można zakodować w base64, aby zapisać go w formie, w której można wygodnie i bezpiecznie pracować. Na etapie instalacji można zdekodować klucz publiczny i zapisać go w pliku known_hosts aby pozbyć się opisanego powyżej błędu.
echo <public key> | base64 # wyświetla <publiczny klucz zakodowany w base64>W praktyce ta komenda może wyglądać tak:
echo "123.45.67.89 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En
mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx
NrRFi9wrf+M7Q== you@example.com" | base64A oto jak wygląda to, co ona wydaje — ciąg w kodowaniu base64:
123.45.67.89 ssh-rsa AABBA3NzaC1yc2EAAAAB3Nza...QkBzT3UpkDHIzOWFzY1R2M0NOMFY0cWVTcmhrZmo20C...Oto polecenie, o którym mówiono wcześniej
install:
- echo | base64 -d >> $HOME/.ssh/known_hostsTen sam sposób można zastosować z kluczem prywatnym przy nawiązywaniu połączenia, ponieważ do uzyskania dostępu do serwera możesz potrzebować klucza prywatnego. Podczas pracy z kluczem musisz jedynie zapewnić jego bezpieczne przechowywanie w zmiennej środowiskowej Travis CI oraz nie wypisywać go nigdzie.
Kolejną rzeczą, na którą warto zwrócić uwagę, jest to, że być może będziesz musiał uruchomić cały skrypt wdrażania, przedstawiony w postaci jednej linii, na przykład - za pomocą doctl. Może to wymagać dodatkowego wysiłku.
doctl compute ssh --ssh-command "wszystkie komendy będą tutaj && tutaj"TLS/SSL i równoważenie obciążenia
Po zrobieniu wszystkiego, o czym mówiono wcześniej, ostatnim problemem, przed którym stanęłam, był brak SSL na serwerze. Ponieważ korzystam z serwera Node.js, aby wymusić serwer proxy Nginx i Let’s Encrypt, trzeba sporo nad tym popracować.
Nie chciałam wykonywać tych wszystkich ustawień SSL ręcznie, więc po prostu stworzyłam równoważnik obciążenia i zapisałam jego dane w DNS. W przypadku DigitalOcean na przykład, stworzenie automatycznie odnawiającego się certyfikatu samopodpisanego na równoważniku obciążenia to prosta, bezpłatna i szybka procedura. Taki sposób ma również dodatkową zaletę, która polega na tym, że pozwala bardzo łatwo skonfigurować SSL na wielu serwerach działających za równoważnikiem obciążenia. To pozwala serwerom „nie myśleć” o SSL, ale jednocześnie korzystać z portu 80. Tak więc konfiguracja SSL na równoważniku obciążenia jest znacznie prostsza i wygodniejsza niż alternatywne metody konfigurowania SSL.
Teraz można zamknąć na serwerze wszystkie porty akceptujące połączenia przychodzące — poza portem 80, używanym do komunikacji z równoważnikiem obciążenia, oraz portem 22 dla SSH. W rezultacie próby bezpośredniego dostępu do serwera przez jakiekolwiek porty, z wyjątkiem tych dwóch, zakończą się niepowodzeniem.
Podsumowanie
Po tym, jak wykonałam wszystko, o czym mówiłam w tym materiale, już nie obawiałam się ani platformy Docker, ani koncepcji zautomatyzowanych łańcuchów CI/CD. Udało mi się skonfigurować łańcuch ciągłej integracji, w ramach którego testowany jest kod przed jego wdrożeniem do produkcji oraz automatyczne wdrożenie kodu na serwer. Wszystko to jest dla mnie wciąż stosunkowo nowe, i jestem pewna, że istnieją sposoby na poprawę mojego zautomatyzowanego procesu pracy i uczynienie go bardziej efektywnym. Dlatego jeśli masz jakieś pomysły w tej kwestii – daj mi znać. Mam nadzieję, że ten artykuł pomógł ci w twoich działaniach. Chciałabym wierzyć, że czytając go, dowiedziałeś się tyle, ile ja, podczas gdy analizowałam wszystko, o czym w nim opisałam.
P.S. W naszym jest dostępny obraz , który można zainstalować jednym kliknięciem. Możesz sprawdzić działanie kontenerów na . Wszystkim nowym klientom przysługuje 3 dni darmowego testowania.
Drodzy Czytelnicy! Czy korzystasz z technologii CI/CD w swoich projektach?
Źródło: habr.com
