Création d'une chaîne CI/CD et automatisation du travail avec Docker.

J'ai créé mes premiers sites à la fin des années 90. À l'époque, il était très simple de les mettre en ligne. Il y avait un serveur Apache sur un hébergement partagé, et on pouvait y accéder par FTP en écrivant dans la barre de navigation quelque chose comme ftp://ftp.example.com. Ensuite, il fallait entrer un nom d'utilisateur et un mot de passe pour télécharger les fichiers sur le serveur. C'étaient d'autres temps, tout était alors plus simple qu'aujourd'hui.

Création d'une chaîne CI/CD et automatisation du travail avec Docker.

Au cours des deux dernières décennies, beaucoup de choses ont changé. Les sites sont devenus plus complexes, et avant de les mettre en production, ils doivent être assemblés. Un seul serveur est devenu de nombreux serveurs fonctionnant derrière des équilibrages de charge, et l'utilisation de systèmes de contrôle de version est devenue courante.

Pour mon projet personnel, j'avais une configuration particulière. Et je savais que j'avais besoin de la possibilité de déployer le site en production en effectuant une seule action : écrire le code dans la branche master sur GitHub. De plus, je savais que, pour faire fonctionner ma petite application web, je ne voulais pas m'occuper de la gestion d'un énorme cluster Kubernetes, ou d'utiliser la technologie Docker Swarm, ou de maintenir un parc de serveurs avec des pods, des agents et d'autres complexités. Pour atteindre mon objectif de simplification maximale, j'ai dû me familiariser avec le CI/CD.

Si vous avez un petit projet (dans notre cas, un projet Node.js) et que vous aimeriez savoir comment automatiser le déploiement de ce projet en veillant à ce que ce qui est stocké dans le dépôt corresponde exactement à ce qui fonctionne en production, alors je pense que cet article pourrait vous intéresser.

Prérequis

Il est attendu que le lecteur de cet article ait des connaissances de base en ligne de commande et en écriture de scripts Bash. De plus, il aura besoin de comptes Travis CI et Docker Hub.

Objectifs

Je ne dirai pas que cet article peut être qualifié sans réserve de « guide pratique ». Il s'agit plutôt d'un document dans lequel je partage ce que j'ai appris et décris le processus de test et de déploiement de code en production qui me convient, effectué en un seul passage automatisé.

Voici à quoi ressemble au final mon processus de travail.

Pour le code envoyé dans n'importe quelle branche du dépôt, à l'exception de master, les actions suivantes sont effectuées :

  • La construction du projet est lancée sur Travis CI.
  • Tous les tests unitaires, d'intégration et de bout en bout sont exécutés.

Uniquement pour le code qui est inclus dans master, la procédure suivante est effectuée :

  • Tout ce qui a été dit ci-dessus, plus…
  • Création de l'image Docker basée sur le code actuel, les configurations et l'environnement.
  • Publication de l'image sur Docker Hub.
  • Connexion au serveur de production.
  • Téléchargement de l'image depuis Docker Hub sur le serveur.
  • Arrêt du conteneur actuel et démarrage d'un nouveau basé sur la nouvelle image.

Si vous ne savez absolument rien sur Docker, les images et les conteneurs, ne vous inquiétez pas. Je vais tout vous expliquer.

Qu'est-ce que le CI/CD ?

L'acronyme CI/CD signifie « continuous integration/continuous deployment » — « intégration continue/deploiement continu ».

▍Intégration continue

L'intégration continue est le processus par lequel les développeurs effectuent des commits dans le dépôt principal du code source du projet (généralement dans la branche master). La qualité du code est assurée par des tests automatisés.

▍Déploiement continu

Le déploiement continu est un déploiement fréquent et automatisé du code en production. La deuxième partie de l'acronyme CI/CD est parfois interprétée comme « continuous delivery » (« livraison continue »). C'est, en gros, la même chose que le « déploiement continu », mais la « livraison continue » implique la nécessité d'une validation manuelle des modifications avant de lancer le processus de déploiement du projet.

Commencer

L'application sur laquelle j'ai appris tout cela s'appelle TakeNote. C'est un projet web sur lequel je travaille, destiné à prendre des notes. Au début, j'ai essayé de créer un projet JAMStack- ou une application frontale seule sans serveur, afin de profiter des capacités standard d'hébergement et de déploiement de projets offertes par Netlify. À mesure que la complexité de l'application augmentait, j'ai dû créer sa partie serveur, ce qui signifiait que je devais établir ma propre stratégie d'intégration et de déploiement automatisés du projet.

Dans mon cas, l'application se compose d'un serveur Express fonctionnant dans l'environnement Node.js, servant une application React à page unique et supportant une API serveur sécurisée. Cette architecture suit une stratégie que l'on peut trouver dans ce guide sur l'authentification full stack.

J'ai consulté un autre, qui est un expert en automatisation, et je lui ai demandé ce que je devais faire pour que tout cela fonctionne comme je le souhaite. Il m'a donné une idée de la façon dont le flux de travail automatisé devrait ressembler, comme décrit dans la section « Objectifs » de cet article. Le fait que je me sois fixé de tels objectifs signifiait que je devais comprendre comment utiliser Docker.

Docker

Docker est un outil qui, grâce à la technologie de conteneurisation, permet de distribuer facilement des applications, ainsi que de les déployer et de les exécuter dans le même environnement, même si la plateforme Docker elle-même fonctionne dans des environnements différents. Pour commencer, j'avais besoin d'accéder aux outils de ligne de commande (CLI) Docker. Instructions d'installation de Docker ne peuvent pas être considérées comme très claires et compréhensibles, mais elles permettent de savoir que pour faire le premier pas dans l'installation, il faut télécharger Docker Desktop (pour Mac ou Windows).

Docker Hub est à peu près la même chose que GitHub pour les dépôts git, ou un registre npm pour les paquets JavaScript. C'est un dépôt en ligne pour les images Docker. C'est à lui que se connecte Docker Desktop.

Ainsi, pour commencer à travailler avec Docker, vous devez faire deux choses :

Après cela, vous pouvez vérifier le bon fonctionnement de Docker CLI en exécutant la commande suivante pour vérifier la version de Docker :

docker -v

Ensuite, connectez-vous à Docker Hub en saisissant, lorsque vous y êtes invité, votre nom d'utilisateur et votre mot de passe :

docker login

Pour utiliser Docker, vous devez comprendre les concepts d'images et de conteneurs.

▍Images

Une image est en quelque sorte un plan contenant des instructions pour construire un conteneur. C'est un instantané immuable du système de fichiers et des configurations de l'application. Les développeurs peuvent facilement échanger des images.

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

Cette commande affichera un tableau avec le titre suivant :

REPOSITORY     TAG     IMAGE ID     CREATED     SIZE
---

Ensuite, nous examinerons quelques exemples de commandes dans ce même format — d'abord vient la commande avec un commentaire, puis un exemple de ce qu'elle peut afficher.

▍Conteneurs

Un conteneur est un paquet exécutable qui contient tout ce dont une application a besoin pour fonctionner. Avec cette approche, l'application fonctionne toujours de la même manière, peu importe l'infrastructure : dans un environnement isolé et dans le même cadre. Il s'agit de l'exécution d'instances de la même image dans différents environnements.

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

▍Tags

Une balise est une indication d'une version spécifique de l'image.

▍Aperçu des commandes Docker

Voici un aperçu de certaines commandes Docker fréquemment utilisées.

Commande

Contexte

Action

docker build

Image

Construction de l'image à partir du Dockerfile

docker tag

Image

Taguer l'image

docker images

Image

Afficher la liste des images

docker run

Conteneur

Démarrer un conteneur à partir de l'image

docker push

Image

Pousser l'image dans le registre

docker pull

Image

Tirer l'image du registre

docker ps

Conteneur

Afficher la liste des conteneurs

docker system prune

Image/Conteneur

Supprimer les conteneurs et images inutilisés

▍Fichier Dockerfile

Je sais comment exécuter une application localement pour la production. J'ai une configuration Webpack conçue pour construire une application React prête à l'emploi. Ensuite, j'ai une commande qui lance un serveur basé sur Node.js sur le port 5000. Cela ressemble à ceci :

npm i         # installation des dépendances
npm run build # construction de l'application React
npm run start # démarrer le serveur Node

Il est important de noter que je n'ai pas d'application exemple pour ce matériel. Mais ici, pour faire des expériences, n'importe quelle simple application Node fera l'affaire.

Pour utiliser le conteneur, vous devrez donner des instructions à Docker. Cela se fait via un fichier appelé Dockerfile, situé dans le répertoire racine du projet. Ce fichier peut sembler assez incompréhensible au départ.

Mais ce qu'il contient ne fait que décrire, avec des commandes spécifiques, quelque chose de similaire à la configuration d'un environnement de travail. Voici quelques-unes de ces commandes :

  • DE — Cette commande commence le fichier. Elle spécifie l'image de base sur laquelle le conteneur sera construit.
  • COPY — Copier des fichiers d'une source locale dans le conteneur.
  • WORKDIR — Définir le répertoire de travail pour les commandes suivantes.
  • RUN — Exécuter des commandes.
  • EXPOSE — Configurer le port.
  • ENTRYPOINT — Spécifier la commande à exécuter.

Dockerfile peut ressembler à ceci :

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

Selon l'image de base choisie, vous devrez peut-être installer des dépendances supplémentaires. En effet, certaines images de base (comme Node Alpine Linux) sont conçues pour être aussi compactes que possible. Par conséquent, elles peuvent manquer de certains programmes auxquels vous vous attendez.

▍Construction, étiquetage et lancement d'un conteneur

La construction et le lancement locaux du conteneur – c'est, après avoir obtenu Dockerfile, les tâches sont assez simples. Avant d'envoyer l'image sur Docker Hub, elle doit être testée localement.

▍Construction

Tout d'abord, vous devez construire image, en spécifiant un nom, et, si vous le souhaitez, un tag (si le tag n'est pas spécifié, le système attribuera automatiquement un tag à l'image. latest).

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

Après l'exécution de cette commande, vous pouvez observer comment Docker construit l'image.

Envoi du contexte de construction au démon Docker   2.88MB
Étape 1/9 : FROM node:12-alpine
 ---> ...exécution des étapes de construction...
Construite avec succès 123456789123
Étiquetée avec succès <image>:<tag>

La construction peut prendre quelques minutes – cela dépend des dépendances que vous avez. Une fois la construction terminée, vous pouvez exécuter la commande docker images et voir la description de votre nouvelle image.

RÉPERTOIRE          TAG               ID D'IMAGE            CRÉÉE              TAILLE
<image>             latest            123456789123        Il y a environ une minute   x.xxGB

▍Lancement

L'image est créée. Cela signifie qu'il est possible de lancer un conteneur à partir de celle-ci. Comme je veux pouvoir accéder à l'application qui fonctionne dans le conteneur à l'adresse localhost:5000, dans la partie gauche de la paire 5000:5000 j'ai défini dans la commande suivante. 5000. Dans la partie droite se trouve le port du conteneur.

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

Maintenant que le conteneur est créé et lancé, vous pouvez utiliser la commande docker ps pour voir les informations sur ce conteneur (ou vous pouvez utiliser la commande docker ps -a, qui affiche les informations sur tous les conteneurs, et pas seulement ceux qui sont en cours d'exécution).

ID DE CONTENEUR        IMAGE               COMMANDE                  CRÉÉE              STATUT                      PORTS                    NOMS
987654321234        <image>             "\/bin\/sh -c 'npm run…"   6 secondes ago        En cours depuis 6 secondes                0.0.0.0:5000->5000\/tcp   stoic_darwin

Si vous allez maintenant à l'adresse localhost:5000 – vous pouvez voir la page de l'application en cours d'exécution, qui ressemble exactement à la page de l'application en production.

▍Attribution de tag et publication

Pour utiliser l'une des images créées sur le serveur de production, nous devons avoir la possibilité de télécharger cette image depuis Docker Hub. Cela signifie qu'il faut d'abord créer un dépôt sur Docker Hub pour le projet. Ensuite, nous disposerons d'un endroit où nous pourrons envoyer l'image. L'image doit être renommée de manière à ce que son nom commence par notre nom d'utilisateur sur Docker Hub. Après cela, doit suivre le nom du dépôt. À la fin du nom, il peut y avoir n'importe quelle étiquette. Voici un exemple de nomenclature des images selon ce schéma.

Nous pouvons maintenant construire l'image en lui attribuant un nouveau nom et exécuter la commande docker push pour l'envoyer au dépôt Docker Hub.

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

# En pratique, cela pourrait ressembler à cela :
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

Si tout se passe bien, l'image sera disponible sur Docker Hub et pourra être facilement téléchargée sur le serveur ou transmise à d'autres développeurs.

Prochaines étapes

À ce stade, nous avons confirmé que l'application, sous forme de conteneur Docker, fonctionne localement. Nous avons téléchargé le conteneur sur Docker Hub. Tout cela signifie que nous avons déjà bien progressé vers notre objectif. Maintenant, nous devons résoudre deux autres questions :

  • Configuration de l'outil CI pour tester et déployer le code.
  • Configuration du serveur de production afin qu'il puisse télécharger et exécuter notre code.

Dans notre cas, nous utilisons comme solution CI/CD Travis CI. Comme serveur - DigitalOcean.

Il convient de noter qu'il est également possible d'utiliser une autre combinaison de services. Par exemple, au lieu de Travis CI, on peut utiliser CircleCI ou Github Actions. Et au lieu de DigitalOcean - AWS ou Linode.

Nous avons décidé de travailler avec Travis CI, et pour ce service, j'ai déjà configuré certaines choses. Je vais donc brièvement expliquer comment le préparer au travail.

Travis CI

Travis CI est un outil pour tester et déployer le code. Je ne voudrais pas entrer dans les détails de la configuration de Travis CI, car chaque projet est unique, et cela n'apportera pas de bénéfice particulier. Mais je vais parler des bases qui vous permettront de commencer à travailler si vous décidez d'utiliser Travis CI. Quoi que vous choisissiez - Travis CI, CircleCI, Jenkins, ou autre, des méthodes de configuration similaires s'appliqueront.

Pour commencer à travailler avec Travis CI, rendez-vous sur du projet et créez un compte. Ensuite, intégrez Travis CI avec votre compte GitHub. Au cours de la configuration du système, vous devrez spécifier le dépôt avec lequel vous souhaitez automatiser le travail et lui donner accès. (J'utilise GitHub, mais je suis sûre que Travis CI peut également s'intégrer à BitBucket, GitLab, et d'autres services similaires).

Chaque fois que Travis CI commence à travailler, un serveur est lancé pour exécuter les commandes spécifiées dans le fichier de configuration, y compris le déploiement des branches correspondantes du dépôt.

▍Cycle de vie de la tâche

Le fichier de configuration de Travis CI, appelé .travis.yml et stocké dans le répertoire racine du projet, maintient le concept d'événements durée de vie de tâche. Voici ces événements, présentés dans l'ordre où ils se produisent :

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

▍Tests

Dans le fichier de configuration, je vais configurer un serveur local Travis CI. J'ai choisi le langage Node 12 et j'ai indiqué au système d'installer les dépendances nécessaires pour utiliser Docker.

Tout ce qui est énuméré dans .travis.yml, sera exécuté lors de l'exécution de toutes les pull requests pour toutes les branches du dépôt, sauf indication contraire. C'est une fonctionnalité utile car cela signifie que nous pouvons tester tout le code entrant dans le dépôt. Cela permet de savoir si le code est prêt à être enregistré dans la branche master, et s'il ne perturbera pas le processus de construction du projet. Dans cette configuration globale, j'installe tout localement, lance le serveur de développement Webpack en arrière-plan (c'est une fonctionnalité de mon flux de travail) et exécute les tests.

Si vous souhaitez que votre dépôt affiche des badges avec des informations sur la couverture de code des tests, ici vous pouvez trouver un guide succinct sur l'utilisation de Jest, Travis CI et Coveralls pour rassembler et afficher ces informations.

Alors, voici le contenu du fichier .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

Ici se terminent les actions qui sont effectuées pour toutes les branches du dépôt et pour les pull requests.

▍Déploiement

En supposant que tous les tests automatisés se soient déroulés avec succès, nous pouvons, sans obligation, déployer le code sur le serveur de production. Comme nous souhaitons le faire uniquement pour le code de la branche master, nous donnons au système des instructions appropriées dans les paramètres de déploiement. Avant que vous n'essayiez d'utiliser dans votre projet le code que nous allons examiner plus loin, je voudrais vous avertir qu'il vous faut un véritable script appelé pour le déploiement.

deploy:
  # Construire le conteneur Docker et l'envoyer sur Docker Hub
  provider: script
  script: bash deploy.sh
  on:
    branch: master

Le script de déploiement remplit deux tâches :

  • La construction, le tagging et l'envoi de l'image sur Docker Hub à l'aide de l'outil CI (dans notre cas, c'est Travis CI).
  • Le téléchargement de l'image sur le serveur, l'arrêt de l'ancien conteneur et le démarrage du nouveau (dans notre cas, le serveur fonctionne sur la plateforme DigitalOcean).

Tout d'abord, il faut configurer le processus automatique de construction, de tagging et d'envoi de l'image sur Docker Hub. Tout cela ressemble beaucoup à ce que nous avons déjà fait manuellement, sauf que nous avons besoin ici d'une stratégie pour attribuer des tags uniques aux images et d'automatiser la connexion. J'ai eu des difficultés avec certains détails du script de déploiement, comme la stratégie de tagging, la connexion, l'encodage des clés SSH, l'établissement de la connexion SSH. Mais, heureusement, mon petit ami s'en sort très bien avec bash, ainsi qu'avec beaucoup d'autres choses. Il m'a aidé à écrire ce script.

Ainsi, la première partie du script consiste à envoyer l'image sur Docker Hub. C'est assez simple à faire. Le schéma de tagging que j'utilise implique de combiner le hash git et un tag git, si celui-ci existe. Cela permet de créer un tag unique et facilite l'identification de la build sur laquelle il est basé. DOCKER_USERNAME et DOCKER_PASSWORD — ce sont des variables d'environnement personnalisées que l'on peut définir dans l'interface de Travis CI. Travis CI traite automatiquement les données sensibles afin qu'elles ne tombent pas entre de mauvaises mains.

Voici la première partie du 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 manière dont sera la deuxième partie du script dépend entièrement de l'hôte que vous utilisez et de la façon dont la connexion est organisée. Dans mon cas, puisque j'utilise Digital Ocean, les commandes utilisées pour se connecter au serveur sont doctl. Lorsqu'on travaille avec AWS, l'outil utilisé sera aws, et ainsi de suite.

Configurer le serveur n'était pas particulièrement difficile. J'ai configuré un droplet basé sur une image de base. Il convient de noter que le système que j'ai choisi nécessite une installation manuelle unique de Docker et un lancement manuel unique de Docker. J'ai utilisé Ubuntu 18.04 pour installer Docker, donc si vous utilisez également Ubuntu, vous pouvez simplement suivre ceci un guide simple.

Je ne parle pas ici des commandes spécifiques au service, car cet aspect peut varier considérablement selon les cas. Je vais simplement fournir un plan général d'action à réaliser après s'être connecté par SSH au serveur sur lequel le projet sera déployé :

  • Vous devez trouver le conteneur actuellement en cours d'exécution et l'arrêter.
  • Ensuite, vous devez lancer un nouveau conteneur en arrière-plan.
  • Vous devrez définir le port local du serveur à 80 — cela vous permettra d'accéder au site à une adresse du type example.com, sans indiquer le port, au lieu d'utiliser une adresse comme example.com:5000.
  • Et enfin, il faut supprimer tous les anciens conteneurs et images.

Voici la suite du 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 -f

Quelques éléments à considérer

Il se peut que lorsque vous vous connectiez au serveur par SSH depuis Travis CI, vous rencontriez un avertissement qui empêchera la poursuite de l'installation, car le système attendra la réaction de l'utilisateur.

L'authenticité de l'hôte '<hostname> (<IP address>)' ne peut pas être établie.
L’empreinte de la clé RSA est <key fingerprint>.
Êtes-vous sûr de vouloir continuer à vous connecter (oui/non) ?

J'ai découvert qu'une clé de chaîne peut être codée en base64 afin de la conserver sous une forme qui permet de la manipuler facilement et en toute sécurité. Au stade de l'installation, vous pouvez décoder la clé publique et l'enregistrer dans le fichier known_hosts afin d'éviter l'erreur décrite ci-dessus.

echo <public key> | base64 # affiche <clé publique codée en base64>

En pratique, cette commande pourrait ressembler à ceci :

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

Voici à quoi ressemble la sortie — une chaîne encodée en base64 :

MTIzLjQ1LjY3Ljg5IHNzaC1yc2EgQUFBQUIzTnphQzF5YzJFQUFBQUJJd0FBQVFFQWtsT1Vwa0RIcmZIWTE3U2JybVRJcE5MVEdLOVRqb20vQldEU1UKR1BsK25hZnpsSERUWVc3aGRJNHlaNWV3MThKSDRKVzlqYmhVRnJ2aVF6TTd4bEVMRVZmNGg5bEZYNVFWa2JQcHBTd2cwY2RhMwpQYnY3a09kSi9NVHlCbFdYRkNSK0hBbzNGWFJpdEJxeGlYMW5LaFhwSEFac01jaUxxOFY2UmpzTkFRd2RzZE1GdlNsVksvN1hBCnQzRmFvSm9Bc25jTTFROXg1KzNWMFd3NjgvZUlGbWIxenVVRmxqUUpLcHJyWDg4WHlwTkR2allOYnk2dncvUGIwcndlcnQvRW4KbVorQVc0T1pQblRQSTg5WlBtVk1MdWF5ckQyY0U4NlovaWw4YitndzNyMysxbkthdG1Ja2puMnNvMWQwMVFyYVRsTXFWU3NieApOclJGaTl3cmYrTTdRPT0geW91QGV4YW1wbGUuY29tCg==

Voici la commande mentionnée ci-dessus

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

La même approche peut être utilisée avec une clé privée lors de l'établissement de la connexion, car vous pourriez avoir besoin de la clé privée pour accéder au serveur. Lorsque vous travaillez avec la clé, il vous suffit de la conserver en toute sécurité dans une variable d'environnement Travis CI et de vous assurer qu'elle n'est pas affichée.

Une autre chose à noter est que vous pourriez avoir besoin d'exécuter tout le script de déploiement présenté sous forme d'une seule ligne, par exemple — en utilisant doctl. Cela peut nécessiter quelques efforts supplémentaires.

doctl compute ssh  --ssh-command "toutes les commandes seront ici && ici"

TLS/SSL et répartition de charge

Après avoir fait tout ce qui a été mentionné ci-dessus, le dernier problème auquel j'étais confrontée était que le serveur n'avait pas de SSL. Étant donné que j'utilise un serveur Node.js, il faut que à travailler un proxy inverse Nginx et Let's Encrypt, cela nécessite pas mal d'efforts.

Je n'avais vraiment pas envie de faire toutes ces configurations SSL manuellement, alors j'ai simplement créé un équilibreur de charge et enregistré ses informations dans le DNS. Dans le cas de DigitalOcean, par exemple, créer un certificat auto-signé qui se renouvelle automatiquement sur l'équilibreur de charge est une procédure simple, gratuite et rapide. Cette approche a également l'avantage d'une configuration très simple du SSL sur plusieurs serveurs derrière l'équilibreur de charge. Cela permet aux serveurs de ne pas avoir à « s'inquiéter » du SSL, tout en utilisant le port 80. Ainsi, la configuration du SSL sur l'équilibreur de charge est beaucoup plus simple et pratique que les méthodes alternatives.

Vous pouvez maintenant fermer tous les ports sur le serveur acceptant des connexions entrantes — sauf le port 80, utilisé pour la connexion à l'équilibreur de charge, et le port 22 pour SSH. En conséquence, toute tentative d'accès direct au serveur via d'autres ports, à l'exception de ces deux, échouera.

Résultats

Après avoir fait tout ce que j'ai décrit dans cet article, je ne suis plus intimidée ni par la plateforme Docker ni par les concepts des chaînes CI/CD automatisées. J'ai pu configurer une chaîne d'intégration continue, au cours de laquelle le code est testé avant son déploiement en production et déployé automatiquement sur le serveur. Tout cela est encore relativement nouveau pour moi, et je suis convaincue qu'il existe des moyens d'améliorer mon flux de travail automatisé et de le rendre plus efficace. Donc, si vous avez des idées à ce sujet, faites-le moi savoir. moi J'espère que cet article vous a été utile. Je veux croire qu'en le lisant, vous avez appris autant que moi en explorant tout ce dont j'ai parlé.

P.S. Dans notre sur le marketplace il y a une image Docker, qui s'installe en un clic. Vous pouvez vérifier le fonctionnement des conteneurs sur VPS. Tous les nouveaux clients se voient offrir 3 jours gratuits pour des tests.

Chers lecteurs ! Utilisez-vous des technologies CI/CD dans vos projets ?

Création d'une chaîne CI/CD et automatisation du travail avec Docker.

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster