Creazione di una catena CI/CD e automazione del lavoro con Docker

Ho scritto i miei primi siti web alla fine degli anni '90. Allora era molto semplice metterli in funzione. C'era un server Apache su alcuni hosting condivisi, potevi accedere a questo server tramite FTP scrivendo qualcosa del tipo ftp://ftp.example.com. Quindi dovevi inserire il tuo nome e password e caricare i file sul server. C'erano tempi diversi, tutto era più semplice allora di adesso.

Creazione di una catena CI/CD e automazione del lavoro con Docker

Nei due decenni successivi, tutto è cambiato molto. I siti web sono diventati più complessi; devono essere assemblati prima di essere messi in produzione. Un singolo server divenne molti server in esecuzione dietro sistemi di bilanciamento del carico e l'uso di sistemi di controllo della versione divenne un luogo comune.

Per il mio progetto personale avevo una configurazione speciale. E sapevo che avevo bisogno della possibilità di distribuire il sito in produzione eseguendo una sola azione: scrivere codice su un ramo master su GitHub. Inoltre, sapevo che per garantire il funzionamento della mia piccola applicazione web non volevo gestire un enorme cluster Kubernetes, né utilizzare la tecnologia Docker Swarm, né mantenere una flotta di server con pod, agenti e ogni sorta di altro complessità. Per raggiungere l'obiettivo di semplificare il più possibile il lavoro, avevo bisogno di familiarizzare con CI/CD.

Se hai un piccolo progetto (in questo caso, un progetto Node.js) e vorresti sapere come automatizzare la distribuzione di questo progetto, assicurandoti allo stesso tempo che ciò che è archiviato nel repository corrisponda esattamente a ciò che funziona in produzione, allora io penso che potrebbe interessarti questo articolo.

Prerequisiti

Si prevede che il lettore di questo articolo abbia una conoscenza di base della riga di comando e della scrittura di script Bash. Inoltre, avrà bisogno di conti Travis CI и Hub Docker.

Obiettivi

Non dirò che questo articolo possa essere definito incondizionatamente un “tutorial”. Questo è più un documento in cui parlo di ciò che ho imparato e descrivo il processo più adatto a me per testare e distribuire il codice in produzione, eseguito in un unico passaggio automatizzato.

Questo è quello che è diventato il mio flusso di lavoro.

Per il codice pubblicato in qualsiasi ramo del repository tranne master, vengono eseguite le seguenti azioni:

  • Parte il progetto basato su Travis CI.
  • Vengono eseguiti tutti i test unitari, di integrazione ed end-to-end.

Solo per il codice che rientra in master, si esegue quanto segue:

  • Tutto quanto sopra menzionato, più...
  • Creazione di un'immagine Docker in base al codice, alle impostazioni e all'ambiente correnti.
  • Distribuzione dell'immagine su Docker Hub.
  • Connessione al server di produzione.
  • Caricamento di un'immagine da Docker Hub al server.
  • Arresto del contenitore corrente e avvio di uno nuovo in base alla nuova immagine.

Se non sai assolutamente nulla di Docker, immagini e contenitori, non preoccuparti. Ti dirò tutto.

Cos'è CI/CD?

L'abbreviazione CI/CD sta per "integrazione continua/distribuzione continua".

▍Integrazione continua

L'integrazione continua è un processo in cui gli sviluppatori si impegnano al repository del codice sorgente principale del progetto (solitamente un branch master). Allo stesso tempo, la qualità del codice è garantita attraverso test automatizzati.

▍Distribuzione continua

La distribuzione continua è la distribuzione frequente e automatizzata del codice nella produzione. La seconda parte dell’acronimo CI/CD è talvolta definita “consegna continua”. Fondamentalmente è uguale alla "distribuzione continua", ma la "consegna continua" implica la necessità di confermare manualmente le modifiche prima di avviare il processo di distribuzione del progetto.

Guida introduttiva

L'app con cui ho imparato tutto questo si chiama Prendi nota. Questo è un progetto web a cui sto lavorando, pensato per prendere appunti. All'inizio ho provato a fare JAMStack-project, o semplicemente un'applicazione front-end senza server, per sfruttare le funzionalità standard di hosting e distribuzione dei progetti che offre Netlify. Man mano che la complessità dell'applicazione cresceva, avevo bisogno di creare la sua parte server, il che significava che avrei dovuto formulare la mia strategia per l'integrazione automatizzata e la distribuzione automatizzata del progetto.

Nel mio caso, l'applicazione è un server Express in esecuzione nell'ambiente Node.js, che serve un'applicazione React a pagina singola e supporta un'API lato server sicura. Questa architettura segue la strategia che può essere trovata in questo Guida all'autenticazione dello stack completo.

Mi sono consultato con другом, che è un esperto di automazione, e gli ha chiesto cosa dovevo fare per far funzionare tutto come volevo. È stato lui a darmi l’idea di come dovrebbe essere un flusso di lavoro automatizzato, delineato nella sezione Obiettivi di questo articolo. Avere questi obiettivi significava che dovevo capire come utilizzare Docker.

docker

Docker è uno strumento che, grazie alla tecnologia di containerizzazione, consente di distribuire, implementare ed eseguire facilmente le applicazioni nello stesso ambiente, anche se la piattaforma Docker stessa funziona in ambienti diversi. Innanzitutto, dovevo mettere le mani sugli strumenti da riga di comando (CLI) di Docker. Istruzioni La guida all'installazione di Docker non può essere definita molto chiara e comprensibile, ma da essa puoi apprendere che per poter eseguire il primo passaggio di installazione è necessario scaricare Docker Desktop (per Mac o Windows).

Docker Hub è più o meno la stessa cosa di GitHub per i repository Git o il registro npm per i pacchetti JavaScript. Questo è un repository online per le immagini Docker. Questo è ciò a cui si connette Docker Desktop.

Quindi, per iniziare con Docker, devi fare due cose:

Successivamente, puoi verificare se la CLI Docker funziona eseguendo il comando seguente per verificare la versione di Docker:

docker -v

Successivamente, accedi a Docker Hub inserendo nome utente e password quando richiesto:

docker login

Per utilizzare Docker è necessario comprendere i concetti di immagini e contenitori.

▍Immagini

Un'immagine è qualcosa come un progetto che contiene le istruzioni per assemblare il contenitore. Questa è un'istantanea immutabile del file system e delle impostazioni dell'applicazione. Gli sviluppatori possono condividere facilmente le immagini.

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

Questo comando genererà una tabella con la seguente intestazione:

REPOSITORY     TAG     IMAGE ID     CREATED     SIZE
---

Successivamente esamineremo alcuni esempi di comandi nello stesso formato: prima c'è un comando con un commento e poi un esempio di ciò che può restituire.

▍Contenitori

Un contenitore è un pacchetto eseguibile che contiene tutto il necessario per eseguire un'applicazione. Un'applicazione con questo approccio funzionerà sempre allo stesso modo, indipendentemente dall'infrastruttura: in un ambiente isolato e nello stesso ambiente. Il punto è che istanze della stessa immagine vengono lanciate in ambienti diversi.

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

▍Tag

Un tag è un'indicazione di una versione specifica di un'immagine.

▍Un rapido riferimento ai comandi Docker

Ecco una panoramica di alcuni comandi Docker comunemente utilizzati.

Squadra

Contesto

Azione

build docker

Образ

Creazione di un'immagine da un Dockerfile

etichetta mobile

Образ

Etichettatura delle immagini

immagini docker

Образ

Elenco immagini

run docker

contenitore

Esecuzione di un contenitore basato su un'immagine

spinta mobile

Образ

Caricamento di un'immagine nel registro

tiro del docker

Образ

Caricamento di un'immagine dal registro

docker ps

contenitore

Elenco contenitori

prugna del sistema docker

Immagine/Contenitore

Rimozione di contenitori e immagini inutilizzati

▍Dockerfile

So come eseguire un'applicazione di produzione localmente. Ho una configurazione Webpack progettata per creare un'applicazione React già pronta. Successivamente, ho un comando che avvia un server basato su Node.js sulla porta 5000. Sembra questo:

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

Va notato che non ho un'applicazione di esempio per questo materiale. Ma qui, per gli esperimenti, andrà bene qualsiasi semplice applicazione Node.

Per poter utilizzare il contenitore, dovrai dare istruzioni a Docker. Questo viene fatto attraverso un file chiamato Dockerfile, situato nella directory principale del progetto. Questo file, a prima vista, sembra abbastanza incomprensibile.

Ma ciò che contiene descrive solo, con appositi comandi, qualcosa di simile all'impostazione di un ambiente di lavoro. Ecco alcuni di questi comandi:

  • DA — Questo comando avvia un file. Specifica l'immagine di base su cui è costruito il contenitore.
  • COPIA — Copia di file da un'origine locale a un contenitore.
  • DIR.LAVORO — Impostazione della directory di lavoro per i seguenti comandi.
  • CORRERE - Esegui comandi.
  • ESPORRE — Impostazioni della porta.
  • PUNTO D'ENTRATA — Indicazione del comando da eseguire.

Dockerfile potrebbe assomigliare a questo:

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

A seconda dell'immagine di base scelta, potrebbe essere necessario installare dipendenze aggiuntive. Il fatto è che alcune immagini di base (come Node Alpine Linux) vengono create con l'obiettivo di renderle il più compatte possibile. Di conseguenza, potrebbero non avere alcuni dei programmi che ti aspetti.

▍Costruire, taggare ed eseguire il contenitore

L'assemblaggio locale e il lancio del container avverranno dopo Dockerfile, i compiti sono abbastanza semplici. Prima di inviare l'immagine a Docker Hub, è necessario testarla localmente.

▍Assemblea

Per prima cosa devi raccogliere immagine, specificando un nome e, facoltativamente, un tag (se non viene specificato un tag, il sistema assegnerà automaticamente un tag all'immagine latest).

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

Dopo aver eseguito questo comando, puoi guardare Docker creare l'immagine.

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

La compilazione potrebbe richiedere un paio di minuti: tutto dipende da quante dipendenze hai. Una volta completata la compilazione, puoi eseguire il comando docker images e guarda la descrizione della tua nuova immagine.

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

▍Avvia

L'immagine è stata creata. Ciò significa che puoi eseguire un contenitore basato su di esso. Perché voglio poter accedere all'applicazione in esecuzione nel contenitore su localhost:5000, io, sul lato sinistro della coppia 5000:5000 nel comando successivo installato 5000. Sul lato destro c'è il porto dei container.

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

Ora che il contenitore è stato creato ed è in esecuzione, puoi utilizzare il comando docker ps per visualizzare le informazioni su questo contenitore (oppure puoi utilizzare il comando docker ps -a, che visualizza informazioni su tutti i contenitori, 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 ora vai all'indirizzo localhost:5000 — puoi vedere una pagina di un'applicazione in esecuzione che assomiglia esattamente alla pagina di un'applicazione in esecuzione in un ambiente di produzione.

▍Tagging e pubblicazione

Per poter utilizzare una delle immagini create sul server di produzione, dobbiamo essere in grado di scaricare questa immagine da Docker Hub. Ciò significa che devi prima creare un repository per il progetto su Docker Hub. Successivamente, avremo un posto dove possiamo inviare l'immagine. L'immagine deve essere rinominata in modo che il suo nome inizi con il nostro nome utente Docker Hub. Questo dovrebbe essere seguito dal nome del repository. Qualsiasi tag può essere posizionato alla fine del nome. Di seguito è riportato un esempio di denominazione delle immagini utilizzando questo schema.

Ora puoi creare l'immagine con un nuovo nome ed eseguire il comando docker push per inviarlo al repository 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

Se tutto andrà bene, l'immagine sarà disponibile su Docker Hub e potrà essere facilmente caricata sul server o trasferita ad altri sviluppatori.

Prossimi passi

A questo punto abbiamo verificato che l'applicazione, sotto forma di contenitore Docker, è in esecuzione localmente. Abbiamo caricato il contenitore su Docker Hub. Tutto ciò significa che abbiamo già fatto ottimi progressi verso il nostro obiettivo. Ora dobbiamo risolvere altre due domande:

  • Configurazione di uno strumento CI per testare e distribuire il codice.
  • Configurazione del server di produzione in modo che possa scaricare ed eseguire il nostro codice.

Nel nostro caso, usiamo Travis CI. Come servitore - DigitalOcean.

Va notato che qui puoi utilizzare un'altra combinazione di servizi. Ad esempio, invece di Travis CI, puoi utilizzare CircleCI o Github Actions. E invece di DigitalOcean: AWS o Linode.

Abbiamo deciso di lavorare con Travis CI e ho già configurato qualcosa in questo servizio. Pertanto, ora parlerò brevemente di come prepararlo per il lavoro.

Travis CI

Travis CI è uno strumento per testare e distribuire codice. Non vorrei entrare nella complessità della creazione di Travis CI, poiché ogni progetto è unico e questo non porterà molti benefici. Ma tratterò le nozioni di base per iniziare se decidi di utilizzare Travis CI. Sia che tu scelga Travis CI, CircleCI, Jenkins o qualcos'altro, metodi di configurazione simili verranno utilizzati ovunque.

Per iniziare con Travis CI, vai a sito del progetto e creare un account. Quindi integra Travis CI con il tuo account GitHub. Durante la configurazione del sistema, dovrai specificare il repository con cui desideri automatizzare il lavoro e abilitare l'accesso ad esso. (Uso GitHub, ma sono sicuro che Travis CI possa integrarsi con BitBucket, GitLab e altri servizi simili).

Ogni volta che viene avviato Travis CI, viene avviato il server, eseguendo i comandi specificati nel file di configurazione, inclusa la distribuzione dei rami del repository corrispondenti.

▍Ciclo di vita del lavoro

File di configurazione Travis CI chiamato .travis.yml e memorizzato nella directory root del progetto, supporta il concetto di eventi ciclo vitale compiti. Questi eventi sono elencati nell'ordine in cui si verificano:

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

▍Test

Nel file di configurazione configurerò il server Travis CI locale. Ho selezionato Node 12 come lingua e ho detto al sistema di installare le dipendenze necessarie per utilizzare Docker.

Tutto ciò che è elencato in .travis.yml, verrà eseguito quando tutte le richieste pull verranno effettuate a tutti i rami del repository, se non diversamente specificato. Questa è una funzionalità utile perché significa che possiamo testare tutto il codice che entra nel repository. Ciò ti consente di sapere se il codice è pronto per essere scritto nel ramo. mastere se ciò interromperà il processo di creazione del progetto. In questa configurazione globale, installo tutto localmente, eseguo il server di sviluppo Webpack in background (questa è una funzionalità del mio flusso di lavoro) ed eseguo i test.

Se desideri che il tuo repository visualizzi badge che indicano la copertura del test, qui Puoi trovare brevi istruzioni sull'utilizzo di 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 test

Qui terminano le azioni eseguite per tutti i rami del repository e per le richieste pull.

▍Distribuzione

Partendo dal presupposto che tutti i test automatizzati siano stati completati con successo, possiamo, il che è facoltativo, distribuire il codice sul server di produzione. Poiché vogliamo farlo solo per il codice del ramo master, forniamo al sistema istruzioni appropriate nelle impostazioni di distribuzione. Prima di provare a utilizzare il codice che vedremo in seguito nel tuo progetto, vorrei avvisarti che devi disporre di uno script effettivo chiamato per la distribuzione.

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

Lo script di distribuzione risolve due problemi:

  • Crea, tagga e invia l'immagine a Docker Hub utilizzando uno strumento CI (nel nostro caso, Travis CI).
  • Caricamento dell'immagine sul server, arresto del vecchio contenitore e avvio di uno nuovo (nel nostro caso, il server funziona sulla piattaforma DigitalOcean).

Innanzitutto, devi impostare un processo automatico per creare, taggare e inviare l'immagine a Docker Hub. Tutto questo è molto simile a quello che abbiamo già fatto manualmente, tranne per il fatto che abbiamo bisogno di una strategia per assegnare tag univoci alle immagini e automatizzare gli accessi. Ho avuto difficoltà con alcuni dettagli dello script di distribuzione, come la strategia di tagging, l'accesso, la codifica della chiave SSH, la creazione della connessione SSH. Ma per fortuna il mio ragazzo è molto bravo con la bash, come con tante altre cose. Mi ha aiutato a scrivere questa sceneggiatura.

Quindi, la prima parte dello script sta caricando l'immagine su Docker Hub. Questo è abbastanza facile da fare. Lo schema di tagging che ho utilizzato prevede la combinazione di un hash git e di un tag git, se ne esiste uno. Ciò garantisce che il tag sia univoco e facilita l'identificazione dell'assieme su cui si basa. DOCKER_USERNAME и DOCKER_PASSWORD sono variabili dell'ambiente utente che possono essere impostate utilizzando l'interfaccia Travis CI. Travis CI elaborerà automaticamente i dati sensibili in modo che non cadano nelle mani sbagliate.

Ecco la prima parte della sceneggiatura 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}

Quale sarà la seconda parte dello script dipende interamente dall'host che stai utilizzando e da come è organizzata la connessione ad esso. Nel mio caso, poiché utilizzo Digital Ocean, utilizzo i comandi per connettermi al server docl. Quando si lavora con AWS, verrà utilizzata l'utilità aws, eccetera.

La configurazione del server non è stata particolarmente difficile. Quindi, ho impostato un droplet basato sull'immagine di base. Va notato che il sistema che ho scelto richiede un'installazione manuale una tantum di Docker e un avvio manuale una tantum di Docker. Ho usato Ubuntu 18.04 per installare Docker, quindi se usi anche Ubuntu per fare lo stesso, puoi semplicemente seguire questo guida semplice.

Non sto parlando qui di comandi specifici per il servizio, poiché questo aspetto può variare molto nei diversi casi. Mi limiterò a fornire un piano d'azione generale da eseguire dopo la connessione tramite SSH al server su cui verrà distribuito il progetto:

  • Dobbiamo trovare il contenitore attualmente in esecuzione e fermarlo.
  • Quindi è necessario avviare un nuovo contenitore in background.
  • Dovrai impostare la porta locale del server su 80 - questo ti permetterà di entrare nel sito ad un indirizzo come example.com, senza specificare la porta, anziché utilizzare un indirizzo come example.com:5000.
  • Infine, devi eliminare tutti i vecchi contenitori e immagini.

Ecco la continuazione della sceneggiatura.

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

Alcune cose a cui prestare attenzione

È possibile che quando ti connetti al server tramite SSH da Travis CI, vedrai un avviso che ti impedirà di continuare con l'installazione poiché il sistema attenderà la risposta dell'utente.

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)?

Ho imparato che una chiave di stringa può essere codificata in base64 per salvarla in una forma in cui possa essere utilizzata in modo conveniente e affidabile. Nella fase di installazione è possibile decodificare la chiave pubblica e scriverla in un file known_hosts per eliminare l'errore di cui sopra.

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

In pratica, questo comando potrebbe assomigliare a questo:

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

Ed ecco cosa produce: una stringa codificata base64:

MTIzLjQ1LjY3Ljg5IHNzaC1yc2EgQUFBQUIzTnphQzF5YzJFQUFBQUJJd0FBQVFFQWtsT1Vwa0RIcmZIWTE3U2JybVRJcE5MVEdLOVRqb20vQldEU1UKR1BsK25hZnpsSERUWVc3aGRJNHlaNWV3MThKSDRKVzlqYmhVRnJ2aVF6TTd4bEVMRVZmNGg5bEZYNVFWa2JQcHBTd2cwY2RhMwpQYnY3a09kSi9NVHlCbFdYRkNSK0hBbzNGWFJpdEJxeGlYMW5LaFhwSEFac01jaUxxOFY2UmpzTkFRd2RzZE1GdlNsVksvN1hBCnQzRmFvSm9Bc25jTTFROXg1KzNWMFd3NjgvZUlGbWIxenVVRmxqUUpLcHJyWDg4WHlwTkR2allOYnk2dncvUGIwcndlcnQvRW4KbVorQVc0T1pQblRQSTg5WlBtVk1MdWF5ckQyY0U4NlovaWw4YitndzNyMysxbkthdG1Ja2puMnNvMWQwMVFyYVRsTXFWU3NieApOclJGaTl3cmYrTTdRPT0geW91QGV4YW1wbGUuY29tCg==

Ecco il comando menzionato sopra

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

Lo stesso approccio può essere utilizzato con una chiave privata quando si stabilisce una connessione, poiché potrebbe essere necessaria una chiave privata per accedere al server. Quando si lavora con la chiave, è sufficiente assicurarsi che sia archiviata in modo sicuro in una variabile di ambiente Travis CI e che non venga visualizzata da nessuna parte.

Un'altra cosa da notare è che potrebbe essere necessario eseguire l'intero script di distribuzione su una riga, ad esempio - with doctl. Ciò potrebbe richiedere uno sforzo aggiuntivo.

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

TLS/SSL e bilanciamento del carico

Dopo aver fatto tutto quanto sopra menzionato, l'ultimo problema che ho riscontrato è stato che il server non aveva SSL. Poiché utilizzo un server Node.js, per forzare lavoro proxy inverso Nginx e Let's Encrypt, devi armeggiare molto.

Non volevo davvero eseguire tutta questa configurazione SSL manualmente, quindi ho semplicemente creato un bilanciatore del carico e ne ho registrato i dettagli nel DNS. Nel caso di DigitalOcean, ad esempio, creare un certificato autofirmato con rinnovo automatico sul bilanciatore di carico è una procedura semplice, gratuita e veloce. Questo approccio ha il vantaggio aggiuntivo di rendere molto semplice la configurazione di SSL su più server in esecuzione dietro un bilanciatore del carico, se necessario. Ciò consente ai server stessi di non "pensare" affatto a SSL, ma allo stesso tempo di utilizzare la porta come al solito 80. Pertanto, configurare SSL su un bilanciatore del carico è molto più semplice e conveniente rispetto ai metodi alternativi di configurazione SSL.

Ora puoi chiudere tutte le porte sul server che accettano connessioni in entrata, tranne la porta 80, utilizzato per comunicare con il sistema di bilanciamento del carico e la porta 22 per SSH. Di conseguenza, il tentativo di accedere direttamente al server su qualsiasi porta diversa da queste due fallirà.

Risultati di

Dopo aver fatto tutto ciò di cui ho parlato in questo materiale, né la piattaforma Docker né i concetti di catene CI/CD automatizzate non mi spaventavano più. Sono stato in grado di impostare una catena di integrazione continua, durante la quale il codice viene testato prima di entrare in produzione e il codice viene automaticamente distribuito sul server. Tutto questo è ancora relativamente nuovo per me e sono sicuro che ci siano modi per migliorare il mio flusso di lavoro automatizzato e renderlo più efficiente. Quindi, se avete qualche idea su questo argomento, fatemelo sapere. me Sapere. Spero che questo articolo ti abbia aiutato nei tuoi sforzi. Voglio credere che dopo averlo letto, hai imparato tanto quanto ho imparato io mentre capivo tutto ciò di cui ho parlato in esso.

PS Nel nostro mercato c'è un'immagine docker, che può essere installato con un clic. Puoi controllare il funzionamento dei contenitori su VPS. A tutti i nuovi clienti vengono concessi 3 giorni di test gratuiti.

Cari lettori! Utilizzi tecnologie CI/CD nei tuoi progetti?

Creazione di una catena CI/CD e automazione del lavoro con Docker

Fonte: habr.com

Aggiungi un commento