Ho scritto i miei primi siti alla fine degli anni '90. Allora era molto semplice renderli operativi. C'era un server Apache su un hosting condiviso, a cui si poteva accedere via FTP, scrivendo nella barra degli indirizzi del browser qualcosa come ftp://ftp.example.com. Poi era necessario inserire nome utente e password e caricare i file sul server. Erano altri tempi, tutto era più semplice allora rispetto a oggi.
Negli ultimi due decenni, tutto è cambiato notevolmente. I siti sono diventati più complessi e, prima del rilascio in produzione, devono essere assemblati. Un unico server è diventato un insieme di server che lavorano dietro bilanciatori di carico, l'uso di sistemi di controllo versione è diventato normale.
Per il mio progetto personale avevo una configurazione speciale. E sapevo che avevo bisogno della possibilità di implementare il sito in produzione eseguendo un'unica azione: scrivere il codice nel branch master su GitHub. Inoltre, sapevo che, per garantire il funzionamento della mia piccola applicazione web, non volevo gestire un enorme cluster Kubernetes, o utilizzare la tecnologia Docker Swarm, o sostenere un parco server con pod, agenti e altre complessità. Per raggiungere l'obiettivo di semplificare al massimo il lavoro, avevo bisogno di familiarizzare con CI/CD.
Se hai un piccolo progetto (nel nostro caso stiamo parlando di un progetto Node.js) e ti piacerebbe sapere come automatizzare il rilascio di questo progetto, facendo in modo che ciò che è contenuto nel repository corrisponda esattamente a ciò che funziona in produzione, allora credo che questo articolo possa interessarti.
Requisiti preliminari
Ci si aspetta che il lettore di questo articolo abbia una conoscenza di base del funzionamento della riga di comando e della scrittura di script Bash. Inoltre, avrà bisogno di account e .
Obiettivi
Non dirò che questo articolo possa essere considerato senza riserve una "guida pratica". È piuttosto un documento in cui racconto ciò che ho imparato e descrivo il processo di test e distribuzione del codice in produzione che mi soddisfa, eseguito con un solo passaggio automatizzato.
Ecco come è diventato il mio flusso di lavoro.
Per il codice inviato in qualsiasi branch del repository, tranne master, vengono eseguite le seguenti azioni:
- Viene avviata la build del progetto su Travis CI.
- Vengono eseguiti tutti i test unitari, di integrazione e end-to-end.
Solo per il codice che si inserisce in master, viene eseguito il seguente processo:
- Tutto ciò che è stato detto sopra, più…
- Creazione dell'immagine Docker basata sul codice corrente, sulle impostazioni e sull'ambiente.
- Pubblicazione dell'immagine su Docker Hub.
- Connessione al server di produzione.
- Caricamento dell'immagine da Docker Hub sul server.
- Interruzione del contenitore corrente e avvio di uno nuovo, basato sulla nuova immagine.
Se non sai assolutamente nulla di Docker, delle immagini e dei contenitori, non preoccuparti. Ti parlerò di tutto questo.
Cos'è CI/CD?
L'abbreviazione CI/CD sta per «integrazione continua / distribuzione continua».
▍Integrazione continua
L'integrazione continua è un processo in cui gli sviluppatori effettuano commit nel repository principale del codice sorgente del progetto (di solito nel ramo master). Durante questo processo, la qualità del codice è garantita attraverso test automatizzati.
▍Distribuzione continua
La distribuzione continua è un rilascio automatizzato e frequente del codice in produzione. La seconda parte dell'abbreviazione CI/CD viene talvolta interpretata come «consegna continua». Questo è, in generale, lo stesso della «distribuzione continua», ma la «consegna continua» implica la necessità di una conferma manuale delle modifiche prima di avviare il processo di distribuzione del progetto.
Inizio del lavoro
L'applicazione su cui ho appreso tutto questo si chiama . È un progetto web su cui sto lavorando, destinato a prendere appunti. Inizialmente ho cercato di creare un , o un'applicazione front-end senza server, per approfittare delle possibilità standard di hosting e distribuzione di progetti offerte da . Con l'aumentare della complessità dell'applicazione, ho dovuto creare anche la sua parte server, il che significava che dovevo sviluppare una mia strategia per l'integrazione automatizzata e la distribuzione automatizzata del progetto.
Nel mio caso, l'applicazione è un server Express che opera in un ambiente Node.js, gestendo un'applicazione React a pagina singola e supportando un'API server sicura. Questa architettura segue una strategia che puoi trovare in guida all'autenticazione full-stack.
Ho consultato , che è un esperto di automazione, e gli ho chiesto cosa devo fare affinché tutto funzioni come voglio io. Mi ha suggerito un'idea su come dovrebbe essere il processo di lavoro automatizzato, descritto nella sezione “Obiettivi” di questo articolo. Il fatto che avessi fissato obiettivi del genere significava che dovevo capire come utilizzare Docker.
Docker
Docker è uno strumento che, grazie alla tecnologia di containerizzazione, consente di distribuire facilmente le applicazioni e di eseguirne il deployment e l'avvio nello stesso ambiente, anche se la piattaforma Docker stessa funziona in ambienti diversi. Per iniziare, avevo bisogno di avere a disposizione gli strumenti della riga di comando (CLI) di Docker. per l'installazione di Docker non possono essere definite molto chiare e comprensibili, ma da esse si può capire che, per fare il primo passo nell'installazione, è necessario scaricare Docker Desktop (per Mac o Windows).
Docker Hub è più o meno ciò che è per i repository git, o un registro per i pacchetti JavaScript. Si tratta di un repository online per le immagini di Docker. È a esso che si collega Docker Desktop.
Quindi, per iniziare a lavorare con Docker, è necessario fare due cose:
- Installare .
- Registrati su .
Dopo di ciò, puoi controllare se Docker CLI funziona correttamente eseguendo il seguente comando per verificare la versione di Docker:
docker -vSuccessivamente, accedi a Docker Hub inserendo, quando richiesto, il tuo nome utente e password:
docker loginPer utilizzare Docker, è necessario comprendere i concetti di immagini e contenitori.
▍Immagini
Un'immagine è un po' come un piano che contiene istruzioni per costruire un contenitore. È uno snapshot immutabile del file system e delle impostazioni dell'applicazione. Gli sviluppatori possono scambiare immagini con facilità.
# Вывод сведений обо всех образах
docker imagesQuesto comando restituirà una tabella con il seguente intestazione:
REPOSITORY TAG IMAGE ID CREATED SIZE
---Successivamente, esamineremo alcuni esempi di comandi in questo formato – prima c'è il comando con un commento, poi un esempio di ciò che può restituire.
▍Contenitori
Il contenitore è un pacchetto eseguibile che contiene tutto il necessario per l'esecuzione dell'applicazione. Con questo approccio, l'applicazione funzionerà sempre allo stesso modo, indipendentemente dall'infrastruttura: in un ambiente isolato e nella stessa configurazione. Si tratta del fatto che in ambienti diversi vengono avviati esemplari della stessa immagine.
# Перечисление всех контейнеров
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
---▍Tag
Il tag è un'indicazione di una versione specifica dell'immagine.
▍Breve guida ai comandi Docker
Ecco una panoramica di alcuni comandi Docker comunemente usati.
Team
Contesto
Azione
Immagine
Costruzione dell'immagine da Dockerfile
Immagine
Tagging dell'immagine
Immagine
Visualizzazione dell'elenco delle immagini
Contenitore
Avvio del contenitore basato su un'immagine
Immagine
Invio dell'immagine al registro
Immagine
Download dell'immagine dal registro
Contenitore
Visualizzazione dell'elenco dei contenitori
Immagine/Contenitore
Rimozione di contenitori e immagini non utilizzati
▍File Dockerfile
So come avviare localmente un'applicazione per la produzione. Ho una configurazione di Webpack destinata a costruire un'applicazione React pronta. Quindi, ho un comando che avvia un server basato su Node.js sulla porta 5000. Risulta così:
npm i # installazione delle dipendenze
npm run build # costruzione dell'applicazione React
npm run start # avvio del server NodeÈ importante notare che non ho un'applicazione di esempio per questo materiale. Ma qui, qualsiasi semplice applicazione Node andrà bene per esperimenti.
Per utilizzare il contenitore, sarà necessario dare istruzioni a Docker. Questo avviene tramite un file chiamato Dockerfile, che si trova nella directory principale del progetto. Questo file, inizialmente, sembra piuttosto incomprensibile.
Ma ciò che contiene è solo una descrizione, tramite comandi speciali, di qualcosa di simile alla configurazione di un ambiente di lavoro. Ecco alcuni di questi comandi:
- — Questo comando avvia il file. Indica l'immagine di base su cui si costruisce il contenitore.
- — Copia dei file da una fonte locale nel contenitore.
- — Impostazione della directory di lavoro per i comandi successivi.
- — Esecuzione dei comandi.
- — Configurazione della porta.
- — Indicazione del comando da eseguire.
Dockerfile può apparire più o meno così:
# Загрузить базовый образ
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 startA seconda dell'immagine di base scelta, potresti dover installare dipendenze aggiuntive. Il fatto è che alcune immagini di base (come Node Alpine Linux) sono create per essere il più compatte possibile. Di conseguenza, potrebbero mancare alcuni programmi di cui ti aspetti.
▍Costruzione, etichettatura e avvio del container
La costruzione e l'avvio locali del container sono, dopo che abbiamo, Dockerfilele attività abbastanza semplici. Prima di inviare l'immagine su Docker Hub, deve essere testata localmente.
▍Costruzione
Prima di tutto, devi costruire , specificando un nome e, se necessario, un'etichetta (se non viene specificata un'etichetta, il sistema ne assegnerà automaticamente una all'immagine. latest).
# Сборка образа
docker build -t <image>:<tag> .Dopo aver eseguito questo comando, puoi osservare come Docker esegue la costruzione dell'immagine.
Invio del contesto di build al demone Docker 2.88MB
Step 1/9 : FROM node:12-alpine
---> ...esecuzione delle fasi di costruzione...
Costruito con successo 123456789123
Etichettato con successo <image>:<tag> La costruzione può richiedere alcuni minuti — tutto dipende da quante dipendenze hai. Dopo che la costruzione è completata, puoi eseguire il comando docker images e dare un'occhiata alla descrizione della tua nuova immagine.
REPOSITORY TAG IMAGE ID CREATED SIZE
<image> latest 123456789123 Circa un minuto fa x.xxGB▍Avvio
L'immagine è stata creata. Questo significa che puoi avviare un container a partire da essa. Poiché voglio avere la possibilità di accedere all'applicazione che sta funzionando nel container all'indirizzo localhost:5000, ho impostato nella parte sinistra della coppia 5000:5000 nella seguente riga di comando. 5000A destra si trova la porta del container.
# Запуск с использованием локального порта 5000 и порта контейнера 5000
docker run -p 5000:5000 <image>:<tag> Ora, quando il container è stato creato e avviato, puoi usare il comando docker ps per visualizzare le informazioni su questo container (oppure puoi utilizzare il comando docker ps -a, che mostra le informazioni su tutti i container, non solo su quelli in esecuzione).
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 Se vai ora all'indirizzo localhost:5000 puoi vedere la pagina dell'applicazione in esecuzione, che appare esattamente come la pagina dell'applicazione in esecuzione in ambiente di produzione.
▍Assegnazione dell'etichetta e pubblicazione
Per utilizzare uno dei modelli creati sul server di produzione, è necessario avere la possibilità di caricare questo modello da Docker Hub. Questo significa che prima bisogna creare un repository su Docker Hub per il progetto. Dopo di che avremo a disposizione uno spazio dove poter inviare il modello. È necessario rinominare il modello in modo che il suo nome inizi con il nostro nome utente su Docker Hub. Dopo di ciò, deve seguire il nome del repository. Alla fine del nome può esserci qualsiasi tag. Di seguito è mostrato un esempio di denominazione dei modelli secondo questo schema.
Ora possiamo costruire il modello assegnandogli un nuovo nome ed eseguire il comando docker push per inviarlo al repository di Docker Hub.
docker build -t \/: .
docker tag \/: \/:latest
docker push \/:
# In pratica, può apparire ad esempio così:
docker build -t user\/app:v1.0.0 .
docker tag user\/app:v1.0.0 user\/app:latest
docker push user\/app:v1.0.0Se tutto va come previsto, il modello sarà disponibile su Docker Hub e sarà facile caricarlo sul server o trasferirlo ad altri sviluppatori.
Passaggi successivi
Fino a questo momento siamo certi che l'applicazione, sotto forma di contenitore Docker, funziona localmente. Abbiamo caricato il contenitore su Docker Hub. Tutto ciò significa che abbiamo già fatto dei buoni progressi verso l'obiettivo. Ora è necessario risolvere altri due problemi:
- Configurazione dello strumento CI per il testing e il deployment del codice.
- Configurazione del server di produzione in modo che possa caricare e avviare il nostro codice.
Nel nostro caso, come soluzione CI/CD viene utilizzato . Come server — .
Va notato che qui è possibile utilizzare anche un'altra combinazione di servizi. Ad esempio, invece di Travis CI, si può utilizzare CircleCI o Github Actions. E invece di DigitalOcean — AWS o Linode.
Abbiamo deciso di lavorare con Travis CI, e in questo servizio ho già configurato alcune cose. Quindi ora descriverò brevemente come prepararlo per il lavoro.
Travis CI
Travis CI è uno strumento per il testing e il deployment del codice. Non vorrei entrare nei dettagli della configurazione di Travis CI, poiché ogni progetto è unico e non sarebbe particolarmente utile. Tuttavia, parlerò delle basi che ti permetteranno di iniziare a lavorare nel caso tu decida di utilizzare Travis CI. Qualunque cosa tu scelga — Travis CI, CircleCI, Jenkins, o altro, verranno utilizzati metodi di configurazione simili.
Per iniziare a lavorare con Travis CI, vai su e crea un account. Poi integra Travis CI con il tuo account GitHub. Durante la configurazione del sistema, ti verrà chiesto di specificare il repository con cui desideri automatizzare il lavoro e di concedere l'accesso. (Io utilizzo GitHub, ma sono sicura che Travis CI possa integrarsi anche con BitBucket, GitLab e altri servizi simili).
Ogni volta che Travis CI inizia a lavorare, viene avviato un server che esegue i comandi specificati nel file di configurazione, incluso il deploy delle appropriate branch del repository.
▍Ciclo di vita del compito
Il file di configurazione di Travis CI, chiamato .travis.yml e situato nella directory principale del progetto, supporta il concetto di eventi del compito. Ecco questi eventi, elencati nell'ordine in cui si verificano:
apt addonscache componentsbefore_installinstallbefore_scriptscriptbefore_cacheafter_success o after_failurebefore_deploydeployafter_deployafter_script
▍Testing
Nel file di configurazione intendo impostare un server locale per Travis CI. Come linguaggio ho scelto Node versione 12 e ho indicato al sistema di installare le dipendenze necessarie per utilizzare Docker.
Tutto ciò che è elencato in .travis.yml, sarà eseguito per tutti i pull request su tutte le branch del repository, a meno che non sia specificato diversamente. Questa è una funzionalità utile, poiché significa che possiamo testare tutto il codice che arriva nel repository. Questo permette di sapere se il codice è pronto per essere registrato nella branch master, e se non interromperà il processo di build del progetto. In questa configurazione globale, installo tutto localmente, avvio il server di sviluppo Webpack in background (questo è un aspetto del mio flusso di lavoro) ed eseguo i test.
Se desideri che nel tuo repository vengano visualizzati i badge con le informazioni sulla copertura del codice dai test, puoi trovare una breve guida su come utilizzare Jest, Travis CI e Coveralls per raccogliere e visualizzare queste informazioni.
Quindi, ecco il contenuto del file .travis.yml:
# Установить язык
language: node_js
# Установить версию Node.js
node_js:
- '12'
services:
# Использовать командную строку Docker
- docker
install:
# Установить зависимости для тестов
- npm ci
before_script:
# Запустить сервер и клиент для тестов
- npm run dev &
script:
# Запустить тесты
- npm run testQui terminano le azioni eseguite per tutte le branch del repository e per i pull request.
▍Deploy
Basandoci sull'ipotesi che tutti i test automatizzati siano stati completati con successo, possiamo, se lo desideriamo, effettuare il deploy del codice sul server di produzione. Poiché vogliamo farlo solo per il codice proveniente dalla branch master, diamo al sistema le indicazioni appropriate nelle impostazioni di distribuzione. Prima di tentare di utilizzare nel tuo progetto il codice che esamineremo in seguito, vorrei avvisarti che devi avere uno script reale chiamato per la distribuzione.
deploy:
# Costruire il container Docker e inviarlo su Docker Hub
provider: script
script: bash deploy.sh
on:
branch: masterLo script di distribuzione ha due compiti:
- Costruzione, tagging e invio dell'immagine su Docker Hub tramite uno strumento CI (nel nostro caso Travis CI).
- Caricamento dell'immagine sul server, fermando il vecchio container e avviando il nuovo (nel nostro caso il server funziona sulla piattaforma DigitalOcean).
Per prima cosa, è necessario impostare il processo automatico di costruzione, tagging e invio dell'immagine su Docker Hub. Tutto questo è molto simile a ciò che abbiamo già fatto manualmente, a parte il fatto che qui abbiamo bisogno di una strategia per assegnare tag unici alle immagini e automatizzare l'accesso. Ho avuto difficoltà con alcuni dettagli dello script di distribuzione, come la strategia di tagging, l'accesso, la codifica delle chiavi SSH e l'instaurazione della connessione SSH. Ma, fortunatamente, il mio ragazzo si destreggia molto bene con bash, così come con molte altre cose. Mi ha aiutato a scrivere questo script.
Quindi, la prima parte dello script è l'invio dell'immagine su Docker Hub. Farlo è abbastanza semplice. Lo schema di tagging che ho utilizzato prevede la combinazione di un hash git e un tag git, se esiste. Questo consente di garantire la creazione di un tag unico e semplifica l'identificazione della build da cui è basato. DOCKER_USERNAME e DOCKER_PASSWORD sono variabili ambientali che possono essere impostate tramite l'interfaccia di Travis CI. Travis CI gestirà automaticamente i dati sensibili in modo che non finiscano nelle mani sbagliate.
Ecco la prima parte dello script 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} La seconda parte dello script dipende completamente dall'host che stai utilizzando e da come è organizzata la connessione. Nel mio caso, poiché utilizzo Digital Ocean, per collegarmi al server vengono utilizzati i comandi . Quando lavoro con AWS, verrà utilizzato lo strumento aws, e così via.
Configurare il lavoro del server non è stato particolarmente complicato. Ho configurato un droplet basato su un'immagine di base. Va notato che il sistema da me scelto richiede l'installazione manuale una tantum di Docker e l'avvio manuale di Docker una sola volta. Io, per installare Docker, ho usato Ubuntu 18.04, quindi anche voi, se utilizzate Ubuntu, per fare lo stesso, potete semplicemente seguire una guida semplice.
Non parlo qui di comandi specifici per il servizio, poiché questo aspetto può variare notevolmente in diversi casi. Fornirò solo un piano generale di azione che si esegue dopo aver effettuato la connessione SSH al server dove sarà distribuito il progetto:
- Dovete trovare il contenitore che attualmente è in esecuzione e fermarlo.
- Poi dovete avviare un nuovo contenitore in background.
- Dovrete impostare la porta locale del server sul valore
80— questo permetterà di accedere al sito all'indirizzo del tipoexample.com, senza specificare la porta, invece di utilizzare un indirizzo comeexample.com:5000. - E, infine, dovete eliminare tutti i vecchi contenitori e le immagini.
Ecco la continuazione dello script.
# Найти 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 -fAlcune cose a cui prestare attenzione
Probabilmente, quando vi connettete al server tramite SSH da Travis CI, vedrete un avviso che impedirà di continuare l'installazione, poiché il sistema attenderà una reazione da parte dell'utente.
L'autenticità dell'host ' ()' non può essere stabilita.
L'impronta della chiave RSA è .
Siete sicuri di voler continuare a connettervi (sì/no)? Ho scoperto che è possibile codificare la chiave di stringa in base64 per conservarla in un formato con cui è possibile lavorare comodamente e in modo sicuro. Durante la fase di installazione, è possibile decodificare la chiave pubblica e scriverla nel file known_hosts per eliminarne l'errore descritto in precedenza.
echo | base64 # restituisceNella pratica, questo comando potrebbe apparire così:
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" | base64Ecco come appare ciò che restituisce: una stringa in codifica base64:
MTIzLjQ1LjY3Ljg5IHNzaC1yc2EgQUFBQUIzTnphQzF5YzJFQUFBQUJJd0FBQVFFQWtsT1Vwa0RIcmZIWTE3U2JybVRJcE5MVEdLOVRqb20vQldEU1UKR1BsK25hZnpsSERUWVc3aGRJNHlaNWV3MThKSDRKVzlqYmhVRnJ2aVF6TTd4bEVMRVZmNGg5bEZYNVFWa2JQcHBTd2cwY2RhMwpQYnY3a09kSi9NVHlCbFdYRkNSK0hBbzNGWFJpdEJxeGlYMW5LaFhwSEFac01jaUxxOFY2UmpzTkFRd2RzZE1GdlNsVksvN1hBCnQzRmFvSm9Bc25jTTFROXg1KzNWMFd3NjgvZUlGbWIxenVVRmxqUUpLcHJyWDg4WHlwTkR2allOYnk2dncvUGIwcndlcnQvRW4KbVorQVc0T1pQblRQSTg5WlBtVk1MdWF5ckQyY0U4NlovaWw4YitndzNyMysxbkthdG1Ja2puMnNvMWQwMVFyYVRsTXFWU3NieApOclJGaTl3cmYrTTdRPT0geW91QGV4YW1wbGUuY29tCg==Ecco il comando di cui si parlava sopra
install:
- echo | base64 -d >> $HOME/.ssh/known_hostsLo stesso approccio può essere utilizzato con la chiave privata durante l'instaurazione della connessione, poiché per accedere al server potrebbe essere necessaria una chiave privata. Quando si utilizza la chiave, è sufficiente assicurarsi che venga memorizzata in modo sicuro nella variabile d'ambiente Travis CI e che non venga stampata da nessuna parte.
Un'altra cosa da tenere a mente è che potrebbe essere necessario eseguire l'intero script di distribuzione presentato come una sola riga, ad esempio - tramite doctl. Questo potrebbe richiedere alcuni sforzi aggiuntivi.
doctl compute ssh --ssh-command "tutti i comandi saranno qui && qui"TLS/SSL e bilanciamento del carico
Dopo aver fatto tutto ciò di cui si è parlato sopra, l'ultimo problema che mi sono trovata ad affrontare è stato che il server non aveva SSL. Poiché utilizzo un server Node.js, per costringere un reverse proxy Nginx e Let's Encrypt, è necessario lavorarci un po'.
Non volevamo affatto eseguire manualmente tutte queste configurazioni SSL, quindi ho semplicemente creato un bilanciatore di carico e registrato le informazioni in DNS. Nel caso di DigitalOcean, ad esempio, la creazione di un certificato autofirmato autoaggiornante sul bilanciatore di carico è una procedura semplice, gratuita e veloce. Questo approccio ha anche un ulteriore vantaggio, poiché consente di configurare SSL molto facilmente su diversi server che lavorano dietro il bilanciatore di carico. Ciò consente ai server stessi di non 80dover preoccuparsi
di SSL, ma di utilizzare, come al solito, la porta 80, utilizzata per comunicare con il bilanciatore di carico, e la porta 22 per SSH. Di conseguenza, il tentativo di accesso diretto al server su qualsiasi porta, ad eccezione di queste due, fallirà.
Conclusioni
Dopo aver fatto tutto ciò di cui ho parlato in questo articolo, non avevo più paura né della piattaforma Docker né dei concetti delle catene CI/CD automatizzate. Sono riuscita a configurare una catena di integrazione continua, durante la quale viene effettuato il testing del codice prima che arrivi in produzione e il rilascio automatico del codice sul server. Tutto questo è ancora relativamente nuovo per me, e sono sicura che ci siano modi per migliorare il mio flusso di lavoro automatizzato e renderlo più efficiente. Quindi, se avete idee al riguardo - fatemelo sapere. Spero che questo articolo vi sia stato utile. Spero che leggendo, abbiate appreso tanto quanto ho appreso io mentre facevo chiarezza su tutto ciò di cui ho parlato.
P.S. Nel nostro si ha un'immagine , che si installa con un clic. Puoi verificare il funzionamento dei container su . A tutti i nuovi clienti vengono forniti gratuitamente 3 giorni per la sperimentazione.
Gentili lettori! Utilizzate tecnologie CI/CD nei vostri progetti?
Fonte: habr.com
