Ebben a cikkben segítségével , , és sorozatmentes telepítést valósítunk meg egy webalkalmazás számára. — egy technika, amely lehetővé teszi az alkalmazás azonnali frissítését anélkül, hogy bármilyen kérést elutasítanánk. Ez az egyik stratégiája a nulladik leállási idővel történő telepítésnek, és legjobban azokhoz az alkalmazásokhoz illik, amelyeknek egy példánya van, de van lehetőség egy második, működő példány bevezetésére.
Tegyük fel, hogy van egy webalkalmazás, amelyet sok ügyfél aktívan használ, és amelyet semmilyen körülmények között nem lehet néhány másodpercre leállítani. Önnek nagyon szüksége van egy könyvtár frissítésére, egy hiba javítására vagy egy új, menő funkció bevezetésére. Normális helyzetben meg kell állítani az alkalmazást, kicserélni és újraindítani. Docker esetén először kicserélheti, majd újraindíthatja, de ennek ellenére létezik egy időszak, amikor a kérések nem lesznek feldolgozva, mert az alkalmazásnak általában időre van szüksége az első betöltéshez. Mi van, ha elindul, de nem működik? Ilyen feladat elé nézünk, próbáljuk meg a lehető legkevesebb eszközzel és a lehető legkifinomultabban megoldani.
FELHÍVÁS: A cikk nagy része kísérleti formátumban van, konzolos munkamenet felvételében. Remélem, nem lesz túl nehéz ezt követni, és ez a kód kellőképpen dokumentálja önmagát. Az élmény kedvéért képzelje el, hogy ez nem csupán kódrészletek, hanem egy "acéltípusú" teletávirat papírja.
Érdekes technikák, amelyeket nehéz csak a kód olvasásával megtalálni, minden szakasz elején szerepelnek. Ha valami nem világos, kérdezzen a (szerencsére, ismét működik a Telegram feloldása miatt). Amit nem talál meg a Google-ban, kérdezzen a kommentekben. Szívesen kiegészítem az "Érdekes technikák" című szakaszt.
Kezdjük.
$ mkdir blue-green-deployment && cd $_Szolgáltatás
Készítünk egy tesztszolgáltatást, és egy konténerbe helyezzük.
Érdekes technikák
cat < file-name( + ) — egy módja annak, hogy több soros fájlt hozzunk létre egy parancssal. Minden, amit a bash olvas a/dev/stdine sor után és azEOFsor előtt, az afile-name.wget -qO- URL() — a HTTP-n keresztül kapott dokumentum megjelenítése/dev/stdout(analógcurl URL).
Kinyomtatás
Kifejezetten megszakítom a snippetet, hogy kiemelést tegyek a Python számára. A végén még egy ilyen darab lesz. Tekintse úgy, hogy ezeken a helyeken a papírt vágták el a kiemelés osztály számára (ahol a kódot manuálisan színeztek kiemelőkkel), majd ezeket a darabokat vissza ragasztották.
$ cat < uptimer.pya http.server importálásához használja a BaseHTTPRequestHandler-t és a HTTPServer-t
az idő importálásához használja a monotonic-t
app_version = 1
app_name = f'Uptimer v{app_version}.0'
loading_seconds = 15 - app_version * 5
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '':
try:
t = monotonic() - server_start
if t < loading_seconds:
self.send_error(503)
else:
self.send_response(200)
self.send_header('Content-Type', 'text/html')
self.end_headers()
response = f'<h2>{app_name} {t:3.1f} másodpercig fut.</h2>n'
self.wfile.write(response.encode('utf-8'))
except Exception:
self.send_error(500)
else:
self.send_error(404)
httpd = HTTPServer(('', 8080), Handler)
server_start = monotonic()
print(f'{app_name} (betöltési idő: {loading_seconds} sec.) indítva.)
httpd.serve_forever()EOF
$ cat << EOF > Dockerfile
FROM python:alpine
EXPOSE 8080
COPY uptimer.py app.py
CMD [ "python", "-u", ".\/app.py" ]
EOF
$ docker build --tag uptimer .
Sending build context to Docker daemon 39.42kB
Step 1\/4 : FROM python:alpine
---> 8ecf5a48c789
Step 2\/4 : EXPOSE 8080
---> Using cache
---> cf92d174c9d3
Step 3\/4 : COPY uptimer.py app.py
---> a7fbb33d6b7e
Step 4\/4 : CMD [ "python", "-u", ".\/app.py" ]
---> Running in 1906b4bd9fdf
Removing intermediate container 1906b4bd9fdf
---> c1655b996fe8
Successfully built c1655b996fe8
Successfully tagged uptimer:latest
$ docker run --rm --detach --name uptimer --publish 8080:8080 uptimer
8f88c944b8bf78974a5727070a94c76aa0b9bb2b3ecf6324b784e782614b2fbf
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8f88c944b8bf uptimer "python -u .\/app.py" 3 seconds ago Up 5 seconds 0.0.0.0:8080->8080\/tcp uptimer
$ docker logs uptimer
Uptimer v1.0 (10 másodperc alatt töltődik) elindult.
$ wget -qSO- http:\/\/localhost:8080
HTTP\/1.0 503 Szolgáltatás nem elérhető
Server: BaseHTTP\/0.6 Python\/3.8.3
Date: Sat, 22 Aug 2020 19:52:40 GMT
Connection: close
Content-Type: text\/html;charset=utf-8
Content-Length: 484
$ wget -qSO- http:\/\/localhost:8080
HTTP\/1.0 200 OK
Server: BaseHTTP\/0.6 Python\/3.8.3
Date: Sat, 22 Aug 2020 19:52:45 GMT
Content-Type: text\/html
<h2>Az Uptimer v1.0 15,4 másodperc óta fut.</h2>
$ docker rm --force uptimer
uptimerFordított proxy
Ahhoz, hogy az alkalmazásunk észrevétlenül megváltozhasson, szükség van egy másik entitásra előtte, amely eltakarja a cseréjét. Ez lehet egy webkiszolgáló. be. . A fordított proxy a kliens és az alkalmazás között helyezkedik el. Elfogadja a kliens által indított kéréseket, és átirányítja őket az alkalmazás felé, míg az alkalmazás válaszait a kliensek felé továbbítja.
Az alkalmazást és a fordított proxy-t összekapcsolhatjuk a Docker segítségével . Így az alkalmazás konténerének még portot sem kell megnyitnia a hoszt rendszeren; ez lehetővé teszi az alkalmazás maximális izolálását a külső fenyegetésektől.
Ha a fordított proxy másik hoszton él, el kell hagyni a docker network-öt, és összekapcsolni az alkalmazást a fordított proxy-val a hoszthálózaton keresztül, a port megnyitásával. alkalmazás paraméterrel --publish, mint az első indításnál és a fordított proxy esetében.
A fordított proxy-t a 80-as porton fogjuk futtatni, mert ez az a entitás, amelynek hallgatnia kell a külső forgalomra. Ha a 80-as port a teszt hoszton foglalt, módosítsa a paramétert. --publish 80:80 Gyorsan emlékezzünk vissza, hogyan működik a moduláris aritmetika. Az óra már egy ismert koncepció. Az órák használata --publish ANY_FREE_PORT:80.
Érdekes technikák
- A "Felhasználó által létrehozott docker-hálózatokon a konténerekkel nemcsak IP-címen keresztül lehet kapcsolatba lépni. A konténer neve szintén feloldódik az IP-címére" (, a docker kódex 5. pontja).
Kinyomtatás
$ docker network create web-gateway
5dba128fb3b255b02ac012ded1906b7b4970b728fb7db3dbbeccc9a77a5dd7bd
$ docker run --detach --rm --name uptimer --network web-gateway uptimer
a1105f1b583dead9415e99864718cc807cc1db1c763870f40ea38bc026e2d67f
$ docker run --rm --network web-gateway alpine wget -qO- http://uptimer:8080
<h2>Az Uptimer v1.0 már 11,5 másodperce fut.</h2>
$ docker run --detach --publish 80:80 --network web-gateway --name reverse-proxy nginx:alpine
80695a822c19051260c66bf60605dcb4ea66802c754037704968bc42527bf120
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
80695a822c19 nginx:alpine "\/docker-entrypoint.…" 27 másodperce Futtatás alatt 25 másodperce 0.0.0.0:80->80\/tcp reverse-proxy
a1105f1b583d uptimer "python -u .\/app.py" Körülbelül egy perce Futtatás alatt Körülbelül egy perce 8080\/tcp uptimer
$ cat << EOF > uptimer.conf
server {
listen 80;
location \/ {
proxy_pass http://uptimer:8080;
}
}
EOF
$ docker cp .\/uptimer.conf reverse-proxy:\/etc\/nginx\/conf.d\/default.conf
$ docker exec reverse-proxy nginx -s reload
2020\/06\/23 20:51:03 [notice] 31#31: process startelt
$ wget -qSO- http://localhost
HTTP\/1.1 200 OK
Server: nginx\/1.19.0
Date: Sat, 22 Aug 2020 19:56:24 GMT
Content-Type: text\/html
Transfer-Encoding: chunked
Connection: keep-alive
<h2>Az Uptimer v1.0 már 104,1 másodperce fut.</h2>Zökkenőmentes telepítés
Ki fogjuk adni az alkalmazás új verzióját (dupla teljesítménynöveléssel az indítási teljesítményben), és megpróbáljuk zökkenőmentesen telepíteni.
Érdekes technikák
echo 'my text' | docker exec -i my-container sh -c 'cat > /my-file.txt'— Írja be a szövegetmy texta fájlba/my-file.txta konténeren belülmy-container.cat > /my-file.txt— Írja be a szabványos bemenet tartalmát a fájlba/dev/stdin.
Kinyomtatás
$ sed -i "s/app_version = 1/app_version = 2/" uptimer.py
$ docker build --tag uptimer .
A build context sending to Docker daemon 39.94kB
Step 1/4 : FROM python:alpine
---> 8ecf5a48c789
Step 2/4 : EXPOSE 8080
---> Cache használata
---> cf92d174c9d3
Step 3/4 : COPY uptimer.py app.py
---> 3eca6a51cb2d
Step 4/4 : CMD [ "python", "-u", ".\/app.py" ]
---> Futtatás 8f13c6d3d9e7
Közbenső konténer eltávolítása 8f13c6d3d9e7
---> 1d56897841ec
Sikeresen építve 1d56897841ec
Sikeresen címkézve uptimer:latest
$ docker run --detach --rm --name uptimer_BLUE --network web-gateway uptimer
96932d4ca97a25b1b42d1b5f0ede993b43f95fac3c064262c5c527e16c119e02
$ docker logs uptimer_BLUE
Uptimer v2.0 (betöltés 5 sec.) elindult.
$ docker run --rm --network web-gateway alpine wget -qO- http://uptimer_BLUE:8080
<h2>Az Uptimer v2.0 23,9 másodperce fut.</h2>
$ sed s/uptimer/uptimer_BLUE/ uptimer.conf | docker exec --interactive reverse-proxy sh -c 'cat > /etc/nginx/conf.d/default.conf'
$ docker exec reverse-proxy cat /etc/nginx/conf.d/default.conf
server {
listen 80;
location / {
proxy_pass http://uptimer_BLUE:8080;
}
}
$ docker exec reverse-proxy nginx -s reload
2020/06/25 21:22:23 [notice] 68#68: jelzésfolyamat elindult
$ wget -qO- http://localhost
<h2>Az Uptimer v2.0 63,4 másodperce fut.</h2>
$ docker rm -f uptimer
uptimer
$ wget -qO- http://localhost
<h2>Az Uptimer v2.0 84,8 másodperce fut.</h2>
$ docker ps
KONTÉNER AZONOSÍTÓ KÉP PARANCS LÉTREHOZVA ÁLLAPOT PORTOK NEVEK
96932d4ca97a uptimer "python -u .\/app.py" Körülbelül egy perce Fenn Körülbelül egy perce 8080/tcp uptimer_BLUE
80695a822c19 nginx:alpine "\/docker-entrypoint.…" 8 perce Fenn 8 perce 0.0.0.0:80->80/tcp reverse-proxyEzen a ponton a kép közvetlenül a szerveren készül, amely megköveteli, hogy az alkalmazás forrásai ott legyenek, és felesleges munkát ad a szervernek. A következő lépés egy külön gépre (például CI-rendszerbe) történő képkészítési folyamat kiemelése, majd ennek átköltöztetése a szerverre.
Képek átköltöztetése
Sajnálom, de a localhostról a localhostra történő képfeltöltésnek nincs értelme, így ezt a részt csak akkor tudod kipróbálni, ha két docker hostod van. Minimális beállítások mellett ez körülbelül így néz ki:
$ ssh production-server docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
$ docker image save uptimer | ssh production-server 'docker image load'
Loaded image: uptimer:latest
$ ssh production-server docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
uptimer latest 1d56897841ec 5 minutes ago 78.9MBA parancs docker save a képadatokat egy .tar archívumba menti, tehát körülbelül 1,5-ször nagyobb lesz, mint amennyi lehetne tömörítve. Akkor tömörítsük, hogy időt és forgalmat takarítsunk meg:
$ docker image save uptimer | gzip | ssh production-server 'zcat | docker image load'
Loaded image: uptimer:latestA folyamat megfigyelésére is van lehetőség (bár ehhez külső segédprogram szükséges):
$ docker image save uptimer | gzip | pv | ssh production-server 'zcat | docker image load'
25,7MiB 0:01:01 [ 425KiB/s] [ ]
Loaded image: uptimer:latestTipp: Ha az SSH-kapcsolathoz sok paraméterre van szükséged, lehet, hogy nem használod a fájlt
~/.ssh/config.
Kép átvitele a docker image save/load — ez a legminimalista módszer, de nem az egyetlen. Más módszerek is léteznek:
- Container Registry (iparági szabvány).
- Csatlakozás a server docker daemonhoz egy másik hostból:
- Környezeti változó
DOCKER_HOST. - Parancssori paraméter
-Hvagy--hosteszközdocker-compose. docker context
- Környezeti változó
A második módszer (három megvalósítási lehetőséggel) jól le van írva a cikkben .
deploy.sh
Most mindazt, amit kézzel csináltunk, összevonjuk egy scriptbe. Kezdjük a legfelső szintű funkcióval, majd nézzük meg a többi, benne használtat.
Érdekes technikák
${parameter?err_msg}— a bash-mágia egyik varázsigéje (aka ). Ha aparameternincs megadva, akkor kiírjaerr_msgés kilép 1-es kóddal.docker --log-driver journald— alapértelmezés szerint a docker naplózásának meghajtója egy szöveges fájl bármilyen forgatás nélkül. Ezzel a megközelítéssel a naplók gyorsan elfoglalják az egész lemezt, ezért produkciós környezetben a meghajtót intelligensebbre kell váltani.
Telepítési script
deploy() {
local usage_msg="Használat: ${FUNCNAME[0]} image_name"
local image_name=${1?$usage_msg}
ensure-reverse-proxy || return 2
if get-active-slot $image_name
then
local OLD=${image_name}_BLUE
local new_slot=GREEN
else
local OLD=${image_name}_GREEN
local new_slot=BLUE
fi
local NEW=${image_name}_${new_slot}
echo "Telepítés '$NEW' helyett '$OLD'..."
docker run
--detach
--restart always
--log-driver journald
--name $NEW
--network web-gateway
$image_name || return 3
echo "Konténer elindítva. Egészség ellenőrzése..."
for i in {1..20}
do
sleep 1
if get-service-status $image_name $new_slot
then
echo "Az új '$NEW' szolgáltatás rendben van. Fejváltás..."
sleep 2 # Gondoskodik arról, hogy a szolgáltatás készen álljon
set-active-slot $image_name $new_slot || return 4
echo "A '$NEW' szolgáltatás él!"
sleep 2 # Gondoskodik arról, hogy minden kérés feldolgozva legyen
echo "'Killing '$OLD'..."
docker rm -f $OLD
docker image prune -f
echo "Telepítés sikeres!"
return 0
fi
echo "Az új '$NEW' szolgáltatás még nem készen áll. Várakozás ($i)..."
done
echo "Az új '$NEW' szolgáltatás nem indult el, megszüntetve. A telepítés nem sikerült T_T"
docker rm -f $NEW
return 5
}Használt funkciók:
ensure-reverse-proxy— Ellenőrzi, hogy a fordított proxy működik (hasznos az első telepítéshez)get-active-slot service_name— Meghatározza, hogy melyik slot aktív a megadott szolgáltatás számára (BLUEvagyGREEN)get-service-status service_name deployment_slot— Meghatározza, hogy a szolgáltatás készen áll-e bejövő kérések feldolgozásáraset-active-slot service_name deployment_slot— Megváltoztatja az nginx konfigurációt a fordított proxy konténerében
Részletesen:
ensure-reverse-proxy() {
is-container-up reverse-proxy && return 0
echo "Visszapillantó telepítése..."
docker network create web-gateway
docker run
--detach
--restart always
--log-driver journald
--name reverse-proxy
--network web-gateway
--publish 80:80
nginx:alpine || return 1
docker exec --interactive reverse-proxy sh -c "> /etc/nginx/conf.d/default.conf"
docker exec reverse-proxy nginx -s reload
}
is-container-up() {
local container=${1?"Használat: ${FUNCNAME[0]} container_name"}
[ -n "$(docker ps -f name=${container} -q)" ]
return $?
}
get-active-slot() {
local service=${1?"Használat: ${FUNCNAME[0]} service_name"}
if is-container-up ${service}_BLUE && is-container-up ${service}_GREEN; then
echo "Ütközés történt! ${service}_GREEN leállítása..."
docker rm -f ${service}_GREEN
return 0 # KÉK
fi
if is-container-up ${service}_BLUE && ! is-container-up ${service}_GREEN; then
return 0 # KÉK
fi
if ! is-container-up ${service}_BLUE; then
return 1 # ZÖLD
fi
}
get-service-status() {
local usage_msg="Használat: ${FUNCNAME[0]} service_name deployment_slot"
local service=${1?usage_msg}
local slot=${2?$usage_msg}
case $service in
# Adjon meg konkrét egészségellenőrzési útvonalakat a szolgáltatásaihoz itt
*) local health_check_port_path=":8080/" ;;
esac
local health_check_address="http://${service}_${slot}${health_check_port_path}"
echo "'${health_check_address}' címre kérés a 'web-gateway' docker hálózaton:"
docker run --rm --network web-gateway alpine
wget --timeout=1 --quiet --server-response $health_check_address
return $?
}
set-active-slot() {
local usage_msg="Használat: ${FUNCNAME[0]} service_name deployment_slot"
local service=${1?$usage_msg}
local slot=${2?$usage_msg}
[ "$slot" == BLUE ] || [ "$slot" == GREEN ] || return 1
get-nginx-config $service $slot | docker exec --interactive reverse-proxy sh -c "cat > /etc/nginx/conf.d/$service.conf"
docker exec reverse-proxy nginx -t || return 2
docker exec reverse-proxy nginx -s reload
}Funkció get-active-slot kisebb magyarázatra szorul:
Miért ad vissza számot, és miért nem szöveget írásba?
Mindazonáltal a hívó függvényben ellenőrizzük a működésének eredményét, és a bash-beli exit kódot ellenőrizni sokkal egyszerűbb, mint egy szöveget. Ezenkívül, nagyon egyszerű kibővíteni szöveggé:
get-active-slot service && echo BLUE || echo GREEN.
De vajon elegendő három feltétel a különböző állapotok megkülönböztetésére?
Még csupán kettő is elegendő, az utolsó itt csak a teljesség kedvéért van, hogy ne kelljen írni. else.
Csak a nginx konfigurációkat visszaadó függvény maradt meghatározatlanul: get-nginx-config service_name deployment_slot. Hasonlóan a healthcheck-hez, itt bármilyen konfigurációt megadhat bármelyik szolgáltatáshoz. Ami érdekes — csak cat <<- EOF, amely lehetővé teszi, hogy eltávolítsuk az összes tabulát az elején. Az igazság az, hogy a megfelelő formázás ára – a különböző tabok és szóközök keveréke, ami manapság nagyon rossz formának számít. De a bash erőlteti a tabokat, és az nginx konfigurációban is jó lenne, ha megfelelő formázás lenne. Röviden, itt a tabok és szóközök keveréke valóban a legrosszabb megoldás legjobbja. Azonban az alábbi snippetben ezt nem fogja látni, mivel a habr „jól csinálja”, mindent 4 szóközre cserél, és érvénytelen EOF-ot készít. .
Hogy elkerüljük a felesleges ismétlést, azonnal beszélek a
cat << 'EOF', amely még találkozni fog később. Ha csak annyit írsz, hogycat << EOF, akkor a heredoc-on belül a szöveg interpolálódik (kibővülnek a változók ($foo), parancshívások ($(bar)) stb.), azonban ha a dokumentum végét egyes idézőjelek közé zárjuk, akkor az interpoláció ki van kapcsolva, és a karakter$könnyen kibővíthető. Ez pontosan szükséges ahhoz, hogy egy scriptet beleillesszünk egy másik scriptbe.
get-nginx-config() {
local usage_msg="Használat: ${FUNCNAME[0]} szolgáltatás_név telepítési_hely"
local service=${1?$usage_msg}
local slot=${2?$usage_msg}
[ "$slot" == KÉK ] || [ "$slot" == ZÖLD ] || return 1
local container_name=${service}_${slot}
case $service in
# Itt add meg a szolgáltatásaid specifikus nginx konfigurációit
*) nginx-config-simple-service $container_name:8080 ;;
esac
}
nginx-config-simple-service() {
local usage_msg="Használat: ${FUNCNAME[0]} proxy_pass"
local proxy_pass=${1?$usage_msg}
cat << EOF
server {
listen 80;
location / {
proxy_pass http://$proxy_pass;
}
}
EOF
}Ez az egész script. És itt van letöltéshez wget vagy curl segítségével.
Paraméterezett script-ek végrehajtása távoli szerveren
Itt az idő, hogy belépjünk a célszerverre. Most localhost teljesen megfelelő lesz:
$ ssh-copy-id localhost
/usr/bin/ssh-copy-id: INFO: új kulcs(ok)kal próbálkozik a bejelentkezéshez, hogy kiszűrje azokat, amelyek már telepítve vannak
/usr/bin/ssh-copy-id: INFO: 1 kulcs(ok) maradtak telepítésre - ha most megkérdezik, az új kulcsok telepítésére történik
himura@localhost jelszava:
A telepített kulcs(ok) száma: 1
Most próbálj meg bejelentkezni a gépre: "ssh 'localhost'"
és ellenőrizd, hogy csak a kívánt kulcs(ok) lettek-e telepítve.Írtunk egy telepítő szkriptet, amely feltölti az előre összeállított képet a cél szerverre, és zökkenőmentesen kicseréli a szolgáltatás konténerét, de hogyan hajtsuk végre azt távoli gépen? A szkriptnek vannak argumentumai, mivel univerzális, és egyszerre több szolgáltatást is képes telepíteni egy fordított proxy alatt (az nginx konfigurációkkal megoldható, hogy mely URL-hez melyik szolgáltatás tartozik). A szkriptet nem lehet a szerveren tárolni, mert ebben az esetben nem tudjuk automatikusan frissíteni (a hibajavítások és új szolgáltatások hozzáadása érdekében), és egyáltalán, a state = rossz dolog.
Megoldás 1: Mégis tárolni a szkriptet a szerveren, de minden alkalommal átmásolni scp. Ezután csatlakozni ssh és végrehajtani a szkriptet a szükséges argumentumokkal.
Hátrányok:
- Két lépés egy helyett
- A hely, ahová másolsz, lehet, hogy nem létezik, vagy nem lesz hozzáférésed, vagy a szkript végrehajtása történhet a csere pillanatában.
- Ajánlott eltakarítani magad után (törölni a szkriptet).
- Már három lépés.
Megoldás 2:
- A szkriptben csak a függvények definiálását tartani, és egyáltalán semmit nem végrehajtani
- A segítségével
seda függvényhívás végére írni - Mindezt közvetlenül az shh-n át küldeni pipe-on keresztül (
|)
Előnyök:
- Tényleg stateless
- Nincsenek sablon entity-k
- Menőnek lenni
Csak kérlek, Ansible nélkül. Igen, már mindent kitaláltak. Igen, a kerék. Nézd, milyen egyszerű, elegáns és minimalista kerék:
$ cat < deploy.sh#!/bin/bash
usage_msg="Usage: $0 ssh_address local_image_tag"
ssh_address=${1?$usage_msg}
image_name=${2?$usage_msg}
echo "Connecting to '$ssh_address' via ssh to seamlessly deploy '$image_name'..."
( sed "$a deploy $image_name" | ssh -T $ssh_address ) << 'END_OF_SCRIPT'
deploy() {
echo "Yay! The '${FUNCNAME[0]}' function is executing on '$(hostname)' with argument '$1'"
}
END_OF_SCRIPTEOF
$ chmod +x deploy.sh
$ ./deploy.sh localhost magic-porridge-pot
Csatlakozás a localhost-hoz...
Hurrá! A 'deploy' függvény a 'hut'-on fut a 'magic-porridge-pot' argumentummal.Mégsem lehetünk biztosak abban, hogy a távoli hoszton van megfelelő bash, ezért adjunk hozzá egy kis ellenőrzést az elejére (ez a ):
if [ "$SHELL" != "/bin/bash" ]
then
echo "A '$SHELL' shell nem támogatott a 'deploy.sh'-ben. Állíts be egy '/bin/bash' shellt a '$USER@$HOSTNAME'-nek."
exit 1
fiMost pedig minden valódi:
$ docker exec reverse-proxy rm /etc/nginx/conf.d/default.conf
$ wget -qO deploy.sh https://git.io/JUURc
$ chmod +x deploy.sh
$ ./deploy.sh localhost uptimer
Gzipelt képként küldjük az 'uptimer'-t a 'localhost'-ra ssh-n keresztül...
Betöltött kép: uptimer:latest
Kapcsolódás a 'localhost'-hoz ssh-n keresztül az 'uptimer' zökkenőmentes telepítéséhez...
Az 'uptimer_GREEN' telepítése az 'uptimer_BLUE' helyére...
06f5bc70e9c4f930e7b1f826ae2ca2f536023cc01e82c2b97b2c84d68048b18a
A konténer elindult. Egészségellenőrzés folyamatban...
'http://uptimer_GREEN:8080/' kérés a 'web-gateway' docker hálózaton belül:
HTTP/1.0 503 Szolgáltatás nem elérhető
wget: a szerver hibát adott vissza: HTTP/1.0 503 Szolgáltatás nem elérhető
Az új 'uptimer_GREEN' szolgáltatás még nem készen áll. Várakozás (1)...
'http://uptimer_GREEN:8080/' kérés a 'web-gateway' docker hálózaton belül:
HTTP/1.0 503 Szolgáltatás nem elérhető
wget: a szerver hibát adott vissza: HTTP/1.0 503 Szolgáltatás nem elérhető
Az új 'uptimer_GREEN' szolgáltatás még nem készen áll. Várakozás (2)...
'http://uptimer_GREEN:8080/' kérés a 'web-gateway' docker hálózaton belül:
HTTP/1.0 200 Rendben
Szerver: BaseHTTP/0.6 Python/3.8.3
Dátum: 2020. augusztus 22. 20:15:50 GMT
Tartalom típusa: text/html
Az új 'uptimer_GREEN' szolgáltatás rendben van. Fejek váltása...
nginx: a konfigurálási fájl /etc/nginx/nginx.conf szintaktikailag helyes
nginx: konfigurálási fájl /etc/nginx/nginx.conf tesztje sikeres
2020/08/22 20:15:54 [notice] 97#97: jelzés folyamat elindítva
Az 'uptimer_GREEN' szolgáltatás aktív!
Az 'uptimer_BLUE' leállítása...
uptimer_BLUE
Teljesen visszanyert terület: 0B
A telepítés sikeres!Most már megnyithatjuk a böngészőben, újra indíthatjuk a telepítést, és megbizonyosodhatunk róla, hogy zökkenőmentesen zajlik az oldal frissítési folyamatával a telepítés alatt.
Ne felejtsük el kitakarítani a munka után :3
$ docker rm -f uptimer_GREEN reverse-proxy
uptimer_GREEN
reverse-proxy
$ docker network rm web-gateway
web-gateway
$ cd ..
$ rm -r blue-green-deploymentForrás: habr.com
