Crearea unui lanț CI/CD și automatizarea lucrului cu Docker.

Am scris primele mele site-uri la sfârșitul anilor '90. Atunci era foarte simplu să le pui în funcțiune. Era un server Apache pe un serviciu de hosting comun, la care se putea accesa prin FTP, tastând în bara de adrese a browserului ceva de genul ftp://ftp.example.com. Apoi, trebuia să introduci un nume de utilizator și o parolă și să încarci fișierele pe server. Alte vremuri, totul era mai simplu decât acum.

Crearea unui lanț CI/CD și automatizarea lucrului cu Docker.

În cele două decenii care au trecut de atunci, multe s-au schimbat. Site-urile au devenit mai complexe, iar înainte de lansarea în producție, trebuie să fie compilate. Un singur server a devenit o mulțime de servere, lucrând prin echilibratoare de sarcină, iar utilizarea sistemelor de control al versiunilor a devenit normal.

Pentru proiectul meu personal, am avut o configurație specială. Știam că am nevoie de posibilitatea de a desfășura site-ul în producție, efectuând o singură acțiune: să scriu codul în ramura master de pe GitHub. De asemenea, știam că nu vreau să gestionez un cluster imens de Kubernetes pentru a asigura funcționarea micii mele aplicații web, să utilizez Docker Swarm sau să mențin un parc de servere cu module, agenți și alte complexități. Pentru a atinge obiectivul de a simplifica munca la maxim, a trebuit să mă familiarizez cu CI/CD.

Dacă ai un proiect mic (în cazul nostru, vorbim despre un proiect Node.js) și vrei să înveți cum să automatizezi desfășurarea acestuia, asigurându-te că ceea ce se află în depozit corespunde exact cu ceea ce este în producție, cred că te-ar putea interesa acest articol.

Cerințe preliminare

Se așteaptă ca cititorul acestui articol să aibă cunoștințe de bază despre utilizarea liniei de comandă și scrierea scripturilor Bash. De asemenea, va avea nevoie de conturi Travis CI și Docker Hub.

Obiective

Nu aș spune că acest articol poate fi considerat fără ezitare un „ghid didactic”. Este mai degrabă un document în care împărtășesc ce am învățat și descriu procesul de testare și desfășurare a codului în producție, realizat într-o singură trecere automatizată.

Iată cum a rezultat, în cele din urmă, procesul meu de lucru.

Pentru codul trimis în orice ramură a depozitului, cu excepția master, se efectuează următoarele acțiuni:

  • Se pornește construirea proiectului pe Travis CI.
  • Se efectuează toate testele unitare, de integrare și funcționale.

Numai pentru codul care ajunge în master, se execută următoarele:

  • Tot ceea ce s-a spus mai sus, plus…
  • Construirea unei imagini Docker pe baza codului, setărilor și mediului curent.
  • Încărcarea imaginii pe Docker Hub.
  • Conectarea la serverul de producție.
  • Descărcarea imaginii de pe Docker Hub pe server.
  • Oprirea containerului curent și pornirea unuia nou, bazat pe noua imagine.

Dacă nu știți nimic despre Docker, imagini și containere — nu vă faceți griji. Voi explica totul despre acestea.

Ce este CI/CD?

Abrevierea CI/CD se traduce prin 'integrare continuă/implementare continuă'.

▍Integrare continuă

Integrarea continuă este un proces în care dezvoltatorii fac commit-uri în depozitul principal de cod sursă al proiectului (de obicei în ramura master). Calitatea codului este asigurată prin teste automatizate.

▍Implementare continuă

Implementarea continuă este desfășurarea frecventă și automatizată a codului în producție. A doua parte a abreviaturii CI/CD este uneori dezvăluită ca 'livrare continuă'. Aceasta este, în general, același lucru cu 'implementare continuă', dar 'livrarea continuă' implică necesitatea confirmării manuale a modificărilor înainte de a lansa procesul de desfășurare a proiectului.

Începerea utilizării

Aplicația pe care am învățat totul aceasta se numește TakeNote. Acesta este un proiect web la care lucrez, destinat pentru a face note. La început am încercat să creez un proiect JAMStack- sau doar o aplicație frontend fără server, pentru a profita de caracteristicile standard de găzduire și desfășurare a proiectelor oferite de Netlify. Pe măsură ce complexitatea aplicației a crescut, a trebuit să îmi creez și partea serverului, ceea ce a însemnat că ar fi trebuit să formulez propria strategie de integrare automatizată și desfășurare automatizată a proiectului.

În cazul meu, aplicația reprezintă un server Express care funcționează în mediu Node.js, servind o aplicație React de o pagină și susținând un API server protejat. Această arhitectură urmează o strategie pe care o puteți găsi în acest ghid de autentificare full-stack.

Am consultat alt, care este expert în automatizare, și l-am întrebat despre ce ar trebui să fac pentru ca toate acestea să funcționeze așa cum îmi doresc. Mi-a sugerat o idee despre cum ar trebui să arate fluxul de lucru automatizat, prezentat în secțiunea „Obiective” a acestui articol. Faptul că mi-am propus astfel de obiective înseamnă că trebuie să învăț cum să folosesc Docker.

Docker

Docker este un instrument care, datorită tehnologiei de containerizare, permite distribuirea ușoară a aplicațiilor, precum și desfășurarea și rularea lor în același mediu, chiar dacă platforma Docker funcționează în medii diverse. Pentru început, am avut nevoie să obțin instrumentele de linie de comandă (CLI) Docker. Instrucțiunea pentru instalarea Docker nu poate fi considerată foarte clară și ușor de înțeles, dar din ea se poate învăța că, pentru a face primul pas în instalare, trebuie să descarci Docker Desktop (pentru Mac sau Windows).

Docker Hub este cam același lucru GitHub cu repositoriile git, sau un registru npm pentru pachetele JavaScript. Acesta este un repository online pentru imaginile Docker. La el se conectează Docker Desktop.

Așadar, pentru a începe lucrul cu Docker, trebuie să faci două lucruri:

După aceasta, poți verifica funcționalitatea Docker CLI, rulând următoarea comandă pentru a verifica versiunea Docker:

docker -v

Apoi, conectează-te la Docker Hub, introducând, atunci când ți se cere, numele de utilizator și parola:

docker login

Pentru a folosi Docker, trebuie să înțelegi conceptele de imagini și containere.

▍Imagini

O imagine este ca un plan, conținând instrucțiuni pentru construirea unui container. Este o captură de ecran nemodificată a sistemului de fișiere și a setărilor aplicației. Dezvoltatorii pot face schimb de imagini cu ușurință.

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

Această comandă va afișa un tabel cu următoarea antet:

REPOSITORY     TAG     IMAGE ID     CREATED     SIZE
---

Mai departe, vom analiza câteva exemple de comenzi într-un format similar — începutul va fi comanda cu un comentariu, iar apoi un exemplu al output-ului său.

▍Containere

Un container este un pachet executabil care conține tot ce este necesar pentru a rula o aplicație. Astfel, aplicația va funcționa întotdeauna la fel, indiferent de infrastructură: într-un mediu izolat și în aceeași mediu. Este vorba despre faptul că instanțele aceleași imagini sunt lansate în diferite medii.

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

▍Etichete

O etichetă este o indicație a unei versiuni specifice a imaginii.

▍Informații generale despre comenzile Docker

Iată o privire de ansamblu asupra unor comenzi Docker frecvent utilizate.

Comanda

Context

Acțiune

docker build

Tip

Construirea imaginii din Dockerfile

docker tag

Tip

Etichetarea imaginii

docker images

Tip

Lista imaginilor

docker run

Container

Pornirea containerului pe baza imaginii

docker push

Tip

Trimiterea imaginii către registru

docker pull

Tip

Descărcarea imaginii din registru

docker ps

Container

Lista containerelor

docker system prune

Imagine/Container

Ștergerea containerelor și imaginilor neutilizate

▍Fișier Dockerfile

Știu cum să rulez local o aplicație pentru producție. Am o configurație Webpack destinată construirii unei aplicații React gata de utilizare. În continuare, am o comandă care pornește un server bazat pe Node.js pe portul 5000. Asta arată așa:

npm i         # instalarea dependențelor
npm run build # construirea aplicației React
npm run start # pornirea serverului Node

Trebuie menționat că nu am o aplicație de exemplu pentru acest material. Dar, pentru experimente, orice aplicație simplă Node va funcționa.

Pentru a folosi containerul, trebuie să oferiți instrucțiuni Docker. Acest lucru se realizează printr-un fișier numit Dockerfile, aflat în directorul rădăcină al proiectului. Acest fișier pare, la început, destul de incomprehensibil.

Dar ceea ce conține nu este decât o descriere, prin comenzi specifice, a unei configurații asemănătoare cu setarea unui mediu de lucru. Iată câteva dintre aceste comenzi:

  • FROM — Această comandă începe fișierul. Se specifică imaginea de bază pe care se bazează containerul.
  • COPIE — Copierea fișierelor dintr-o sursă locală în container.
  • WORKDIR — Setarea directorului de lucru pentru comenzile următoare.
  • comenzi RUN după semnificație. — Executarea comenzilor.
  • EXPOSE — Configurarea portului.
  • ENTRYPOINT — Specificarea comenzii care trebuie executată.

Dockerfile poate arăta cam așa:

# Загрузить базовый образ
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

În funcție de imaginea de bază aleasă, este posibil să fie necesar să instalați dependențe suplimentare. Unele imagini de bază (precum Node Alpine Linux) sunt proiectate pentru a fi cât mai compacte. Ca urmare, este posibil să lipsească anumite programe pe care le-ați așteptat.

▍Construirea, etichetarea și rularea containerului

Construirea și rularea locală a containerului — asta se întâmplă după ce avem Dockerfile, sarcinile fiind destul de simple. Înainte de a trimite imaginea pe Docker Hub, trebuie testată local.

▍Construirea

Primul pas este să construim imagine, specificând un nume și, opțional, un tag (dacă nu se specifică un tag, sistemul va atribui automat un tag imaginii) latest).

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

După ce această comandă este executată, puteți observa cum Docker construiește imaginea.

Trimiterea contextului de construcție către daemonul Docker   2.88MB
Pasul 1/9 : FROM node:12-alpine
 —> ...executarea etapelor de construcție...
Construire reușită 123456789123
Etichetare reușită <imagine>:<tag>

Construcția poate dura câteva minute — totul depinde de câte dependențe aveți. După finalizarea construcției, puteți executa comanda docker images și să vizualizați descrierea noii dumneavoastră imagini.

REPOSITORY          TAG               IMAGE ID            CREATED              SIZE
<imagine>             latest            123456789123        Acum aproximativ un minut   x.xxGB

▍Rularea

Imaginea a fost creată. Asta înseamnă că pe baza ei se poate rula un container. Deoarece vreau să pot accesa aplicația care rulează în container la adresa localhost:5000, am setat în partea stângă a perechii 5000:5000 în următoarea comandă. 5000. În partea dreaptă se află portul containerului.

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

Acum, când containerul este creat și pornit, puteți folosi comanda docker ps pentru a vizualiza informațiile despre acest container (sau puteți folosi comanda docker ps -a, care afișează informații despre toate containerele, nu doar despre cele în funcțiune).

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

Dacă accesați acum adresa localhost:5000 — puteți vedea pagina aplicației funcționale, care arată exact ca pagina aplicației din mediul de producție.

▍Atribuirea etichetei și publicarea

Pentru a folosi una dintre imaginile create pe serverul de producție, trebuie să avem posibilitatea de a încărca această imagine din Docker Hub. Aceasta înseamnă că trebuie să creăm mai întâi un repository pe Docker Hub pentru proiect. După aceea, vom avea un loc unde putem trimite imaginea. Imaginea trebuie redenumită astfel încât numele să înceapă cu numele nostru de utilizator de pe Docker Hub. Următorul lucru trebuie să fie numele repository-ului. La finalul numelui poate fi plasat orice tag. Mai jos este un exemplu de denumire a imaginilor conform acestei scheme.

Acum putem construi imaginea, acordându-i un nou nume și executând comanda docker push pentru a o trimite în repository-ul Docker Hub.

docker build -t \/ : .
docker tag \/ : \/ :latest
docker push \/ :

# În practică, aceasta ar putea arăta, de exemplu, astfel:
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

Dacă totul decurge bine, imaginea va fi disponibilă pe Docker Hub și va putea fi ușor încărcată pe server sau transmisă altor dezvoltatori.

Următorii pași

Până în prezent, ne-am asigurat că aplicația, sub formă de container Docker, funcționează local. Am încărcat containerul pe Docker Hub. Tot acest lucru înseamnă că am avansat semnificativ către obiectiv. Acum trebuie să rezolvăm încă două întrebări:

  • Configurarea instrumentului CI pentru testarea și desfășurarea codului.
  • Configurarea serverului de producție astfel încât să poată încărca și rula codul nostru.

În cazul nostru, ca soluție CI/CD se utilizează Travis CI. Ca server — DigitalOcean.

Trebuie menționat că aici se poate folosi și o altă combinație de servicii. De exemplu, în loc de Travis CI, se poate utiliza CircleCI sau Github Actions. Și în loc de DigitalOcean — AWS sau Linode.

Am decis să lucrăm cu Travis CI, iar în acest serviciu am deja câteva setări realizate. Așadar, acum voi explica pe scurt cum să-l pregătim pentru utilizare.

Travis CI

Travis CI este un instrument pentru testarea și desfășurarea codului. Nu mi-aș dori să intru în detaliile configurării Travis CI, deoarece fiecare proiect este unic și acest lucru nu ar aduce o valoare semnificativă. Totuși, voi vorbi despre elementele de bază care vă vor permite să începeți să lucrați în cazul în care decideți să utilizați Travis CI. Indiferent ce alegeți — Travis CI, CircleCI, Jenkins sau altceva, metodele de configurare vor fi similare.

Pentru a începe să lucrați cu Travis CI, vizitați site-ul proiectului și creați un cont. Apoi, integrați Travis CI cu contul dumneavoastră GitHub. În timpul configurării sistemului, va trebui să specificați depozitul cu care doriți să automatizați lucrul și să activați accesul la acesta. (Eu folosesc GitHub, dar sunt sigură că Travis CI se poate integra și cu BitBucket, și cu GitLab, și cu alte servicii similare).

De fiecare dată când Travis CI începe să lucreze, se lansează un server care execută comenzile specificate în fișierul de configurare, inclusiv desfășurarea ramurilor corespunzătoare ale depozitului.

▍Ciclul de viață al sarcinii

Fișierul de configurare Travis CI, numit .travis.yml și stocat în directorul rădăcină al proiectului, susține conceptul de evenimente ciclului de viață al sarcinii. Iată aceste evenimente, enumerate în ordinea în care apar:

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

▍Testare

În fișierul de configurare, intenționez să configurez un server local Travis CI. Ca limbaj, am ales Node versiunea 12 și am indicat sistemului să instaleze dependențele necesare pentru utilizarea Docker.

Tot ce este enumerat în .travis.yml, va fi executat la fiecare pull request pe toate ramurile depozitului, cu excepția cazului în care se specifică altceva. Aceasta este o caracteristică utilă, deoarece înseamnă că putem testa tot codul care intră în depozit. Aceasta ne permite să știm dacă codul este pregătit pentru a fi înregistrat în ramură master, și dacă nu va afecta procesul de compilare al proiectului. În această configurație globală, instalez totul local, pornesc serverul dezvoltatorului Webpack în fundal (aceasta este o caracteristică a fluxului meu de lucru) și execut teste.

Dacă doriți ca în depozitul dumneavoastră să apară insigne cu informații despre acoperirea codului de teste, aici puteți găsi un ghid scurt despre utilizarea Jest, Travis CI și Coveralls pentru a colecta și a afișa aceste informații.

Așadar, iată conținutul fișierului .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

Aici se încheie acele acțiuni care se execută pentru toate ramurile depozitului și pentru pull requests.

▍Desfășurare

Pornind de la presupunerea că toate testele automatizate s-au finalizat cu succes, noi, ceea ce nu este obligatoriu, putem desfășura codul pe serverul de producție. Deoarece dorim să facem acest lucru doar pentru codul din ramură master, oferim sistemului instrucțiuni corespunzătoare în setările de desfășurare. Înainte de a încerca să folosiți în proiectul dumneavoastră codul pe care îl vom analiza mai departe, aș dori să vă atenționez că trebuie să aveți un script real, apelat pentru desfășurare.

deploy:
  # Construiește containerul Docker și trimite-l pe Docker Hub
  provider: script
  script: bash deploy.sh
  on:
    branch: master

Scriptul de desfășurare are două sarcini:

  • Construirea, etichetarea și trimiterea imaginii pe Docker Hub cu ajutorul instrumentului CI (în cazul nostru, este Travis CI).
  • Încărcarea imaginii pe server, oprirea containerului vechi și pornirea celui nou (în cazul nostru, serverul operează pe platforma DigitalOcean).

Mai întâi, trebuie să configurăm procesul automat de construire, etichetare și trimitere a imaginii pe Docker Hub. Totul este foarte similar cu ceea ce am făcut manual, cu excepția faptului că avem nevoie de o strategie pentru atribuirea de etichete unice imaginilor și automatizarea autentificării. Am avut dificultăți cu unele detalii ale scriptului de desfășurare, cum ar fi strategia de etichetare, autentificarea, codificarea cheilor SSH și stabilirea conexiunii SSH. Dar, din fericire, prietenul meu se descurcă foarte bine cu bash, la fel ca și cu multe alte lucruri. El m-a ajutat să scriu acest script.

Așadar, prima parte a scriptului este trimiterea imaginii pe Docker Hub. A face acest lucru este destul de simplu. Schema de etichetare pe care am folosit-o implică combinarea hash-ului git și etichetei git, dacă există. Acest lucru asigură crearea unei etichete unice și simplifică identificarea compilării pe care se bazează. DOCKER_USERNAME și DOCKER_PASSWORD — sunt variabile de mediu utilizator care pot fi setate prin intermediul interfeței Travis CI. Travis CI va gestiona automat datele sensibile astfel încât acestea să nu fie expuse altora.

Iată prima parte a scriptului 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}

Ce va fi a doua parte a scriptului depinde în totalitate de ce gazdă folosiți și de modul în care este organizată conectarea la aceasta. În cazul meu, deoarece folosesc Digital Ocean, comenzile utilizate pentru conectarea la server sunt doctl. La lucru cu AWS se va folosi utilitarul aws, și așa mai departe.

Configurarea funcționării serverului nu a fost foarte complicată. Așadar, am configurat un droplet bazat pe imaginea de bază. Trebuie menționat că sistemul ales de mine necesită o instalare manuală unică a Docker și o pornire manuală unică a Docker. Eu am folosit Ubuntu 18.04 pentru instalarea Docker, așa că, dacă folosiți și voi Ubuntu pentru a face același lucru, puteți pur și simplu să urmați acestei ghidul simplu.

Nu vorbesc aici despre comenzile specifice pentru serviciu, deoarece acest aspect poate să varieze semnificativ în diferite situații. Voi prezenta doar un plan general de acțiune, realizat după conectarea prin SSH la serverul pe care va fi desfășurat proiectul:

  • Trebuie să găsim containerul care rulează în prezent și să-l oprim.
  • Apoi, trebuie să lansăm un nou container în fundal.
  • Va trebui să setați portul local al serverului la valoarea 80 — acest lucru va permite accesul la site la adresa de tip example.com, fără a specifica portul, și nu să folosiți adresa de genul example.com:5000.
  • Și, în cele din urmă, trebuie să ștergeți toate containerele și imaginile vechi.

Iată continuarea scriptului.

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

Câteva lucruri la care merită să fiți atenți

Este posibil ca, atunci când vă conectați la server prin SSH din Travis CI, să vedeți un avertisment care nu va permite continuarea instalării, deoarece sistemul va aștepta o reacție din partea utilizatorului.

Autenticitatea gazdei '<hostname> (<IP address>)' nu poate fi stabilită.
Amprenta cheii RSA este <key fingerprint>.
Sunteți sigur că doriți să continuați conectarea (da/nu)?

Am aflat că cheia pe șir poate fi codificată în base64 pentru a fi păstrată într-o formă cu care să fie ușor și sigur de lucrat. În timpul instalării, cheia publică poate fi decodificată și scrisă într-un fișier known_hosts pentru a scăpa de eroarea descrisă mai sus.

echo <public key> | base64 # produce <cheia publică, codificată în base64>

În practică, acestă comandă poate arăta așa:

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" | base64

Iată cum arată ceea ce produce — un șir în codificare base64:

123.45.67.89 ssh-rsa AABAB3NzaC1y...QExExample.com

Iată comanda menționată anterior

install:
  - echo  | base64 -d >> $HOME/.ssh/known_hosts

Aceeași abordare poate fi utilizată cu cheia privată atunci când stabiliți o legătură, deoarece este posibil să aveți nevoie de cheia privată pentru a accesa serverul. Când lucrați cu cheia, trebuie doar să asigurați stocarea sa sigură în variabila de mediu Travis CI, iar aceasta să nu fie printată nicăieri.

Un alt aspect de care ar trebui să țineți cont este că este posibil să trebuiască să rulați întregul script de desfășurare, prezentat ca un singur șir, de exemplu — folosind doctl. Acest lucru poate necesita unele eforturi suplimentare.

doctl compute ssh  --ssh-command "toate comenzile vor fi aici && aici"

TLS/SSL și echilibrarea încărcării

După ce am făcut tot ce am discutat mai sus, ultima problemă întâmpinată a fost că serverul nu avea SSL. Deoarece folosesc un server Node.js, pentru a face funcționa un proxy invers Nginx și Let’s Encrypt, trebuie să muncești destul.

Nu am vrut deloc să fac toate aceste configurații SSL manual, așa că am creat doar un echilibrator de încărcare și am salvat informațiile despre acesta în DNS. În cazul DigitalOcean, de exemplu, crearea automată a unui certificat auto-semnat pe echilibratorul de încărcare este o procedură simplă, gratuită și rapidă. Această abordare are și un avantaj suplimentar, în măsura în care permite să configurăm foarte simplu SSL pe mai multe servere care operează în spatele echilibratorului de încărcare. Aceasta face ca serverele în sine să nu trebuiască să „se gândească” la SSL, dar să folosească, de obicei, portul 80. Așadar, configurarea SSL pe echilibratorul de încărcare este mult mai simplă și mai comodă decât metodele alternative de configurare SSL.

Acum se pot închide toate porturile de pe server care acceptă conexiuni externe — în afară de portul 80, utilizat pentru comunicația cu echilibratorul de încărcare, și portul 22 pentru SSH. Prin urmare, încercarea de a accesa direct serverul pe orice porturi, cu excepția acestor două, va eșua.

Concluzii

După ce am realizat tot ce am descris în acest material, atât platforma Docker, cât și conceptele de fluxuri de lucru CI/CD nu mă mai sperie. Am reușit să configurez un flux de integrare continuă, în care codul este testat înainte de a ajunge în producție și este desfășurat automat pe server. Toate acestea sunt încă relativ noi pentru mine și sunt sigură că există modalități de a îmbunătăți fluxul meu de lucru automatizat și de a-l face mai eficient. Așadar, dacă aveți idei despre acest subiect — spuneți-mi mi se pare să știu. Sper că acest articol v-a fost de ajutor în activitățile voastre. Îmi doresc să cred că, citind-l, ați învățat la fel de mult cât am învățat eu în timp ce mă familiarizam cu tot ce am menționat aici.

P.S. În materialul nostru pe marketplace există o imagine Docker, care se instalează cu un singur clic. Puteți verifica funcționarea containerelor pe VPS. Toți clienții noi beneficiază de 3 zile gratuite pentru testare.

Stimați cititori! Folosiți tehnologiile CI/CD în proiectele voastre?

Crearea unui lanț CI/CD și automatizarea lucrului cu Docker.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster