Стварэнне CI/CD-ланцужкі і аўтаматызацыя працы з Docker

Я напісала мае першыя сайты напрыканцы 90-х. Тады прыводзіць іх у працоўны стан было вельмі проста. Быў Apache-сервер на якім-небудзь агульным хостынгу, на гэты сервер можна было ўвайсці па FTP, напісаўшы ў браузерным радку нешта накшталт ftp://ftp.example.com. Пасля трэба было ўвесці імя і пароль і выгрузіць файлы на сервер. Іншыя былі часы, усё тады было прасцей, чым зараз.

Стварэнне CI/CD-ланцужкі і аўтаматызацыя працы з Docker

За мінулыя з таго часу два дзесяцігоддзі ўсё ладна змянілася. Сайты сталі больш складанымі, іх, перад выпускам у прадакшн, трэба збіраць. Адзін адзіны сервер стаў мноствам сервераў, якія працуюць за балансавальнікамі нагрузкі, звычайнай справай стала выкарыстанне сістэм кантролю версій.

Для майго персанальнага праекту ў мяне была адмысловая канфігурацыя. І я ведала, што мне патрэбна магчымасць разгортваць сайт у прадакшні, выконваючы ўсяго адно дзеянне: запіс кода ў галінку master на GitHub. Я, акрамя таго, ведала, што мне, для забеспячэння працы майго маленькага вэб-прыкладанні, не жадаецца займацца кіраваннем велізарным кластарам Kubernetes, ці карыстацца тэхналогіяй Docker Swarm, ці падтрымліваць парк сервераў з подамі, агентамі і ўсякімі іншымі складанасцямі. Для таго каб дасягнуць мэты па максімальным спрашчэнні працы, мне спатрэбілася пазнаёміцца ​​з CI/CD.

Калі ў вас ёсць маленькі праект (у нашым выпадку гаворка ідзе пра Node.js-праект) і вам хацелася б даведацца пра тое, як аўтаматызаваць разгортванне гэтага праекта, зрабіўшы пры гэтым так, каб тое, што захоўваецца ў рэпазітары, у дакладнасці адпавядала б таму, што працуе ў прадакшні, то, мяркую, вас можа зацікавіць гэты артыкул.

папярэднія патрабаванні

Чакаецца, што чытач гэтага артыкула мае базавыя веды ў вобласці працы з камандным радком і напісанні Bash-скрыптоў. Акрамя таго, яму спатрэбяцца ўліковыя запісы Travis CI и Дак-канцэнтратар.

Мэты

Не скажу, што гэты артыкул можа безумоўна называцца "навучальным кіраўніцтвам". Гэта - хутчэй дакумент, у якім я распавядаю аб тым, што даведалася, і апісваю які задавальняе мяне працэс тэставання і разгортванні кода ў прадакшні, выкананы за адзін аўтаматызаваны праход.

Вось якім у выніку атрымаўся мой працоўны працэс.

Для кода, адпраўленага ў любую галіну рэпазітара, акрамя master, вырабляюцца такія дзеянні:

  • Запускаецца зборка праекту на Travis CI.
  • Выконваюцца ўсе модульныя, інтэграцыйныя і скразныя тэсты.

Толькі для кода, які трапляе ў master, выконваецца наступнае:

  • Усё тое, пра што сказана вышэй, плюс…
  • Зборка выявы Docker на падставе бягучага кода, налад і асяроддзі.
  • Размяшчэнне выявы на Docker Hub.
  • Падключэнне да прадакшн-сервера.
  • Загрузка выявы з Docker Hub на сервер.
  • Прыпынак бягучага кантэйнера і запуск новага, заснаванага на новым вобразе.

Калі вы зусім нічога не ведаеце аб Docker, аб выявах і кантэйнерах - не турбуйцеся. Я пра гэта ўсё вам раскажу.

Што такое CI/CD?

Абрэвіятура CI/CD расшыфроўваецца як "continuous integration/continuous deployment" - "бесперапынная інтэграцыя/бесперапыннае разгортванне".

▍Бесперапынная інтэграцыя

Бесперапынная інтэграцыя – гэта працэс, падчас якога распрацоўшчыкі робяць коміты ў галоўнае сховішча зыходнага кода праекта (звычайна ў галінку master). Пры гэтым якасць кода забяспечваецца шляхам правядзення аўтаматызаванага тэсціравання.

▍ Бесперапыннае разгортванне

Бесперапыннае разгортванне - гэта частае аўтаматызаванае разгортванне кода ў прадакшне. Другая частка абрэвіятуры CI/CD часам расчыняецца як "continuous delivery" ("бесперапынная дастаўка"). Гэта, у цэлым, тое ж самае, што і "бесперапыннае разгортванне", але "бесперапынная дастаўка" мае на ўвазе неабходнасць ручнога пацверджання змяненняў перад запускам працэсу разгортвання праекта.

Пачатак працы

Дадатак, на якім я гэта ўсё асвойвала, называецца Прымаць да ведама. Гэта - вэб-праект, над якім я працую, прызначаны для таго, каб рабіць нататкі. Спачатку я паспрабавала зрабіць JAMStack-праект, ці толькі фронтэнд-дадатак без сервера, для таго каб скарыстацца стандартнымі магчымасцямі па хостынгу і разгортванню праектаў, якія прапануе Netlify. Па меры таго, як расла складанасць дадатку, мне спатрэбілася стварыць і яго серверную частку, а гэта азначала, што мне трэба было б сфарміраваць уласную стратэгію па аўтаматызаванай інтэграцыі і аўтаматызаваным разгортванні праекта.

У маім выпадку прыкладанне ўяўляе сабой Express-сервер, які працуе ў асяроддзі Node.js, які абслугоўвае аднастаронкавая React-дадатак і падтрымлівае абаронены серверны API. Гэтая архітэктура варта стратэгіі, якую можна знайсці ў дадзеным кіраўніцтве па фулстэк-аўтэнтыфікацыі.

Я параілася з сябрам, які з'яўляецца экспертам па аўтаматызацыі, і спытала яго аб тым, што мне трэба зрабіць для таго, каб усё гэта працавала так, як мне трэба. Ён падкінуў мне ідэю аб тым, як павінен выглядаць аўтаматызаваны працоўны працэс, выкладзены ў раздзеле "Мэты" гэтага артыкула. Тое, што я паставіла перад сабой падобныя мэты, азначала, што мне трэба разабрацца ў тым, як скарыстацца Docker.

Докер

Docker - гэта інструмент, які, дзякуючы тэхналогіі кантэйнерызацыі, дазваляе лёгка распаўсюджваць прыкладанні, а таксама выконваць іх разгортванне і запуск у адным і тым жа асяроддзі нават у тым выпадку, калі сама платформа Docker працуе ў розных асяроддзях. Для пачатку мне трэба было атрымаць у сваё распараджэнне прылады каманднага радка (CLI) Docker. Інструкцыю па ўсталёўцы Docker нельга назваць вельмі выразнай і зразумелай, але з яе можна пазнаць аб тым, што для таго, каб зрабіць першы крок усталёўкі, трэба спампаваць Docker Desktop (для Mac або Windows).

Docker Hub - гэта прыкладна тое ж самае, што GitHub для git-рэпазітараў, або рэестр НПМ для 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 build

вобраз

Зборка выявы з Dockerfile

docker tag

вобраз

Тэгаванне выявы

докер малюнка

вобраз

Выснова спісу выяў

докер прабег

кантэйнер

Запуск кантэйнера на аснове выявы

docker push

вобраз

Адпраўка выявы ў рэестр

докер цягнуць

вобраз

Загрузка выявы з рэестра

докер п.с.

кантэйнер

Выснова спісу кантэйнераў

docker system prune

Выява/Кантэйнер

Выдаленне кантэйнераў і вобразаў, якія не выкарыстоўваюцца.

▍Файл Dockerfile

Я ведаю, як лакальна запусціць прыкладанне для прадакшна. У мяне ёсць Webpack-канфігурацыя, прызначаная для зборкі гатовага React-прыкладанні. Далей, у мяне ёсць каманда, якая запускае сервер, заснаваны на Node.js, на порце 5000. Выглядае гэта так:

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

Трэба адзначыць, што ў мяне няма прыкладанні-прыкладу для гэтага матэрыялу. Але тут, для эксперыментаў, падыдзе любое простае Node-дадатак.

Для таго каб скарыстацца кантэйнерам, вам спатрэбіцца даць інструкцыі Docker. Робіцца гэта з дапамогай файла, званага Dockerfile, які знаходзіцца ў каранёвай дырэкторыі праекта. Гэты файл, спачатку, здаецца даволі-такі незразумелым.

Але тое, што ў ім утрымоўваецца, усяго толькі апісвае, адмысловымі камандамі, нешта падобнае наладзе працоўнага асяроддзя. Вось некаторыя з гэтых каманд:

  • З - Гэтая каманда пачынае файл. У ёй паказваецца базавая выява, на аснове якога будуецца кантэйнер.
  • COPY - Капіраванне файлаў з лакальнага крыніцы ў кантэйнер.
  • WORKDIR - Устаноўка рабочай дырэкторыі для наступных каманд.
  • RUN - Запуск каманд.
  • ВЫКРЫЦЬ - Настройка порта.
  • ENTRYPOINT - Указанне выкананай каманды.

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, я, у левай частцы пары 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. У якасці сервера DitigalOcean.

Трэба адзначыць, што тут можна карыстацца і іншай камбінацыяй сэрвісаў. Напрыклад, замест 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, будзе выконвацца пры выкананні ўсіх pull-запытаў ва ўсе галінкі рэпазітара, калі толькі не пазначана іншае. Гэта карысная асаблівасць, бо яна азначае, што мы можам тэставаць увесь код, які паступае ў рэпазітар. Гэта дазваляе ведаць аб тым, ці гатовы код да запісу ў галінку. master, і ці не парушыць ён працэс зборкі праекта. У гэтай глабальнай канфігурацыі я ўсталёўваю ўсё лакальна, запускаю сервер распрацоўніка Webpack у фоне (гэта - асаблівасць майго працоўнага працэсу) і выконваю тэсты.

Калі вы хочаце, каб у вашым рэпазітары выводзіліся б значкі са звесткамі аб пакрыцці кода тэстамі, тут вы можаце знайсці кароткую інструкцыю аб выкарыстанні Jest, Travis CI і Coveralls для збору і вываду гэтых звестак.

Такім чынам, вось змесціва файла .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

Тут сканчаюцца тыя дзеянні, якія выконваюцца для ўсіх галін рэпазітара і для pull-запытаў.

▍Разгортванне

Зыходзячы са здагадкі аб тым, што ўсе аўтаматызаваныя тэсты завяршыліся паспяхова, мы, што рабіць неабавязкова, можам разгарнуць код на прадакшн-серверы. Бо мы жадаем рабіць гэта толькі для кода з галінкі. 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. Я, для ўстаноўкі Docker, выкарыстоўвала Ubuntu 18.04, таму вы, калі таксама карыстаецеся 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

Крыніца: habr.com

Дадаць каментар