Créer une chaîne CI/CD et automatiser le travail avec Docker

J'ai écrit mes premiers sites Web à la fin des années 90. À l’époque, il était très facile de les remettre en état de marche. Il y avait un serveur Apache sur un hébergement mutualisé, vous pouviez vous connecter à ce serveur via FTP en écrivant quelque chose comme ftp://ftp.example.com. Ensuite, vous deviez saisir votre nom et votre mot de passe et télécharger les fichiers sur le serveur. Il y avait des époques différentes, tout était plus simple alors qu'aujourd'hui.

Créer une chaîne CI/CD et automatiser le travail avec Docker

Au cours des deux décennies qui ont suivi, tout a beaucoup changé. Les sites Web sont devenus plus complexes ; ils doivent être assemblés avant d’être mis en production. Un seul serveur est devenu plusieurs serveurs fonctionnant derrière des équilibreurs de charge, et l'utilisation de systèmes de contrôle de version est devenue monnaie courante.

Pour mon projet personnel j'avais une configuration particulière. Et je savais que j'avais besoin de pouvoir déployer le site en production en effectuant une seule action : écrire du code dans une branche. master sur GitHub. De plus, je savais que pour assurer le fonctionnement de ma petite application web, je ne souhaitais pas gérer un énorme cluster Kubernetes, ni utiliser la technologie Docker Swarm, ni entretenir une flotte de serveurs avec des pods, des agents et toutes sortes d'autres choses. complexités. Afin d'atteindre l'objectif de rendre le travail aussi simple que possible, j'avais besoin de me familiariser avec CI/CD.

Si vous avez un petit projet (en l'occurrence un projet Node.js) et que vous aimeriez savoir comment automatiser le déploiement de ce projet, tout en vous assurant que ce qui est stocké dans le référentiel correspond exactement à ce qui fonctionne en production, alors je je pense que cet article pourrait vous intéresser.

Conditions préalables

Le lecteur de cet article doit avoir une compréhension de base de la ligne de commande et de l’écriture de scripts Bash. De plus, il aura besoin de comptes Travis CI и Docker Hub.

Objectifs

Je ne dirai pas que cet article peut inconditionnellement être qualifié de « tutoriel ». Il s'agit plutôt d'un document dans lequel je parle de ce que j'ai appris et décris le processus qui me convient pour tester et déployer du code en production, effectué en une seule passe automatisée.

C’est finalement ce que mon flux de travail a été.

Pour le code publié dans n'importe quelle branche du référentiel, sauf master, les actions suivantes sont effectuées :

  • Le projet basé sur Travis CI démarre.
  • Tous les tests unitaires, d’intégration et de bout en bout sont effectués.

Uniquement pour le code qui tombe dans master, les opérations suivantes sont effectuées :

  • Tout ce qui est mentionné ci-dessus, plus...
  • Création d'une image Docker basée sur le code, les paramètres et l'environnement actuels.
  • Déploiement de l'image sur Docker Hub.
  • Connexion au serveur de production.
  • Téléchargement d'une image de Docker Hub vers le serveur.
  • Arrêter le conteneur actuel et en démarrer un nouveau basé sur la nouvelle image.

Si vous ne savez absolument rien de Docker, des images et des conteneurs, ne vous inquiétez pas. Je vais tout vous raconter.

Qu’est-ce que le CI/CD ?

L'abréviation CI/CD signifie « intégration continue/déploiement continu ».

▍Intégration continue

L'intégration continue est un processus dans lequel les développeurs s'engagent dans le référentiel de code source principal du projet (généralement une branche master). Dans le même temps, la qualité du code est garantie grâce à des tests automatisés.

▍Déploiement continu

Le déploiement continu est le déploiement fréquent et automatisé de code en production. La deuxième partie de l'acronyme CI/CD est parfois orthographiée comme « livraison continue ». C'est fondamentalement la même chose que le « déploiement continu », mais la « livraison continue » implique la nécessité de confirmer manuellement les modifications avant de démarrer le processus de déploiement du projet.

Mise en route

L'application que j'ai utilisée pour apprendre tout cela s'appelle Prendre note. Il s'agit d'un projet Web sur lequel je travaille, conçu pour prendre des notes. Au début, j'ai essayé de faire JAMStack-project, ou simplement une application front-end sans serveur, afin de profiter des capacités standards d'hébergement et de déploiement de projets qu'elle offre Netlify. Au fur et à mesure que la complexité de l'application augmentait, j'avais besoin de créer sa partie serveur, ce qui signifiait que je devais formuler ma propre stratégie d'intégration automatisée et de déploiement automatisé du projet.

Dans mon cas, l'application est un serveur Express exécuté dans l'environnement Node.js, servant une application React d'une seule page et prenant en charge une API sécurisée côté serveur. Cette architecture suit la stratégie que l'on retrouve dans donné Guide d'authentification complet.

j'ai consulté autre, qui est un expert en automatisation, et lui a demandé ce que je devais faire pour que tout fonctionne comme je le souhaitais. Il m'a donné une idée de ce à quoi devrait ressembler un flux de travail automatisé, décrit dans la section Objectifs de cet article. Avoir ces objectifs signifiait que je devais comprendre comment utiliser Docker.

Docker

Docker est un outil qui, grâce à la technologie de conteneurisation, permet aux applications d'être facilement distribuées, déployées et exécutées dans le même environnement, même si la plateforme Docker elle-même s'exécute dans des environnements différents. Tout d’abord, je devais mettre la main sur les outils de ligne de commande (CLI) Docker. Instruction Le guide d'installation de Docker ne peut pas être qualifié de très clair et compréhensible, mais vous pouvez y apprendre que pour passer à la première étape d'installation, vous devez 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 le registre NPM pour les packages JavaScript. Il s'agit d'un référentiel en ligne pour les images Docker. C'est à cela que Docker Desktop se connecte.

Ainsi, pour démarrer avec Docker, vous devez faire deux choses :

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

docker -v

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

docker login

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

▍Images

Une image est quelque chose comme un plan contenant des instructions pour assembler le conteneur. Il s'agit d'un instantané immuable du système de fichiers et des paramètres de l'application. Les développeurs peuvent facilement partager des images.

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

Cette commande affichera un tableau avec l'en-tête suivant :

REPOSITORY     TAG     IMAGE ID     CREATED     SIZE
---

Nous examinerons ensuite quelques exemples de commandes dans le même format - il y a d'abord une commande avec un commentaire, puis un exemple de ce qu'elle peut générer.

▍Conteneurs

Un conteneur est un package exécutable qui contient tout ce dont vous avez besoin pour exécuter une application. Une application avec cette approche fonctionnera toujours de la même manière, quelle que soit l'infrastructure : dans un environnement isolé et dans le même environnement. Le fait est que les instances de la même image sont lancées dans des environnements différents.

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

▍Étiquettes

Une balise est une indication d’une version spécifique d’une image.

▍Une référence rapide aux commandes Docker

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

Équipe

Contexte

Действие

construction de menu fixe

Image

Construire une image à partir d'un Dockerfile

balise docker

Image

Marquage d'images

images docker

Image

Liste des images

docker courir

récipient

Exécuter un conteneur basé sur une image

docker poussée

Image

Télécharger une image dans le registre

docker tirer

Image

Chargement d'une image depuis le registre

docker ps

récipient

Répertorier les conteneurs

pruneau du système Docker

Image/Conteneur

Suppression des conteneurs et des images inutilisés

▍Fichier Docker

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

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

Il convient de noter que je n'ai pas d'exemple d'application pour ce matériel. Mais ici, pour les 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 dossier, à première vue, semble assez incompréhensible.

Mais ce qu'il contient décrit seulement, avec des commandes spéciales, quelque chose de similaire à la configuration d'un environnement de travail. Voici quelques-unes de ces commandes :

  • De — Cette commande démarre un fichier. Il spécifie l'image de base sur laquelle le conteneur est construit.
  • COPY — Copie de fichiers d'une source locale vers un conteneur.
  • RÉP TRAVAIL — Définition du répertoire de travail pour les commandes suivantes.
  • COURT - Exécutez des commandes.
  • EXPOSER — Paramètres des ports.
  • POINT D'ACCÈS — Indication de la commande à exécuter.

Dockerfile pourrait 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

En fonction de l'image de base que vous choisissez, vous devrez peut-être installer des dépendances supplémentaires. Le fait est que certaines images de base (comme Node Alpine Linux) sont créées dans le but de les rendre aussi compactes que possible. En conséquence, ils peuvent ne pas disposer de certains des programmes que vous attendez.

▍Construire, baliser et exécuter le conteneur

L'assemblage local et le lancement du conteneur ont lieu après que nous ayons Dockerfile, les tâches sont assez simples. Avant de transférer l'image vers Docker Hub, vous devez la tester localement.

▍Assemblée

Vous devez d'abord collecter image, en précisant un nom et, éventuellement, une balise (si aucune balise n'est spécifiée, le système attribuera automatiquement une balise à l'image latest).

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

Après avoir exécuté cette commande, vous pouvez regarder Docker créer l'image.

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

La construction peut prendre quelques minutes – tout dépend du nombre de dépendances dont vous disposez. Une fois la construction terminée, vous pouvez exécuter la commande docker images et regardez la description de votre nouvelle image.

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

▍Lancement

L'image a été créée. Cela signifie que vous pouvez exécuter un conteneur basé sur celui-ci. Parce que je veux pouvoir accéder à l'application exécutée dans le conteneur à localhost:5000, moi, du côté gauche de la paire 5000:5000 dans la prochaine commande installée 5000. Sur le côté droit se trouve le port à conteneurs.

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

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

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

Si vous allez maintenant à l'adresse localhost:5000 - vous pouvez voir une page d'une application en cours d'exécution qui ressemble exactement à la page d'une application exécutée dans un environnement de production.

▍Étiquetage et publication

Afin d'utiliser l'une des images créées sur le serveur de production, nous devons pouvoir télécharger cette image depuis Docker Hub. Cela signifie que vous devez d'abord créer un référentiel pour le projet sur Docker Hub. Après cela, nous aurons un endroit où nous pourrons envoyer l’image. L'image doit être renommée pour que son nom commence par notre nom d'utilisateur Docker Hub. Cela doit être suivi du nom du référentiel. N'importe quelle balise peut être placée à la fin du nom. Vous trouverez ci-dessous un exemple de dénomination d'images à l'aide de ce schéma.

Vous pouvez maintenant créer l'image avec un nouveau nom et exécuter la commande docker push pour le pousser vers le référentiel 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

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

Prochaines étapes

Nous avons désormais vérifié que l'application, sous la forme d'un conteneur Docker, s'exécute localement. Nous avons téléchargé le conteneur sur Docker Hub. Tout cela signifie que nous avons déjà fait de très bons progrès vers notre objectif. Nous devons maintenant résoudre deux autres questions :

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

Dans notre cas, nous utilisons Travis CI. En tant que serveur - DitigalOcéan.

Il convient de noter qu'ici, vous pouvez utiliser une autre combinaison de services. Par exemple, au lieu de Travis CI, vous pouvez utiliser CircleCI ou Github Actions. Et au lieu de DigitalOcean - AWS ou Linode.

Nous avons décidé de travailler avec Travis CI et j'ai déjà quelque chose de configuré dans ce service. Par conséquent, je vais maintenant parler brièvement de la façon de le préparer au travail.

Travis CI

Travis CI est un outil de test et de déploiement de code. Je ne voudrais pas entrer dans les subtilités de la mise en place de Travis CI, car chaque projet est unique, et cela n'apportera pas beaucoup de bénéfices. Mais je vais aborder les bases pour vous aider à démarrer si vous décidez d'utiliser Travis CI. Que vous choisissiez Travis CI, CircleCI, Jenkins ou autre chose, des méthodes de configuration similaires seront utilisées partout.

Pour démarrer avec Travis CI, accédez à site du projet et créez un compte. Intégrez ensuite Travis CI à votre compte GitHub. Lors de la configuration du système, vous devrez spécifier le référentiel avec lequel vous souhaitez automatiser le travail et en permettre l'accès. (J'utilise GitHub, mais je suis sûr que Travis CI peut s'intégrer à BitBucket, GitLab et d'autres services similaires).

Chaque fois que Travis CI est démarré, le serveur est lancé, exécutant les commandes spécifiées dans le fichier de configuration, y compris le déploiement des branches de référentiel correspondantes.

▍Cycle de vie du travail

Fichier de configuration Travis CI appelé .travis.yml et stocké dans le répertoire racine du projet, prend en charge le concept d'événements cycle de la vie Tâches. Ces événements sont répertoriés dans l'ordre dans lequel ils se produisent :

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

▍Tests

Dans le fichier de configuration, je vais configurer le serveur Travis CI local. J'ai sélectionné Node 12 comme langue et j'ai demandé au système d'installer les dépendances requises pour utiliser Docker.

Tout ce qui est répertorié dans .travis.yml, sera exécuté lorsque toutes les demandes d'extraction seront effectuées vers toutes les branches du référentiel, sauf indication contraire. C'est une fonctionnalité utile car elle signifie que nous pouvons tester tout le code entrant dans le référentiel. Cela vous permet de savoir si le code est prêt à être écrit dans la branche. master, et si cela interrompra le processus de construction du projet. Dans cette configuration globale, j'installe tout localement, j'exécute le serveur de développement Webpack en arrière-plan (c'est une fonctionnalité de mon workflow) et j'exécute des tests.

Si vous souhaitez que votre référentiel affiche des badges indiquant la couverture des tests, ici Vous pouvez trouver de brèves instructions sur l'utilisation de Jest, Travis CI et Coveralls pour collecter et afficher ces informations.

Voici donc 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

C'est ici que se terminent les actions effectuées pour toutes les branches du référentiel et pour les pull request.

▍Déploiement

En partant du principe que tous les tests automatisés se sont terminés avec succès, nous pouvons, ce qui est facultatif, déployer le code sur le serveur de production. Puisque nous voulons faire cela uniquement pour le code de la branche master, nous donnons au système les instructions appropriées dans les paramètres de déploiement. Avant d'essayer d'utiliser le code que nous examinerons ensuite dans votre projet, je voudrais vous avertir que vous devez disposer d'un véritable script appelé pour le déploiement.

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

Le script de déploiement résout deux problèmes :

  • Créez, étiquetez et envoyez l'image à Docker Hub à l'aide d'un outil CI (dans notre cas, Travis CI).
  • Chargement de l'image sur le serveur, arrêt de l'ancien conteneur et démarrage d'un nouveau (dans notre cas, le serveur fonctionne sur la plateforme DigitalOcean).

Tout d’abord, vous devez configurer un processus automatique pour créer, marquer et transférer l’image vers Docker Hub. Tout cela est très similaire à ce que nous avons déjà fait manuellement, sauf que nous avons besoin d'une stratégie pour attribuer des balises uniques aux images et automatiser les connexions. J'ai eu des difficultés avec certains détails du script de déploiement, tels que la stratégie de balisage, la connexion, l'encodage des clés SSH, l'établissement de la connexion SSH. Mais heureusement, mon copain est très doué en bash, comme dans bien d’autres choses. Il m'a aidé à écrire ce scénario.

Ainsi, la première partie du script consiste à télécharger l'image sur Docker Hub. C'est assez facile à faire. Le schéma de balisage que j'ai utilisé consiste à combiner un hachage git et une balise git, s'il en existe une. Cela garantit que la balise est unique et facilite l’identification de l’assembly sur lequel elle est basée. DOCKER_USERNAME и DOCKER_PASSWORD sont des variables d'environnement utilisateur qui peuvent être définies à l'aide de l'interface Travis CI. Travis CI traitera 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}

Le contenu de la deuxième partie du script dépend entièrement de l'hôte que vous utilisez et de la manière dont la connexion à celui-ci est organisée. Dans mon cas, puisque j'utilise Digital Ocean, j'utilise les commandes pour me connecter au serveur doctl. Lorsque vous travaillez avec AWS, l'utilitaire sera utilisé aws, etc.

La configuration du serveur n'a pas été particulièrement difficile. J'ai donc configuré un droplet basé sur l'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 pour faire de même, vous pouvez simplement suivre cette guide simple.

Je ne parle pas ici de commandes spécifiques au service, puisque cet aspect peut varier considérablement selon les cas. Je vais juste donner un plan général d'action à réaliser après connexion via SSH au serveur sur lequel le projet sera déployé :

  • Nous devons trouver le conteneur 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 sur 80 - cela vous permettra d'accéder au site à une adresse comme example.com, sans préciser le port, plutôt que d'utiliser une adresse comme example.com:5000.
  • Enfin, vous devez supprimer tous les anciens conteneurs et images.

Voici la suite du scénario.

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

Certaines choses auxquelles il faut prêter attention

Il est possible que lorsque vous vous connectez au serveur via SSH depuis Travis CI, vous voyiez un avertissement qui vous empêchera de poursuivre l'installation car le système attendra la réponse de l'utilisateur.

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

J'ai appris qu'une clé de chaîne peut être codée en base64 afin de la sauvegarder sous une forme dans laquelle elle peut être utilisée de manière pratique et fiable. Au stade de l'installation, vous pouvez décoder la clé publique et l'écrire dans un fichier known_hosts afin de se débarrasser de l'erreur ci-dessus.

echo <public key> | base64 # выводит <публичный ключ, закодированный в 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== [email protected]" | base64

Et voici ce qu’il produit : une chaîne codée en base64 :

MTIzLjQ1LjY3Ljg5IHNzaC1yc2EgQUFBQUIzTnphQzF5YzJFQUFBQUJJd0FBQVFFQWtsT1Vwa0RIcmZIWTE3U2JybVRJcE5MVEdLOVRqb20vQldEU1UKR1BsK25hZnpsSERUWVc3aGRJNHlaNWV3MThKSDRKVzlqYmhVRnJ2aVF6TTd4bEVMRVZmNGg5bEZYNVFWa2JQcHBTd2cwY2RhMwpQYnY3a09kSi9NVHlCbFdYRkNSK0hBbzNGWFJpdEJxeGlYMW5LaFhwSEFac01jaUxxOFY2UmpzTkFRd2RzZE1GdlNsVksvN1hBCnQzRmFvSm9Bc25jTTFROXg1KzNWMFd3NjgvZUlGbWIxenVVRmxqUUpLcHJyWDg4WHlwTkR2allOYnk2dncvUGIwcndlcnQvRW4KbVorQVc0T1pQblRQSTg5WlBtVk1MdWF5ckQyY0U4NlovaWw4YitndzNyMysxbkthdG1Ja2puMnNvMWQwMVFyYVRsTXFWU3NieApOclJGaTl3cmYrTTdRPT0geW91QGV4YW1wbGUuY29tCg==

Voici la commande mentionnée ci-dessus

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

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

Une autre chose à noter est que vous devrez peut-être exécuter l'intégralité du script de déploiement sur une seule ligne, par exemple - avec doctl. Cela peut nécessiter des efforts supplémentaires.

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

TLS/SSL et équilibrage de charge

Après avoir fait tout ce qui est mentionné ci-dessus, le dernier problème que j'ai rencontré était que le serveur n'avait pas SSL. Puisque j'utilise un serveur Node.js, afin de forcer travailler proxy inverse Nginx et Let's Encrypt, vous devez beaucoup bricoler.

Je ne voulais vraiment pas faire toute cette configuration SSL manuellement, j'ai donc simplement créé un équilibreur de charge et enregistré ses détails dans DNS. Dans le cas de DigitalOcean par exemple, créer un certificat auto-signé à renouvellement automatique sur l'équilibreur de charge est une procédure simple, gratuite et rapide. Cette approche présente l'avantage supplémentaire de faciliter la configuration de SSL sur plusieurs serveurs exécutés derrière un équilibreur de charge si nécessaire. Cela permet aux serveurs eux-mêmes de ne pas « penser » du tout au SSL, mais en même temps d'utiliser le port comme d'habitude 80. Ainsi, la configuration de SSL sur un équilibreur de charge est beaucoup plus simple et pratique que les méthodes alternatives de configuration de SSL.

Vous pouvez désormais fermer tous les ports du serveur qui acceptent les connexions entrantes, à l'exception du port 80, utilisé pour communiquer avec l'équilibreur de charge et le port 22 pour SSH. Par conséquent, toute tentative d'accès direct au serveur sur des ports autres que ces deux échouera.

Les résultats de

Après avoir fait tout ce dont j'ai parlé dans ce document, ni la plateforme Docker ni les concepts de chaînes CI/CD automatisées ne m'ont plus fait peur. J'ai pu mettre en place une chaîne d'intégration continue, durant laquelle le code est testé avant sa mise en production et le code est automatiquement déployé sur le serveur. Tout cela est encore relativement nouveau pour moi et je suis sûr 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, n'hésitez pas à me le faire savoir. moi savoir. J'espère que cet article vous a aidé dans vos démarches. Je veux croire qu'après l'avoir lu, vous avez appris autant que moi en comprenant tout ce dont j'y ai parlé.

PS В нашем marché il y a une image Docker, qui peut être installé en un clic. Vous pouvez vérifier le fonctionnement des conteneurs sur VPS. Tous les nouveaux clients bénéficient de 3 jours de tests gratuits.

Chers lecteurs, Utilisez-vous les technologies CI/CD dans vos projets ?

Créer une chaîne CI/CD et automatiser le travail avec Docker

Source: habr.com

Ajouter un commentaire