Δημιουργία αλυσίδας CI / CD και αυτοματοποίηση της εργασίας με το Docker

Έγραψα τις πρώτες μου ιστοσελίδες στα τέλη της δεκαετίας του '90. Τότε ήταν πολύ εύκολο να τα φέρεις σε λειτουργική κατάσταση. Υπήρχε ένας διακομιστής Apache σε κάποια κοινόχρηστη φιλοξενία, αυτός ο διακομιστής μπορούσε να προσπελαστεί μέσω FTP γράφοντας στη γραμμή του προγράμματος περιήγησης κάτι σαν ftp://ftp.example.com. Στη συνέχεια, ήταν απαραίτητο να εισαγάγετε ένα όνομα και έναν κωδικό πρόσβασης και να ανεβάσετε τα αρχεία στον διακομιστή. Υπήρχαν και άλλες εποχές, όλα ήταν πιο απλά τότε από ότι είναι τώρα.

Δημιουργία αλυσίδας CI / CD και αυτοματοποίηση της εργασίας με το Docker

Τα πράγματα έχουν αλλάξει πολύ τις τελευταίες δύο δεκαετίες. Οι τοποθεσίες έχουν γίνει πιο περίπλοκες, πρέπει να συναρμολογηθούν πριν κυκλοφορήσουν στην παραγωγή. Ένας μεμονωμένος διακομιστής έχει γίνει πολλοί διακομιστές που λειτουργούν πίσω από συσκευές εξισορρόπησης φορτίου, η χρήση συστημάτων ελέγχου έκδοσης έχει γίνει συνηθισμένη.

Για το προσωπικό μου έργο, είχα μια ειδική διαμόρφωση. Και ήξερα ότι χρειαζόμουν τη δυνατότητα να αναπτύξω έναν ιστότοπο στην παραγωγή, εκτελώντας μόνο μία ενέργεια: γράφοντας κώδικα σε ένα υποκατάστημα master στο GitHub. Ήξερα επίσης ότι δεν ήθελα να διαχειριστώ ένα τεράστιο σύμπλεγμα Kubernetes ή να χρησιμοποιήσω την τεχνολογία Docker Swarm ή να διατηρήσω ένα πάρκο διακομιστών με pods, πράκτορες και κάθε είδους πολυπλοκότητα, για να τρέξω τη μικρή μου εφαρμογή Ιστού. Για να πετύχω τον στόχο να κάνω τη δουλειά όσο πιο εύκολη γίνεται, χρειάστηκε να εξοικειωθώ με το CI / CD.

Εάν έχετε ένα μικρό έργο (στην περίπτωσή μας, ένα έργο Node.js) και θέλετε να μάθετε πώς να αυτοματοποιείτε την ανάπτυξη αυτού του έργου, φροντίζοντας παράλληλα ότι αυτό που είναι αποθηκευμένο στο αποθετήριο ταιριάζει ακριβώς με αυτό που λειτουργεί στην παραγωγή, νομίζω μπορεί να σας ενδιαφέρει αυτό το άρθρο.

Προαπαιτούμενα

Ο αναγνώστης αυτού του άρθρου αναμένεται να έχει βασικές γνώσεις γραμμής εντολών και Bash scripting. Επιπλέον, θα χρειαστεί λογαριασμούς Travis CI и Docker hub.

Στόχοι

Δεν θα πω ότι αυτό το άρθρο μπορεί άνευ όρων να ονομαστεί "οδηγός εκπαίδευσης". Αυτό είναι περισσότερο ένα έγγραφο στο οποίο μιλάω για όσα έμαθα και περιγράφω τη διαδικασία που μου ταιριάζει για τη δοκιμή και την ανάπτυξη κώδικα στην παραγωγή, που εκτελείται σε ένα αυτοματοποιημένο πάσο.

Εδώ είναι πώς κατέληξε η ροή εργασίας μου.

Για κώδικα που προωθείται σε οποιοδήποτε κλάδο του αποθετηρίου εκτός από master, εκτελούνται οι ακόλουθες ενέργειες:

  • Ξεκινά η κατασκευή του έργου στο Travis CI.
  • Εκτελούνται όλες οι δοκιμές μονάδας, ολοκλήρωσης και από άκρο σε άκρο.

Μόνο για κώδικα που καταλήγει σε master, γίνονται τα εξής:

  • Όλα τα παραπάνω, συν...
  • Δημιουργία εικόνας Docker με βάση τον τρέχοντα κώδικα, τις ρυθμίσεις και το περιβάλλον.
  • Φιλοξενία της εικόνας στο Docker Hub.
  • Σύνδεση με τον διακομιστή παραγωγής.
  • Μεταφόρτωση μιας εικόνας από το Docker Hub στον διακομιστή.
  • Διακόψτε το τρέχον κοντέινερ και ξεκινήστε ένα νέο με βάση τη νέα εικόνα.

Εάν δεν γνωρίζετε απολύτως τίποτα για το Docker, τις εικόνες και τα κοντέινερ, μην ανησυχείτε. Θα σας τα πω όλα για αυτό.

Τι είναι το CI/CD;

Η συντομογραφία CI / CD σημαίνει "συνεχής ενσωμάτωση / συνεχής ανάπτυξη" - "συνεχής ενοποίηση / συνεχής ανάπτυξη".

▍Συνεχής Ένταξη

Η συνεχής ενσωμάτωση είναι η διαδικασία με την οποία οι προγραμματιστές αναλαμβάνουν δεσμεύσεις για την κύρια αποθήκη πηγαίου κώδικα ενός έργου (συνήθως ένα υποκατάστημα master). Ταυτόχρονα, η ποιότητα του κωδικού διασφαλίζεται μέσω αυτοματοποιημένων δοκιμών.

▍Συνεχής ανάπτυξη

Η συνεχής ανάπτυξη είναι η συχνή αυτοματοποιημένη ανάπτυξη κώδικα στην παραγωγή. Το δεύτερο μέρος της συντομογραφίας CI / CD αποκαλύπτεται μερικές φορές ως "συνεχής παράδοση" ("συνεχής παράδοση"). Αυτό είναι βασικά το ίδιο με τη "συνεχή ανάπτυξη", αλλά η "συνεχής παράδοση" σημαίνει ότι οι αλλαγές πρέπει να επιβεβαιωθούν με μη αυτόματο τρόπο πριν από την έναρξη της διαδικασίας ανάπτυξης του έργου.

Ξεκινώντας

Η εφαρμογή στην οποία κατέκτησα όλα αυτά λέγεται Να λάβει υπόψη. Αυτό είναι ένα web project στο οποίο εργάζομαι για τη λήψη σημειώσεων. Πρώτα προσπάθησα να κάνω JAMStack-έργο ή απλώς μια εφαρμογή front-end χωρίς διακομιστή, προκειμένου να επωφεληθείτε από τις τυπικές επιλογές φιλοξενίας και ανάπτυξης έργου που προσφέρει δικτυώνω. Καθώς η πολυπλοκότητα της εφαρμογής μεγάλωνε, χρειαζόταν να δημιουργήσω το back-end της, πράγμα που σήμαινε ότι θα έπρεπε να διαμορφώσω τη δική μου στρατηγική για την αυτοματοποιημένη ενοποίηση και την αυτοματοποιημένη ανάπτυξη του έργου.

Στην περίπτωσή μου, η εφαρμογή είναι ένας διακομιστής Express που εκτελείται σε περιβάλλον Node.js, εξυπηρετεί μια εφαρμογή React μιας σελίδας και υποστηρίζει ένα ασφαλές API από την πλευρά του διακομιστή. Αυτή η αρχιτεκτονική ακολουθεί μια στρατηγική που μπορεί να βρεθεί σε δεδομένος οδηγός ελέγχου ταυτότητας πλήρους στοίβας.

συμβουλεύτηκα με другом, που είναι ειδικός στον αυτοματισμό, και τον ρώτησα τι πρέπει να κάνω για να λειτουργήσουν όλα όπως θέλω. Μου έδωσε μια ιδέα για το πώς πρέπει να μοιάζει η αυτοματοποιημένη ροή εργασίας που περιγράφεται στην ενότητα Στόχοι αυτού του άρθρου. Ο καθορισμός στόχων σαν αυτόν σήμαινε ότι έπρεπε να καταλάβω πώς να χρησιμοποιήσω το Docker.

Λιμενεργάτης

Το Docker είναι ένα εργαλείο που, χάρη στην τεχνολογία κοντέινερ, διευκολύνει τη διανομή εφαρμογών, καθώς και την ανάπτυξη και εκτέλεση τους στο ίδιο περιβάλλον, ακόμα κι αν η ίδια η πλατφόρμα Docker εκτελείται σε διαφορετικά περιβάλλοντα. Πρώτα, χρειάστηκε να βάλω στα χέρια μου τα εργαλεία γραμμής εντολών Docker (CLI). εντολή Ο οδηγός εγκατάστασης για το Docker δεν είναι πολύ σαφής, αλλά μπορείτε να μάθετε από αυτόν ότι για να κάνετε το πρώτο βήμα της εγκατάστασης, πρέπει να κάνετε λήψη του Docker Desktop (για Mac ή Windows).

Το Docker Hub είναι περίπου το ίδιο με GitHub για αποθετήρια git ή μητρώο npm για πακέτα JavaScript. Αυτό είναι ένα διαδικτυακό αποθετήριο για εικόνες Docker. Εδώ συνδέεται το Docker Desktop.

Έτσι, για να ξεκινήσετε με το Docker, πρέπει να κάνετε δύο πράγματα:

Μετά από αυτό, μπορείτε να ελέγξετε εάν το Docker CLI λειτουργεί εκτελώντας την ακόλουθη εντολή για να ελέγξετε την έκδοση Docker:

docker -v

Στη συνέχεια, συνδεθείτε στο Docker Hub εισάγοντας το όνομα χρήστη και τον κωδικό πρόσβασής σας όταν σας ζητηθεί:

docker login

Για να χρησιμοποιήσετε το Docker, πρέπει να κατανοήσετε τις έννοιες των εικόνων και των κοντέινερ.

▍Εικόνες

Μια εικόνα είναι ένα είδος σχεδιαγράμματος που περιέχει οδηγίες για την κατασκευή ενός κοντέινερ. Αυτό είναι ένα αμετάβλητο στιγμιότυπο του συστήματος αρχείων και των ρυθμίσεων της εφαρμογής. Οι προγραμματιστές μπορούν εύκολα να μοιράζονται εικόνες.

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

Αυτή η εντολή θα παράγει έναν πίνακα με τον ακόλουθο τίτλο:

REPOSITORY     TAG     IMAGE ID     CREATED     SIZE
---

Στη συνέχεια, θα εξετάσουμε μερικά παραδείγματα εντολών στην ίδια μορφή - πρώτα υπάρχει μια εντολή με ένα σχόλιο και, στη συνέχεια, ένα παράδειγμα του τι μπορεί να παράγει.

▍Δοχεία

Ένα κοντέινερ είναι ένα εκτελέσιμο πακέτο που περιέχει όλα όσα χρειάζονται για την εκτέλεση μιας εφαρμογής. Μια εφαρμογή με αυτήν την προσέγγιση θα λειτουργεί πάντα το ίδιο, ανεξάρτητα από την υποδομή: σε ένα απομονωμένο περιβάλλον και στο ίδιο περιβάλλον. Μιλάμε για το γεγονός ότι οι περιπτώσεις της ίδιας εικόνας εκκινούνται σε διαφορετικά περιβάλλοντα.

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

▍Ετικέτες

Μια ετικέτα είναι μια ένδειξη μιας συγκεκριμένης έκδοσης μιας εικόνας.

▍Γρήγορη αναφορά για εντολές Docker

Ακολουθεί μια επισκόπηση ορισμένων εντολών Docker που χρησιμοποιούνται συνήθως.

Ομάδα

Πλαίσιο

επίδραση

κατασκευή λιμενεργατών

Εικόνα

Δημιουργία εικόνας από αρχείο Docker

ετικέτα docker

Εικόνα

Επισήμανση εικόνων

εικόνες docker

Εικόνα

Εμφάνιση λίστας εικόνων

τρέξιμο λιμανιού

Δοχείο

Εκτέλεση ενός κοντέινερ που βασίζεται σε εικόνα

ώθηση λιμενεργατών

Εικόνα

Αποστολή εικόνας στο Μητρώο

λιμνοδεξαμενής-τραβήγματος

Εικόνα

Φόρτωση εικόνας από το Μητρώο

docker ps

Δοχείο

Δοχεία καταχώρισης

κλάδεμα συστήματος docker

Εικόνα/Δοχείο

Αφαίρεση αχρησιμοποίητων κοντέινερ και εικόνων

▍Dockerfile

Ξέρω πώς να τρέχω μια εφαρμογή παραγωγής τοπικά. Έχω μια διαμόρφωση webpack για να δημιουργήσω μια ολοκληρωμένη εφαρμογή React. Στη συνέχεια, έχω μια εντολή που ξεκινά έναν διακομιστή που βασίζεται στο Node.js στη θύρα 5000. Μοιάζει με αυτό:

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

Σημειωτέον ότι δεν έχω παράδειγμα εφαρμογής για αυτό το υλικό. Αλλά εδώ, για πειράματα, κάθε απλή εφαρμογή Node θα κάνει.

Για να χρησιμοποιήσετε το δοχείο, θα χρειαστεί να δώσετε οδηγίες στο Docker. Αυτό γίνεται μέσω ενός αρχείου που ονομάζεται Dockerfileπου βρίσκεται στον ριζικό κατάλογο του έργου. Αυτό το αρχείο, αρχικά, φαίνεται μάλλον ακατανόητο.

Αλλά αυτό που περιέχει περιγράφει μόνο, σε ειδικές εντολές, κάτι σαν τη δημιουργία ενός περιβάλλοντος εργασίας. Εδώ είναι μερικές από αυτές τις εντολές:

  • ΑΠΟ — Αυτή η εντολή ξεκινά ένα αρχείο. Καθορίζει την εικόνα βάσης από την οποία είναι κατασκευασμένο το κοντέινερ.
  • COPY - Αντιγραφή αρχείων από τοπική πηγή σε κοντέινερ.
  • ΔΙΕΥΘΥΝΤΗΣ ΕΡΓΑΣΙΑΣ - Ρύθμιση του καταλόγου εργασίας για τις ακόλουθες εντολές.
  • ΤΡΈΞΙΜΟ - Εκτέλεση εντολών.
  • ΕΚΘΕΣΕΙ — Ρύθμιση θύρας.
  • ΣΗΜΕΙΟ ΕΙΣΟΔΟΥ — Ένδειξη της εντολής που πρέπει να εκτελεστεί.

Dockerfile μπορεί να μοιάζει κάπως έτσι:

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

Ανάλογα με τη βασική εικόνα που θα επιλέξετε, μπορεί να χρειαστεί να εγκαταστήσετε πρόσθετες εξαρτήσεις. Το γεγονός είναι ότι ορισμένες βασικές εικόνες (όπως το Node Alpine Linux) έχουν σχεδιαστεί για να είναι όσο το δυνατόν πιο συμπαγείς. Ως αποτέλεσμα, ενδέχεται να μην περιλαμβάνουν ορισμένα από τα προγράμματα που περιμένετε.

▍ Κατασκευή, προσθήκη ετικετών και λειτουργία κοντέινερ

Τοπική συναρμολόγηση και εκτόξευση του κοντέινερ είναι, αφού έχουμε Dockerfileοι εργασίες είναι αρκετά απλές. Πριν προωθήσετε μια εικόνα στο Docker Hub, πρέπει να δοκιμαστεί τοπικά.

▍Συναρμολόγηση

Πρώτα πρέπει να συλλέξετε εικόνα, καθορίζοντας ένα όνομα και, προαιρετικά, μια ετικέτα (εάν δεν έχει καθοριστεί ετικέτα, το σύστημα θα αντιστοιχίσει αυτόματα μια ετικέτα στην εικόνα latest).

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

Αφού εκτελέσετε αυτήν την εντολή, μπορείτε να παρακολουθήσετε τον Docker να δημιουργεί την εικόνα.

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

Η κατασκευή μπορεί να διαρκέσει μερικά λεπτά - όλα εξαρτώνται από το πόσες εξαρτήσεις έχετε. Αφού ολοκληρωθεί η κατασκευή, μπορείτε να εκτελέσετε την εντολή docker images και ρίξτε μια ματιά στην περιγραφή της νέας σας εικόνας.

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

▍Εκκίνηση

Η εικόνα έχει δημιουργηθεί. Και αυτό σημαίνει ότι στη βάση του μπορείτε να εκτελέσετε ένα δοχείο. Επειδή θέλω να έχω πρόσβαση στην εφαρμογή που εκτελείται στο κοντέινερ στο localhost:5000, i, στην αριστερή πλευρά του ζεύγους 5000:5000 στο ακόλουθο σύνολο εντολών 5000. Στη δεξιά πλευρά είναι η θύρα εμπορευματοκιβωτίων.

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

Τώρα που το κοντέινερ δημιουργείται και εκτελείται, μπορείτε να χρησιμοποιήσετε την εντολή docker ps για να δείτε πληροφορίες σχετικά με αυτό το κοντέινερ (ή μπορείτε να χρησιμοποιήσετε την εντολή docker ps -a, το οποίο εμφανίζει πληροφορίες για όλα τα κοντέινερ, όχι μόνο για τα τρέχοντα).

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

Αν τώρα πας στο localhost:5000 - μπορείτε να δείτε τη σελίδα της εφαρμογής που εκτελείται, η οποία μοιάζει ακριβώς με τη σελίδα της εφαρμογής που εκτελείται στο περιβάλλον παραγωγής.

▍Ανάθεση και δημοσίευση ετικετών

Για να χρησιμοποιήσουμε μία από τις δημιουργημένες εικόνες στον διακομιστή παραγωγής, πρέπει να μπορούμε να κάνουμε λήψη αυτής της εικόνας από το Docker Hub. Αυτό σημαίνει ότι πρέπει πρώτα να δημιουργήσετε ένα αποθετήριο για το έργο στο Docker Hub. Μετά από αυτό, θα έχουμε ένα μέρος όπου μπορούμε να στείλουμε την εικόνα. Η εικόνα πρέπει να μετονομαστεί έτσι ώστε το όνομά της να ξεκινά με το όνομα χρήστη Docker Hub. Αυτό θα πρέπει να ακολουθείται από το όνομα του αποθετηρίου. Οποιαδήποτε ετικέτα μπορεί να τοποθετηθεί στο τέλος του ονόματος. Παρακάτω είναι ένα παράδειγμα ονομασίας εικόνων σύμφωνα με αυτό το σχήμα.

Τώρα μπορείτε να δημιουργήσετε την εικόνα με ένα νέο όνομα που της έχει εκχωρηθεί και να εκτελέσετε την εντολή docker push για να το προωθήσετε στο αποθετήριο 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

Εάν όλα πάνε καλά, η εικόνα θα είναι διαθέσιμη στο Docker Hub και μπορεί εύκολα να μεταφορτωθεί στον διακομιστή ή να μοιραστεί με άλλους προγραμματιστές.

Επόμενα βήματα

Μέχρι τώρα, έχουμε επαληθεύσει ότι η εφαρμογή, με τη μορφή κοντέινερ Docker, εκτελείται τοπικά. Ανεβάσαμε το κοντέινερ στο Docker Hub. Όλα αυτά σημαίνουν ότι έχουμε ήδη κάνει πολύ καλή πρόοδο προς τον στόχο μας. Τώρα πρέπει να λύσουμε δύο ακόμη ερωτήματα:

  • Ρύθμιση ενός εργαλείου CI για δοκιμή και ανάπτυξη κώδικα.
  • Ρύθμιση του διακομιστή παραγωγής ώστε να μπορεί να κατεβάσει και να εκτελέσει τον κώδικά μας.

Στην περίπτωσή μας, ως λύση CI / CD, χρησιμοποιούμε Travis CI. Ως διακομιστής - DigitalOcean.

Θα πρέπει να σημειωθεί ότι εδώ μπορείτε να χρησιμοποιήσετε έναν άλλο συνδυασμό υπηρεσιών. Για παράδειγμα, αντί για το Travis CI, μπορείτε να χρησιμοποιήσετε το CircleCI ή το Github Actions. Και αντί για DigitalOcean - AWS ή Linode.

Αποφασίσαμε να συνεργαστούμε με τον Travis CI και έχω ήδη ρυθμίσει κάτι σε αυτήν την υπηρεσία. Επομένως, τώρα θα μιλήσω εν συντομία για το πώς να το προετοιμάσω για εργασία.

Travis CI

Το Travis CI είναι ένα εργαλείο για τη δοκιμή και την ανάπτυξη κώδικα. Δεν θέλω να μπω σε λεπτομέρειες σχετικά με τη ρύθμιση του Travis CI, καθώς κάθε έργο είναι μοναδικό και δεν θα κάνει πολύ καλό. Αλλά θα καλύψω τα βασικά για να ξεκινήσετε εάν αποφασίσετε να χρησιμοποιήσετε το Travis CI. Ό,τι κι αν επιλέξετε - Travis CI, CircleCI, Jenkins ή κάτι άλλο, παρόμοιες μέθοδοι διαμόρφωσης θα ισχύουν παντού.

Για να ξεκινήσετε με το Travis CI, μεταβείτε στο ιστοσελίδα έργου και δημιουργήστε λογαριασμό. Στη συνέχεια, ενσωματώστε το Travis CI με τον λογαριασμό σας στο GitHub. Κατά τη ρύθμιση του συστήματος, θα χρειαστεί να καθορίσετε το αποθετήριο που θέλετε να αυτοματοποιήσετε και να ενεργοποιήσετε την πρόσβαση σε αυτό. (Χρησιμοποιώ το GitHub, αλλά είμαι σίγουρος ότι το Travis CI μπορεί να ενσωματωθεί με το BitBucket, το GitLab και άλλες παρόμοιες υπηρεσίες).

Κάθε φορά που ξεκινά το Travis CI, ξεκινά ένας διακομιστής που εκτελεί τις εντολές που καθορίζονται στο αρχείο διαμόρφωσης, συμπεριλαμβανομένης της ανάπτυξης των κατάλληλων διακλαδώσεων του αποθετηρίου.

▍Κύκλος ζωής της εργασίας

Κλήση αρχείου διαμόρφωσης Travis CI .travis.yml και αποθηκεύεται στον ριζικό κατάλογο του έργου, υποστηρίζει την έννοια των συμβάντων κύκλος ζωής καθήκοντα. Ακολουθούν τα γεγονότα, τα οποία παρατίθενται με τη σειρά με την οποία συμβαίνουν:

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

▍Δοκιμές

Στο αρχείο διαμόρφωσης, πρόκειται να εγκαταστήσω έναν τοπικό διακομιστή Travis CI. Επέλεξα την Node 12 ως γλώσσα και είπα στο σύστημα να εγκαταστήσει τις εξαρτήσεις που απαιτούνται για τη χρήση του Docker.

Όλα όσα αναφέρονται σε .travis.yml, θα εκτελεστεί σε όλα τα αιτήματα έλξης σε όλους τους κλάδους του αποθετηρίου, εκτός εάν ορίζεται διαφορετικά. Αυτό είναι ένα χρήσιμο χαρακτηριστικό, καθώς σημαίνει ότι μπορούμε να δοκιμάσουμε όλο τον κώδικα που μπαίνει στο αποθετήριο. Αυτό σας επιτρέπει να γνωρίζετε εάν ο κωδικός είναι έτοιμος για εγγραφή στο υποκατάστημα. master, και αν θα σπάσει τη διαδικασία κατασκευής του έργου. Σε αυτήν την καθολική διαμόρφωση, εγκαθιστώ τα πάντα τοπικά, εκτελώ τον διακομιστή προγραμματιστών Webpack στο παρασκήνιο (αυτή είναι μια δυνατότητα της ροής εργασιών μου) και εκτελώ τις δοκιμές.

Εάν θέλετε το αποθετήριό σας να εμφανίζει εικονίδια κάλυψης κώδικα, εδώ μπορείτε να βρείτε ένα γρήγορο σεμινάριο σχετικά με τον τρόπο χρήσης του Jest, του Travis CI και των Φόρμες για τη συλλογή και εμφάνιση αυτών των πληροφοριών.

Ιδού λοιπόν το περιεχόμενο του αρχείου .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

Εδώ τελειώνουν οι ενέργειες που εκτελούνται για όλους τους κλάδους του αποθετηρίου και για αιτήματα έλξης.

▍Ανάπτυξη

Με βάση την υπόθεση ότι όλες οι αυτοματοποιημένες δοκιμές έχουν ολοκληρωθεί με επιτυχία, μπορούμε προαιρετικά να αναπτύξουμε τον κώδικα στον διακομιστή παραγωγής. Επειδή θέλουμε να το κάνουμε αυτό μόνο για τον κωδικό κλάδου master, δίνουμε στο σύστημα τις κατάλληλες οδηγίες στις ρυθμίσεις ανάπτυξης. Πριν προσπαθήσετε να χρησιμοποιήσετε τον κώδικα που θα εξετάσουμε στη συνέχεια στο έργο σας, θα ήθελα να σας προειδοποιήσω ότι πρέπει να έχετε ένα πραγματικό σενάριο που καλείται για ανάπτυξη.

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

Το σενάριο ανάπτυξης κάνει δύο πράγματα:

  • Δημιουργία, προσθήκη ετικετών και αποστολή της εικόνας στο Docker Hub χρησιμοποιώντας ένα εργαλείο CI (στην περίπτωσή μας είναι το Travis CI).
  • Φόρτωση της εικόνας στον διακομιστή, διακοπή του παλιού κοντέινερ και εκκίνηση νέου (στην περίπτωσή μας, ο διακομιστής εκτελείται στην πλατφόρμα DigitalOcean).

Πρώτα, πρέπει να ρυθμίσετε μια αυτόματη διαδικασία για τη δημιουργία, την προσθήκη ετικετών και την προώθηση της εικόνας στο Docker Hub. Όλα αυτά μοιάζουν πολύ με αυτά που κάναμε ήδη χειροκίνητα, εκτός από το ότι εδώ χρειαζόμαστε μια στρατηγική για την αντιστοίχιση μοναδικών ετικετών σε εικόνες και την αυτοματοποίηση της σύνδεσης. Αντιμετώπισα δυσκολίες με ορισμένες λεπτομέρειες του σεναρίου ανάπτυξης, όπως στρατηγική προσθήκης ετικετών, σύνδεση, κωδικοποίηση κλειδιών SSH, δημιουργία σύνδεσης SSH. Αλλά ευτυχώς ο φίλος μου τα πάει πολύ καλά με το bash, όπως και με πολλά άλλα πράγματα. Με βοήθησε να γράψω αυτό το σενάριο.

Έτσι, το πρώτο μέρος του σεναρίου είναι η αποστολή της εικόνας στο Docker Hub. Για να γίνει αυτό είναι αρκετά απλό. Το σχήμα προσθήκης ετικετών που χρησιμοποίησα περιλαμβάνει το συνδυασμό του κατακερματισμού git και της ετικέτας git, εάν υπάρχει. Αυτό διασφαλίζει ότι η ετικέτα είναι μοναδική και διευκολύνει την αναγνώριση του συγκροτήματος στο οποίο βασίζεται. DOCKER_USERNAME и DOCKER_PASSWORD είναι μεταβλητές περιβάλλοντος που ορίζονται από το χρήστη και μπορούν να ρυθμιστούν χρησιμοποιώντας τη διεπαφή Travis CI. Το Travis CI θα επεξεργαστεί αυτόματα ευαίσθητα δεδομένα, ώστε να μην πέσουν σε λάθος χέρια.

Εδώ είναι το πρώτο μέρος του σεναρίου 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}

Το ποιο θα είναι το δεύτερο μέρος του σεναρίου εξαρτάται αποκλειστικά από τον κεντρικό υπολογιστή που χρησιμοποιείτε και τον τρόπο οργάνωσης της σύνδεσης με αυτόν. Στην περίπτωσή μου, δεδομένου ότι χρησιμοποιώ το Digital Ocean, οι εντολές χρησιμοποιούνται για τη σύνδεση στον διακομιστή doctl. Όταν εργάζεστε με το Aws, θα χρησιμοποιηθεί το βοηθητικό πρόγραμμα aws, και ούτω καθεξής.

Η ρύθμιση του διακομιστή δεν ήταν ιδιαίτερα δύσκολη. Έτσι, έστησα ένα σταγονίδιο με βάση τη βασική εικόνα. Θα πρέπει να σημειωθεί ότι το σύστημα που επέλεξα απαιτεί μία χειροκίνητη εγκατάσταση του Docker και μία χειροκίνητη εκκίνηση του Docker. Χρησιμοποίησα το Ubuntu 18.04 για να εγκαταστήσω το Docker, οπότε αν χρησιμοποιείτε επίσης το Ubuntu μπορείτε απλώς να ακολουθήσετε αυτό απλή καθοδήγηση.

Δεν μιλώ για συγκεκριμένες εντολές για την υπηρεσία εδώ, καθώς αυτή η πτυχή μπορεί να διαφέρει πολύ σε διαφορετικές περιπτώσεις. Θα δώσω απλώς ένα γενικό σχέδιο δράσης που πρέπει να εκτελεστεί μετά τη σύνδεση μέσω SSH στον διακομιστή όπου θα αναπτυχθεί το έργο:

  • Πρέπει να βρείτε το κοντέινερ που λειτουργεί αυτήν τη στιγμή και να το σταματήσετε.
  • Στη συνέχεια, πρέπει να ξεκινήσετε ένα νέο κοντέινερ στο παρασκήνιο.
  • Θα χρειαστεί να ορίσετε την τοπική θύρα του διακομιστή σε 80 - αυτό θα σας επιτρέψει να εισαγάγετε τον ιστότοπο στη διεύθυνση της φόρμας example.com, χωρίς να προσδιορίσετε μια θύρα, αντί να χρησιμοποιήσετε μια διεύθυνση όπως example.com:5000.
  • Και τέλος, πρέπει να αφαιρέσετε όλα τα παλιά δοχεία και τις εικόνες.

Εδώ είναι η συνέχεια του σεναρίου.

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

Μερικά πράγματα που πρέπει να προσέξετε

Είναι πιθανό όταν συνδέεστε στον διακομιστή μέσω SSH από το Travis CI, να δείτε μια προειδοποίηση που δεν θα σας επιτρέψει να συνεχίσετε την εγκατάσταση, καθώς το σύστημα θα περιμένει την απάντηση του χρήστη.

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

Έμαθα ότι ένα κλειδί συμβολοσειράς μπορεί να κωδικοποιηθεί στο base64 για να το αποθηκεύσουμε σε μια μορφή που να μπορεί να εργαστεί με άνεση και αξιοπιστία. Στο στάδιο της εγκατάστασης, μπορείτε να αποκωδικοποιήσετε το δημόσιο κλειδί και να το γράψετε σε ένα αρχείο known_hosts για να απαλλαγείτε από το παραπάνω σφάλμα.

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

Στην πράξη, αυτή η εντολή μπορεί να μοιάζει με αυτό:

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

Και εδώ είναι τι δίνει - μια κωδικοποιημένη συμβολοσειρά base64:

MTIzLjQ1LjY3Ljg5IHNzaC1yc2EgQUFBQUIzTnphQzF5YzJFQUFBQUJJd0FBQVFFQWtsT1Vwa0RIcmZIWTE3U2JybVRJcE5MVEdLOVRqb20vQldEU1UKR1BsK25hZnpsSERUWVc3aGRJNHlaNWV3MThKSDRKVzlqYmhVRnJ2aVF6TTd4bEVMRVZmNGg5bEZYNVFWa2JQcHBTd2cwY2RhMwpQYnY3a09kSi9NVHlCbFdYRkNSK0hBbzNGWFJpdEJxeGlYMW5LaFhwSEFac01jaUxxOFY2UmpzTkFRd2RzZE1GdlNsVksvN1hBCnQzRmFvSm9Bc25jTTFROXg1KzNWMFd3NjgvZUlGbWIxenVVRmxqUUpLcHJyWDg4WHlwTkR2allOYnk2dncvUGIwcndlcnQvRW4KbVorQVc0T1pQblRQSTg5WlBtVk1MdWF5ckQyY0U4NlovaWw4YitndzNyMysxbkthdG1Ja2puMnNvMWQwMVFyYVRsTXFWU3NieApOclJGaTl3cmYrTTdRPT0geW91QGV4YW1wbGUuY29tCg==

Εδώ είναι η εντολή που αναφέρθηκε παραπάνω

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

Η ίδια προσέγγιση μπορεί να χρησιμοποιηθεί με ένα ιδιωτικό κλειδί κατά τη δημιουργία μιας σύνδεσης, καθώς μπορεί να χρειαστείτε ένα ιδιωτικό κλειδί για πρόσβαση στον διακομιστή. Όταν εργάζεστε με ένα κλειδί, χρειάζεται μόνο να βεβαιωθείτε ότι είναι αποθηκευμένο με ασφάλεια σε μια μεταβλητή περιβάλλοντος Travis CI και ότι δεν εμφανίζεται πουθενά.

Ένα άλλο πράγμα που πρέπει να σημειώσετε είναι ότι μπορεί να χρειαστεί να εκτελέσετε ολόκληρο το σενάριο ανάπτυξης ως μία γραμμή, για παράδειγμα με doctl. Αυτό μπορεί να απαιτεί κάποια επιπλέον προσπάθεια.

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

TLS/SSL και εξισορρόπηση φορτίου

Αφού έκανα όλα τα παραπάνω, το τελευταίο πρόβλημα που είχα ήταν ότι ο διακομιστής δεν είχε SSL. Εφόσον χρησιμοποιώ διακομιστή Node.js, για να αναγκάσω εργασία αντίστροφος διακομιστής μεσολάβησης Nginx και Let's Encrypt, πρέπει να κάνετε πολλά.

Πραγματικά δεν ήθελα να κάνω όλες αυτές τις ρυθμίσεις SSL με μη αυτόματο τρόπο, έτσι απλά δημιούργησα ένα πρόγραμμα εξισορρόπησης φορτίου και κατέγραψα πληροφορίες σχετικά με αυτό στο DNS. Στην περίπτωση του DigitalOcean, για παράδειγμα, η δημιουργία ενός αυτο-ανανεούμενου πιστοποιητικού στο εξισορροπητή φορτίου είναι μια απλή, δωρεάν και γρήγορη διαδικασία. Αυτή η προσέγγιση έχει το πρόσθετο πλεονέκτημα ότι καθιστά πολύ εύκολη τη ρύθμιση του SSL σε πολλούς διακομιστές που λειτουργούν πίσω από έναν εξισορροπητή φορτίου, εάν χρειάζεται. Αυτό επιτρέπει στους ίδιους τους διακομιστές να μην «σκέφτονται» καθόλου το SSL, αλλά ταυτόχρονα να χρησιμοποιούν, ως συνήθως, τη θύρα 80. Επομένως, η διαμόρφωση του SSL σε έναν εξισορροπητή φορτίου είναι πολύ πιο εύκολη και πιο βολική από τις εναλλακτικές μεθόδους διαμόρφωσης SSL.

Τώρα μπορείτε να κλείσετε όλες τις θύρες του διακομιστή που δέχονται εισερχόμενες συνδέσεις - εκτός από τη θύρα 80, που χρησιμοποιείται για την επικοινωνία με τον εξισορροπητή φορτίου και τη θύρα 22 για SSH. Ως αποτέλεσμα, μια προσπάθεια να επικοινωνήσετε απευθείας με τον διακομιστή σε οποιαδήποτε άλλη θύρα εκτός από αυτές τις δύο θα αποτύχει.

Αποτελέσματα της

Αφού έκανα όλα όσα μίλησα σε αυτό το άρθρο, ούτε η πλατφόρμα Docker ούτε η έννοια των αυτοματοποιημένων αλυσίδων CI / CD με τρόμαζαν πια. Κατάφερα να δημιουργήσω μια αλυσίδα συνεχούς ενοποίησης, κατά τη διάρκεια της οποίας ο κώδικας ελέγχεται πριν βγει στην παραγωγή και ο κώδικας αναπτύσσεται αυτόματα στον διακομιστή. Όλα αυτά είναι ακόμα σχετικά νέα για μένα και είμαι βέβαιος ότι υπάρχουν τρόποι να βελτιώσω την αυτοματοποιημένη ροή εργασίας μου και να την κάνω πιο αποτελεσματική. Έτσι, εάν έχετε οποιεσδήποτε ιδέες σχετικά με αυτό - δώστε μου ξέρω. Ελπίζω αυτό το άρθρο να σας βοήθησε στις προσπάθειές σας. Θέλω να πιστεύω ότι διαβάζοντάς το έμαθες όσα έμαθα κι εγώ ενώ ασχολούμουν με όλα όσα έλεγα σε αυτό.

PS Σε μας αγορά υπάρχει μια εικόνα Λιμενεργάτης, το οποίο εγκαθίσταται με ένα κλικ. Μπορείτε να ελέγξετε τα δοχεία που δουλεύουν VPS. Σε όλους τους νέους πελάτες δίνονται 3 ημέρες δωρεάν δοκιμές.

Αγαπητοί αναγνώστες! Χρησιμοποιείτε τεχνολογίες CI/CD στα έργα σας;

Δημιουργία αλυσίδας CI / CD και αυτοματοποίηση της εργασίας με το Docker

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο