Tworzenie łańcucha CI/CD i automatyzacja pracy z Dockerem

Pierwsze strony internetowe pisałem pod koniec lat 90-tych. Wtedy bardzo łatwo było je doprowadzić do stanu używalności. Na jakimś hostingu współdzielonym znajdował się serwer Apache, można było zalogować się do tego serwera przez FTP, pisząc coś w stylu ftp://ftp.example.com. Następnie należało podać swoje imię i nazwisko oraz hasło i przesłać pliki na serwer. Były inne czasy, wszystko było wtedy prostsze niż teraz.

Tworzenie łańcucha CI/CD i automatyzacja pracy z Dockerem

W ciągu dwóch dekad od tego czasu wszystko bardzo się zmieniło. Strony internetowe stały się bardziej złożone; przed dopuszczeniem ich do produkcji należy je złożyć. Z jednego serwera powstało wiele serwerów działających za modułami równoważenia obciążenia, a korzystanie z systemów kontroli wersji stało się powszechne.

Dla mojego osobistego projektu miałem specjalną konfigurację. Wiedziałem też, że potrzebuję możliwości wdrożenia witryny w środowisku produkcyjnym poprzez wykonanie tylko jednej czynności: napisania kodu do oddziału master na GitHubie. Poza tym wiedziałem, że aby zapewnić działanie mojej małej aplikacji webowej, nie chcę zarządzać ogromnym klastrem Kubernetes, korzystać z technologii Docker Swarm, czy utrzymywać floty serwerów z podami, agentami i wszelako inną infrastrukturą. zawiłości. Aby osiągnąć cel, jakim było maksymalne ułatwienie pracy, musiałem zapoznać się z CI/CD.

Jeśli masz mały projekt (w tym przypadku projekt Node.js) i chciałbyś wiedzieć jak zautomatyzować wdrożenie tego projektu, jednocześnie mając pewność, że to co przechowywane w repozytorium dokładnie odpowiada temu, co sprawdza się na produkcji, to ja myślę, że ten artykuł może Cię zainteresować.

Wymagania wstępne

Od czytelnika tego artykułu oczekuje się podstawowej wiedzy na temat wiersza poleceń i pisania skryptów Bash. Ponadto będzie potrzebował kont Travis CI и Centrum Dockera.

Cele

Nie powiem, że ten artykuł można bezwarunkowo nazwać „samouczkiem”. To raczej dokument, w którym opowiadam o tym, czego się nauczyłem i opisuję odpowiadający mi proces testowania i wdrażania kodu na produkcję, wykonywany w jednym, zautomatyzowanym przebiegu.

Tak zakończył się mój przepływ pracy.

W przypadku kodu wysłanego do dowolnej gałęzi repozytorium z wyjątkiem masterwykonywane są następujące czynności:

  • Rozpoczyna się projekt oparty na Travis CI.
  • Przeprowadzane są wszystkie testy jednostkowe, integracyjne i end-to-end.

Tylko dla kodu, który należy do master, wykonywane jest:

  • Wszystko wymienione powyżej, plus...
  • Budowanie obrazu Dockera w oparciu o bieżący kod, ustawienia i środowisko.
  • Wdrażanie obrazu w Docker Hub.
  • Połączenie z serwerem produkcyjnym.
  • Przesyłanie obrazu z Docker Hub na serwer.
  • Zatrzymanie bieżącego kontenera i rozpoczęcie nowego na podstawie nowego obrazu.

Jeśli nie wiesz zupełnie nic o Dockerze, obrazach i kontenerach, nie martw się. Opowiem ci o wszystkim.

Co to jest CI/CD?

Skrót CI/CD oznacza „ciągłą integrację/ciągłe wdrażanie”.

▍Ciągła integracja

Ciągła integracja to proces, w którym programiści zatwierdzają główne repozytorium kodu źródłowego projektu (zwykle oddział master). Jednocześnie jakość kodu zapewniana jest poprzez automatyczne testy.

▍Ciągłe wdrażanie

Ciągłe wdrażanie to częste, zautomatyzowane wdrażanie kodu w środowisku produkcyjnym. Druga część akronimu CI/CD jest czasami zapisywana jako „dostawa ciągła”. Zasadniczo jest to to samo, co „ciągłe wdrażanie”, ale „ciągłe dostarczanie” oznacza konieczność ręcznego potwierdzania zmian przed rozpoczęciem procesu wdrażania projektu.

Pierwsze kroki

Aplikacja, której się tego wszystkiego nauczyłem, nazywa się Zrób notatkę. To jest projekt internetowy, nad którym pracuję, przeznaczony do robienia notatek. Na początku próbowałem to zrobić JAMStack-project, lub po prostu aplikacja front-end bez serwera, aby skorzystać ze standardowych możliwości hostingu i wdrażania projektów, jakie oferuje Netlifikuj. Wraz ze wzrostem złożoności aplikacji pojawiła się konieczność stworzenia jej części serwerowej, co wiązało się z koniecznością sformułowania własnej strategii automatycznej integracji i zautomatyzowanego wdrożenia projektu.

W moim przypadku aplikacją jest serwer Express działający w środowisku Node.js, obsługujący jednostronicową aplikację React i obsługujący bezpieczne API po stronie serwera. Architektura ta jest zgodna ze strategią, którą można znaleźć w to Przewodnik uwierzytelniania pełnego stosu.

konsultowałem z другом, który jest ekspertem w dziedzinie automatyzacji, i zapytał go, co muszę zrobić, aby wszystko działało tak, jak chciałem. Podsunął mi pomysł, jak powinien wyglądać zautomatyzowany przepływ pracy, opisany w części Cele tego artykułu. Mając te cele, musiałem dowiedzieć się, jak używać Dockera.

Doker

Docker to narzędzie, które dzięki technologii konteneryzacji pozwala na łatwą dystrybucję, wdrażanie i uruchamianie aplikacji w tym samym środowisku, nawet jeśli sama platforma Docker działa w różnych środowiskach. Najpierw musiałem poznać narzędzia wiersza poleceń Dockera (CLI). instrukcja Poradnika instalacji Dockera nie można nazwać bardzo przejrzystym i zrozumiałym, ale można się z niego dowiedzieć, że aby wykonać pierwszy krok instalacji, należy pobrać Docker Desktop (na Maca lub Windowsa).

Docker Hub to mniej więcej to samo, co GitHub dla repozytoriów git lub rejestru Npm dla pakietów JavaScript. To jest internetowe repozytorium obrazów Dockera. To jest to, z czym łączy się Docker Desktop.

Aby więc rozpocząć pracę z Dockerem, musisz wykonać dwie rzeczy:

Następnie możesz sprawdzić, czy interfejs Docker CLI działa, uruchamiając następujące polecenie, aby sprawdzić wersję Dockera:

docker -v

Następnie zaloguj się do Docker Hub, wpisując swoją nazwę użytkownika i hasło, gdy zostaniesz o to poproszony:

docker login

Aby korzystać z Dockera, musisz zrozumieć pojęcia obrazów i kontenerów.

▍Obrazy

Obraz to coś w rodzaju planu zawierającego instrukcje dotyczące montażu pojemnika. Jest to niezmienna migawka systemu plików i ustawień aplikacji. Programiści mogą łatwo udostępniać obrazy.

# Вывод сведений обо всех образах
docker images

To polecenie wyświetli tabelę z następującym nagłówkiem:

REPOSITORY     TAG     IMAGE ID     CREATED     SIZE
---

Następnie przyjrzymy się kilku przykładom poleceń w tym samym formacie - najpierw jest polecenie z komentarzem, a następnie przykład tego, co może wyświetlić.

▍Kontenery

Kontener to wykonywalny pakiet zawierający wszystko, co potrzebne do uruchomienia aplikacji. Aplikacja przy takim podejściu będzie zawsze działać tak samo, niezależnie od infrastruktury: w izolowanym środowisku i w tym samym środowisku. Chodzi o to, że instancje tego samego obrazu są uruchamiane w różnych środowiskach.

# Перечисление всех контейнеров
docker ps -a
CONTAINER ID     IMAGE     COMMAND     CREATED     STATUS     PORTS     NAMES
---

▍Tagi

Tag wskazuje konkretną wersję obrazu.

▍Szybkie odwołanie do poleceń Dockera

Oto przegląd niektórych często używanych poleceń platformy Docker.

Zespół

Kontekst

efekt

konstrukcja dokera

Obraz

Tworzenie obrazu z pliku Dockerfile

znacznik dokowania

Obraz

Tagowanie obrazów

obrazy doków

Obraz

Lista obrazów

uruchamianie dokera

pojemnik

Uruchamianie kontenera na podstawie obrazu

dokowanie do doku

Obraz

Przesyłanie obrazu do rejestru

ściąganie dokera

Obraz

Ładowanie obrazu z rejestru

docker ps

pojemnik

Lista kontenerów

przycinanie systemu dokowanego

Obraz/kontener

Usuwanie nieużywanych kontenerów i obrazów

▍Plik Dockera

Wiem, jak uruchomić aplikację produkcyjną lokalnie. Mam konfigurację Webpacka zaprojektowaną do zbudowania gotowej aplikacji React. Następnie mam polecenie, które uruchamia na porcie serwer oparty na Node.js 5000. To wygląda tak:

npm i         # установка зависимостей
npm run build # сборка React-приложения
npm run start # запуск Node-сервера

Należy zaznaczyć, że nie posiadam przykładowego zastosowania tego materiału. Ale tutaj, do eksperymentów, wystarczy dowolna prosta aplikacja Node.

Aby skorzystać z kontenera, będziesz musiał wydać instrukcje Dockerowi. Odbywa się to poprzez plik o nazwie Dockerfile, znajdujący się w katalogu głównym projektu. Plik ten na pierwszy rzut oka wydaje się dość niezrozumiały.

Ale to, co zawiera, opisuje jedynie, za pomocą specjalnych poleceń, coś podobnego do konfigurowania środowiska pracy. Oto niektóre z tych poleceń:

  • OD — To polecenie uruchamia plik. Określa obraz podstawowy, na którym zbudowany jest kontener.
  • KOPIA — Kopiowanie plików z lokalnego źródła do kontenera.
  • KIERUNEK ROBOCZY — Ustawianie katalogu roboczego dla następujących poleceń.
  • BIEGAĆ - Uruchom polecenia.
  • OŚWIADCZENIE — Ustawienia portu.
  • PUNKT WEJŚCIA — 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 start

W zależności od wybranego obrazu podstawowego może być konieczne zainstalowanie dodatkowych zależności. Faktem jest, że niektóre obrazy podstawowe (takie jak Node Alpine Linux) są tworzone w celu uczynienia ich jak najbardziej kompaktowymi. W rezultacie mogą nie mieć niektórych programów, których oczekujesz.

▍Budowanie, tagowanie i uruchamianie kontenera

Za nami lokalny montaż i uruchomienie kontenera Dockerfile, zadania są dość proste. Zanim wypchniesz obraz do Docker Hub, musisz go przetestować lokalnie.

▍Montaż

Najpierw musisz zebrać obraz, podając nazwę i opcjonalnie tag (w przypadku braku tagu system automatycznie przypisze tag do obrazu) latest).

# Сборка образа
docker build -t <image>:<tag> .

Po uruchomieniu tego polecenia możesz obserwować, jak Docker buduje obraz.

Sending build context to Docker daemon   2.88MB
Step 1/9 : FROM node:12-alpine
 ---> ...выполнение этапов сборки...
Successfully built 123456789123
Successfully tagged <image>:<tag>

Kompilacja może zająć kilka minut - wszystko zależy od liczby posiadanych zależności. Po zakończeniu kompilacji możesz uruchomić polecenie docker images i spójrz na opis swojego nowego obrazu.

REPOSITORY          TAG               IMAGE ID            CREATED              SIZE
<image>             latest            123456789123        About a minute ago   x.xxGB

▍Uruchom

Obraz został stworzony. Oznacza to, że można na jego podstawie uruchomić kontener. Ponieważ chcę mieć dostęp do aplikacji działającej w kontenerze pod adresem localhost:5000, ja, po lewej stronie pary 5000:5000 w następnym zainstalowanym poleceniu 5000. Po prawej stronie znajduje się port kontenerowy.

# Запуск с использованием локального порта 5000 и порта контейнера 5000
docker run -p 5000:5000 <image>:<tag>

Teraz, gdy kontener jest już utworzony i uruchomiony, możesz użyć polecenia docker ps aby zobaczyć informacje o tym kontenerze (lub możesz użyć polecenia docker ps -a, który wyświetla informacje o wszystkich kontenerach, a nie tylko działających).

CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                      PORTS                    NAMES
987654321234        <image>             "/bin/sh -c 'npm run…"   6 seconds ago        Up 6 seconds                0.0.0.0:5000->5000/tcp   stoic_darwin

Jeśli teraz udasz się pod wskazany 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.

▍Tagowanie i publikowanie

Aby wykorzystać jeden z utworzonych obrazów na serwerze produkcyjnym, musimy mieć możliwość pobrania tego obrazu z Docker Hub. Oznacza to, że najpierw musisz utworzyć repozytorium projektu w Docker Hub. Następnie będziemy mieli miejsce, w którym będziemy mogli wysłać obraz. Należy zmienić nazwę obrazu, tak aby jego nazwa zaczynała się od naszej nazwy użytkownika Docker Hub. Po tym należy podać nazwę repozytorium. Na końcu nazwy można umieścić dowolny tag. Poniżej znajduje się przykład nazywania obrazów przy użyciu tego schematu.

Teraz możesz zbudować obraz pod nową nazwą i uruchomić polecenie docker push aby wypchnąć go do repozytorium Docker Hub.

docker build -t <username>/<repository>:<tag> .
docker tag <username>/<repository>:<tag> <username>/<repository>:latest
docker push <username>/<repository>:<tag>

# На практике это может выглядеть, например, так:
docker build -t user/app:v1.0.0 .
docker tag user/app:v1.0.0 user/app:latest
docker push user/app:v1.0.0

Jeśli wszystko pójdzie dobrze, obraz będzie dostępny w Docker Hub i będzie można go łatwo przesłać na serwer lub przekazać innym programistom.

Kolejne kroki

Do tej pory sprawdziliśmy, że aplikacja w postaci kontenera Docker działa lokalnie. Przesłaliśmy kontener do Docker Hub. Wszystko to oznacza, że ​​zrobiliśmy już bardzo duży postęp w kierunku naszego celu. Teraz musimy rozwiązać jeszcze dwa pytania:

  • Konfigurowanie narzędzia CI do testowania i wdrażania kodu.
  • Konfigurowanie serwera produkcyjnego tak, aby mógł pobrać i uruchomić nasz kod.

W naszym przypadku używamy Travis CI. Jako serwer - DitigalOcean.

Należy zauważyć, że tutaj możesz skorzystać z innej kombinacji usług. Na przykład zamiast Travis CI możesz użyć akcji CircleCI lub Github. I zamiast DigitalOcean - AWS lub Linode.

Zdecydowaliśmy się na współpracę z Travis CI i mam już coś skonfigurowanego w tej usłudze. Dlatego teraz krótko opowiem o tym, jak przygotować go do pracy.

Travis CI

Travis CI to narzędzie do testowania i wdrażania kodu. Nie chciałbym wdawać się w zawiłości konfiguracji Travis CI, ponieważ każdy projekt jest wyjątkowy, a to nie przyniesie zbyt wielu korzyści. Ale omówię podstawy, od których możesz zacząć, jeśli zdecydujesz się korzystać z Travis CI. Niezależnie od tego, czy wybierzesz Travis CI, CircleCI, Jenkins, czy coś innego, wszędzie będą stosowane podobne metody konfiguracji.

Aby rozpocząć korzystanie z Travis CI, przejdź do Strona projektu i utwórz konto. Następnie zintegruj Travis CI ze swoim kontem GitHub. Konfigurując system, będziesz musiał określić repozytorium, z którym chcesz zautomatyzować pracę i umożliwić dostęp do niego. (Korzystam z GitHuba, ale jestem pewien, że Travis CI może zintegrować się z BitBucket, GitLab i innymi podobnymi usługami).

Przy każdym uruchomieniu Travis CI uruchamiany jest serwer, który wykonuje polecenia określone w pliku konfiguracyjnym, łącznie z wdrażaniem odpowiednich gałęzi repozytorium.

▍Cykl życia pracy

Plik konfiguracyjny Travis CI o nazwie .travis.yml i przechowywane w katalogu głównym projektu, wspiera koncepcję zdarzeń koło życia zadania. Zdarzenia te są wymienione w kolejności ich występowania:

  • apt addons
  • cache components
  • before_install
  • install
  • before_script
  • script
  • before_cache
  • after_success или after_failure
  • before_deploy
  • deploy
  • after_deploy
  • after_script

▍Testowanie

W pliku konfiguracyjnym zamierzam skonfigurować lokalny serwer Travis CI. Jako język wybrałem Node 12 i poleciłem systemowi zainstalować zależności wymagane do korzystania z Dockera.

Wszystko, co jest wymienione w .travis.yml, zostanie wykonany, gdy wszystkie żądania ściągnięcia zostaną wysłane do wszystkich gałęzi repozytorium, chyba że określono inaczej. Jest to przydatna funkcja, ponieważ oznacza, że ​​możemy przetestować cały kod trafiający do repozytorium. Dzięki temu wiesz, czy kod jest gotowy do zapisania w gałęzi. masteri czy zakłóci to proces tworzenia projektu. W tej konfiguracji globalnej instaluję wszystko lokalnie, uruchamiam serwer deweloperski Webpack w tle (jest to funkcja mojego przepływu pracy) i uruchamiam testy.

Jeśli chcesz, aby w Twoim repozytorium wyświetlały się plakietki wskazujące pokrycie testami, tutaj Możesz znaleźć krótkie instrukcje dotyczące korzystania z Jest, Travis CI i kombinezonów do gromadzenia i wyświetlania tych informacji.

Oto więc 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 test

Na tym kończą się działania wykonywane dla wszystkich gałęzi repozytorium oraz dla żądań ściągnięcia.

▍Wdrożenie

Wychodząc z założenia, że ​​wszystkie testy automatyczne zakończyły się pomyślnie, możemy opcjonalnie wdrożyć kod na serwerze produkcyjnym. Ponieważ chcemy to zrobić tylko dla kodu z gałęzi master, podajemy systemowi odpowiednie instrukcje w ustawieniach wdrażania. Zanim spróbujesz użyć kodu, któremu przyjrzymy się dalej w Twoim projekcie, chciałbym Cię ostrzec, że musisz mieć wywołany rzeczywisty skrypt do wdrożenia.

deploy:
  # Собрать Docker-контейнер и отправить его на Docker Hub
  provider: script
  script: bash deploy.sh
  on:
    branch: master

Skrypt wdrażania rozwiązuje dwa problemy:

  • Zbuduj, oznacz i wyślij obraz do Docker Hub za pomocą narzędzia CI (w naszym przypadku Travis CI).
  • Załadowanie obrazu na serwer, zatrzymanie starego kontenera i uruchomienie nowego (w naszym przypadku serwer działa na platformie DigitalOcean).

Najpierw musisz skonfigurować automatyczny proces budowania, oznaczania i wypychania obrazu do Docker Hub. Wszystko to jest bardzo podobne do tego, co zrobiliśmy już ręcznie, z tą różnicą, że potrzebujemy strategii przypisywania unikalnych tagów do obrazów i automatyzacji logowania. Miałem trudności z niektórymi szczegółami skryptu wdrażania, takimi jak strategia tagowania, logowanie, kodowanie klucza SSH, ustanawianie połączenia SSH. Ale na szczęście mój chłopak jest bardzo dobry w bashu, podobnie jak w wielu innych rzeczach. Pomógł mi napisać ten scenariusz.

Zatem pierwszą częścią skryptu jest przesłanie obrazu do Docker Hub. Jest to całkiem łatwe do zrobienia. Schemat tagowania, którego użyłem, polega na połączeniu skrótu git i znacznika git, jeśli taki istnieje. Dzięki temu znacznik jest unikalny i ułatwia identyfikację zestawu, na którym się opiera. DOCKER_USERNAME и DOCKER_PASSWORD to zmienne środowiskowe użytkownika, które można ustawić za pomocą interfejsu Travis CI. Travis CI będzie automatycznie przetwarzał wrażliwe dane, tak aby nie dostały się one w niepowołane ręce.

Oto pierwsza część scenariusza 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, jaka będzie druga część skryptu, zależy całkowicie od tego, jakiego hosta używasz i jak zorganizowane jest połączenie z nim. W moim przypadku, ponieważ korzystam z Digital Ocean, używam poleceń, aby połączyć się z serwerem dokt. Podczas pracy z AWS narzędzie będzie używane aws, i tak dalej.

Konfiguracja serwera nie była szczególnie trudna. Skonfigurowałem więc kroplę w oparciu o obraz podstawowy. Należy zaznaczyć, że wybrany przeze mnie system wymaga jednorazowej ręcznej instalacji Dockera i jednorazowego ręcznego uruchomienia Dockera. Do zainstalowania Dockera użyłem Ubuntu 18.04, więc jeśli używasz Ubuntu do zrobienia tego samego, możesz po prostu postępować zgodnie z to prosty przewodnik.

Nie mówię tutaj o konkretnych poleceniach dla usługi, ponieważ ten aspekt może się znacznie różnić w różnych przypadkach. Podam tylko ogólny plan działania do wykonania po połączeniu się przez SSH z serwerem, na którym projekt będzie wdrożony:

  • Musimy znaleźć aktualnie uruchomiony kontener i go zatrzymać.
  • Następnie musisz uruchomić nowy kontener w tle.
  • Będziesz musiał ustawić port lokalny serwera na 80 - umożliwi to wejście na stronę pod adresem np example.com, bez określania portu, zamiast używać adresu takiego jak example.com:5000.
  • Na koniec musisz usunąć wszystkie stare kontenery i obrazy.

Oto kontynuacja scenariusza.

# Найти 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 -f

Kilka rzeczy, na które warto zwrócić uwagę

Możliwe, że gdy połączysz się z serwerem przez SSH z Travis CI, zobaczysz ostrzeżenie, które uniemożliwi kontynuację instalacji, ponieważ system będzie czekać na odpowiedź użytkownika.

The authenticity of host '<hostname> (<IP address>)' can't be established.
RSA key fingerprint is <key fingerprint>.
Are you sure you want to continue connecting (yes/no)?

Dowiedziałem się, że klucz łańcuchowy można zakodować w base64, aby zapisać go w formie, w której można z nim wygodnie i niezawodnie pracować. Na etapie instalacji możesz odszyfrować klucz publiczny i zapisać go do pliku known_hosts aby pozbyć się powyższego błędu.

echo <public key> | base64 # выводит <публичный ключ, закодированный в base64>

W praktyce polecenie to może wyglądać następująco:

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== [email protected]" | base64

A oto co generuje — ciąg zakodowany w formacie base64:

MTIzLjQ1LjY3Ljg5IHNzaC1yc2EgQUFBQUIzTnphQzF5YzJFQUFBQUJJd0FBQVFFQWtsT1Vwa0RIcmZIWTE3U2JybVRJcE5MVEdLOVRqb20vQldEU1UKR1BsK25hZnpsSERUWVc3aGRJNHlaNWV3MThKSDRKVzlqYmhVRnJ2aVF6TTd4bEVMRVZmNGg5bEZYNVFWa2JQcHBTd2cwY2RhMwpQYnY3a09kSi9NVHlCbFdYRkNSK0hBbzNGWFJpdEJxeGlYMW5LaFhwSEFac01jaUxxOFY2UmpzTkFRd2RzZE1GdlNsVksvN1hBCnQzRmFvSm9Bc25jTTFROXg1KzNWMFd3NjgvZUlGbWIxenVVRmxqUUpLcHJyWDg4WHlwTkR2allOYnk2dncvUGIwcndlcnQvRW4KbVorQVc0T1pQblRQSTg5WlBtVk1MdWF5ckQyY0U4NlovaWw4YitndzNyMysxbkthdG1Ja2puMnNvMWQwMVFyYVRsTXFWU3NieApOclJGaTl3cmYrTTdRPT0geW91QGV4YW1wbGUuY29tCg==

Oto polecenie wspomniane powyżej

install:
  - echo < публичный ключ, закодированный в base64> | base64 -d >> $HOME/.ssh/known_hosts

To samo podejście można zastosować w przypadku klucza prywatnego podczas ustanawiania połączenia, ponieważ do uzyskania dostępu do serwera możesz potrzebować klucza prywatnego. Pracując z kluczem, wystarczy upewnić się, że jest on bezpiecznie przechowywany w zmiennej środowiskowej Travis CI i że nie jest nigdzie wyświetlany.

Kolejną rzeczą wartą odnotowania jest to, że może być konieczne uruchomienie całego skryptu wdrażania w jednej linii, na przykład za pomocą doctl. Może to wymagać dodatkowego wysiłku.

doctl compute ssh <droplet> --ssh-command "все команды будут здесь && здесь"

TLS/SSL i równoważenie obciążenia

Po wykonaniu wszystkiego, o czym wspomniałem powyżej, ostatnim problemem, jaki napotkałem, był brak protokołu SSL na serwerze. Ponieważ używam serwera Node.js, aby wymusić praca odwrotne proxy Nginx i Let's Encrypt, musisz dużo majstrować.

Naprawdę nie chciałem wykonywać całej tej konfiguracji SSL ręcznie, więc po prostu utworzyłem moduł równoważenia obciążenia i zapisałem jego szczegóły w DNS. Na przykład w przypadku DigitalOcean utworzenie automatycznie odnawiającego się certyfikatu z podpisem własnym w module równoważenia obciążenia jest prostą, bezpłatną i szybką procedurą. Takie podejście ma tę dodatkową zaletę, że w razie potrzeby bardzo ułatwia konfigurację protokołu SSL na wielu serwerach działających za modułem równoważenia obciążenia. Dzięki temu same serwery w ogóle nie „myślą” o SSL, ale jednocześnie korzystają z portu w zwykły sposób 80. Zatem konfiguracja SSL w module równoważenia obciążenia jest znacznie łatwiejsza i wygodniejsza niż alternatywne metody konfigurowania SSL.

Teraz możesz zamknąć wszystkie porty na serwerze, które akceptują połączenia przychodzące - z wyjątkiem portu 80, używany do komunikacji z modułem równoważenia obciążenia i portem 22 dla SSH. W rezultacie próba bezpośredniego dostępu do serwera na portach innych niż te dwa zakończy się niepowodzeniem.

Wyniki

Po tym jak zrobiłem wszystko o czym mówiłem w tym materiale, ani platforma Docker, ani koncepcje zautomatyzowanych łańcuchów CI/CD już mnie nie przerażały. Udało mi się stworzyć ciągły łańcuch integracji, podczas którego kod jest testowany przed wejściem do produkcji i automatycznie wdrażany na serwerze. To wszystko jest dla mnie wciąż stosunkowo nowe i jestem pewien, że istnieją sposoby na ulepszenie mojego zautomatyzowanego przepływu pracy i zwiększenie jego wydajności. Jeśli więc masz jakieś pomysły w tej kwestii, daj mi znać. mnie wiedzieć. Mam nadzieję, że ten artykuł pomógł ci w twoich wysiłkach. Chcę wierzyć, że po jej przeczytaniu nauczyliście się tyle samo, co ja, jednocześnie domyślając się wszystkiego, o czym w niej mówiłem.

PS В нашем rynek jest obraz Doker, który można zainstalować jednym kliknięciem. Działanie kontenerów można sprawdzić na stronie VPS. Wszystkim nowym klientom oferujemy 3 dni testów bezpłatnie.

Drodzy Czytelnicy! Czy w swoich projektach wykorzystujecie technologie CI/CD?

Tworzenie łańcucha CI/CD i automatyzacja pracy z Dockerem

Źródło: www.habr.com

Dodaj komentarz