V tomto článku sa pomocou , , a organizuje bezproblémové nasadenie webovej aplikácie. je technika, ktorá umožňuje okamžité aktualizovanie aplikácie, bez odmietania akýchkoľvek požiadaviek. Je to jedna zo stratégií zero downtime deployment a najlepšie sa hodí pre aplikácie s jedným inštancom, ale s možnosťou uložiť vedľa druhý, pripravený na prácu inštanc.
Predstavte si, že máte webovú aplikáciu, s ktorou aktívne pracuje množstvo klientov, a nemôže si dovoliť na pár sekúnd prerušiť činnosť. A vy veľmi potrebujete zaviesť aktualizáciu knižnice, opravu chyby alebo novú skvelú funkciu. V bežnej situácii by bolo potrebné zastaviť aplikáciu, nahradiť ju a znovu spustiť. V prípade Dockeru je možné najprv nahradiť a potom reštartovať, ale aj tak bude obdobie, počas ktorého nebudú požiadavky na aplikáciu spracované, keďže aplikácii zvyčajne treba nejaký čas na prvotné načítanie. A čo ak sa spustí, ale nebude funkčná? Takúto úlohu poďme vyriešiť minimálnymi prostriedkami a maximálne elegantne.
DISCLAIMER: Väčšina článku je prezentovaná v experimentálnom formáte — vo forme záznamu konzolovej relácie. Dúfam, že to nebude príliš ťažké na pochopenie a tento kód sám seba dokumentuje v dostatočnej miere. Pre atmosféru si predstavte, že to nie sú len kódové útržky, ale papier z 'železného' teletajpu.
Zaujímavé techniky, ktoré sa ťažko hľadajú len čítaním kódu, sú popísané na začiatku každého oddielu. Ak niečo nebude jasné — hľadajte a kontrolujte v (našťastie, opäť funguje, po odblokovaní Telegramu). Ak sa niečo nedá nájsť — pýtajte sa v komentároch. S radosťou doplním príslušný oddiel 'Zaujímavé techniky'.
Poďme na to.
$ mkdir blue-green-deployment && cd $_Služba
Vytvoríme pokusnú službu a umiestnime ju do kontajnera.
Zaujímavé techniky
cat < file-name( + ) — spôsob, ako vytvoriť viacriadkový súbor jednou príkazom. Všetko, čo bash prečíta z/dev/stdinpo tejto riadke a až do riadkuEOFbude zapísané dofile-name.wget -qO- URL() — vypísať získaný dokument cez HTTP do/dev/stdout(rovnako akocurl URL).
Tlač
Úmyselne prerušujem snippety, aby som zahrnul zvýraznenie pre Python. Na konci bude ešte jedna takáto časť. Považujte to za úpravy papiera na odovzdanie do oddelenia zvýrazňovania (kde kód ručne zafarbovali zvýrazňovačmi), a potom tieto úseky znovu prilepili.
$ cat < uptimer.pyfrom http.server import BaseHTTPRequestHandler, HTTPServer
from time import monotonic
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} beží už {t:3.1f} sekúnd.</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} (načítava sa za {loading_seconds} sek.) spustené.')
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 (nahráva sa za 10 sekúnd) spustený.
$ wget -qSO- http:\/\/localhost:8080
HTTP\/1.0 503 Služba nedostupná
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>Uptimer v1.0 beží 15,4 sekundy.</h2>
$ docker rm --force uptimer
uptimerReverzný proxy server
Aby naše aplikácie mali možnosť bez problémov sa zmeniť, je potrebné, aby pred nimi bola nejaká entita, ktorá skryje ich výmenu. Môže to byť webový server. v . Reverzný proxy server je umiestnený medzi klientom a aplikáciou. Prijíma požiadavky od klientov a presmerováva ich do aplikácie, a odpovede aplikácie posiela klientom.
Aplikáciu a reverzný proxy server môžeme spojiť v prostredí Docker pomocou . Takže kontajneru s aplikáciou ani nemusíte otvorene priraďovať port na hostiteľskom systéme, čo umožňuje maximálne izolovať aplikáciu od externých hrozieb.
Ak bude reverzný proxy server bežať na inom hostiteľovi, budete musieť vzdať docker network a prepojiť aplikáciu s reverzným proxy serverom prostredníctvom siete hostiteľa, priradením portu aplikácie parametrom --publish, ako pri prvom spustení a ako pri reverznom proxy serveri.
Reverzný proxy server spustíme na porte 80, pretože to je tá entita, ktorá by mala počúvať na externé požiadavky. Ak je port 80 na vašom testovacom hostiteľovi obsadený, zmeňte parameter --publish 80:80 na --publish ANY_FREE_PORT:80.
Zaujímavé techniky
- „V docker sieťach, ktoré vytvoril používateľ, môžu byť kontajnery spojené nielen podľa IP adresy. Názov kontajnera sa tiež prekladá na jeho IP adresu“ (, bod 5 docker kódexu).
Tlač
$ 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>Uptimer v1.0 beží 11,5 sekundy.</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.…" pred 27 sekundami Beží 25 sekúnd 0.0.0.0:80->80\/tcp reverse-proxy
a1105f1b583d uptimer "python -u .\/app.py" pred asi minútou Beží asi minútu 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: signal process started
$ wget -qSO- http://localhost
HTTP/1.1 200 OK
Server: nginx/1.19.0
Date: So, 22 Aug 2020 19:56:24 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
<h2>Uptimer v1.0 beží 104,1 sekundy.</h2>Bezproblémové nasadenie
Nasadíme novú verziu aplikácie (s dvojnásobným zlepšením štartovacej výkonnosti) a pokúsime sa ju bezproblémovo nasadiť.
Zaujímavé techniky
echo 'my text' | docker exec -i my-container sh -c 'cat > /my-file.txt'— Zapísať textmy textdo súboru/my-file.txtv rámci kontajneramy-container.cat > /my-file.txt— Zapísať do súboru obsah štandardného vstupu/dev/stdin.
Tlač
$ sed -i "s/app_version = 1/app_version = 2/" uptimer.py
$ docker build --tag uptimer .
Sending build context to Docker daemon 39.94kB
Step 1/4 : FROM python:alpine
---> 8ecf5a48c789
Step 2/4 : EXPOSE 8080
---> Using cache
---> cf92d174c9d3
Step 3/4 : COPY uptimer.py app.py
---> 3eca6a51cb2d
Step 4/4 : CMD [ "python", "-u", ".\/app.py" ]
---> Running in 8f13c6d3d9e7
Removing intermediate container 8f13c6d3d9e7
---> 1d56897841ec
Successfully built 1d56897841ec
Successfully tagged uptimer:latest
$ docker run --detach --rm --name uptimer_BLUE --network web-gateway uptimer
96932d4ca97a25b1b42d1b5f0ede993b43f95fac3c064262c5c527e16c119e02
$ docker logs uptimer_BLUE
Uptimer v2.0 (naštartuje za 5 sekúnd) začal.
$ docker run --rm --network web-gateway alpine wget -qO- http://uptimer_BLUE:8080
<h2>Uptimer v2.0 beží už 23,9 sekundy.</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: signal process started
$ wget -qO- http://localhost
<h2>Uptimer v2.0 beží už 63,4 sekundy.</h2>
$ docker rm -f uptimer
uptimer
$ wget -qO- http://localhost
<h2>Uptimer v2.0 beží už 84,8 sekundy.</h2>
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
96932d4ca97a uptimer "python -u .\/app.py" Pred minútou Beží približne minútu 8080/tcp uptimer_BLUE
80695a822c19 nginx:alpine "\/docker-entrypoint.…" Pred 8 minútami Beží 8 minút 0.0.0.0:80->80/tcp reverse-proxyV tejto fáze sa obraz vybuduje priamo na serveri, čo si vyžaduje, aby tam boli zdrojové kódy aplikácie a tiež zaťažuje server zbytočnou prácou. Nasledujúcim krokom bude vyčlenenie procesu vytvárania obrazu na samostatný stroj (napríklad do CI systému) s následným odovzdaním na server.
Prenos obrazov
Žiaľ, prenášať obrazy z localhost na localhost nemá zmysel, takže túto časť môžete preskúmať len s dvoma hostiteľmi s Dockerom. Pri minimálnych nastaveniach to vyzerá asi takto:
$ ssh production-server docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
$ docker image save uptimer | ssh production-server 'docker image load'
Načítaný obraz: uptimer:latest
$ ssh production-server docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
uptimer latest 1d56897841ec pred 5 minútami 78.9MBTím docker save ukladá dáta obrazu do archívu .tar, čo znamená, že váži približne 1.5-krát viac, ako by mohol vážiť v komprimovanej podobe. Tak to teda skomprimujme v mene úspory času a dátového toku:
$ docker image save uptimer | gzip | ssh production-server 'zcat | docker image load'
Načítaný obraz: uptimer:latestA ešte, môžete sledovať proces prenášania (pravda, pre to potrebujete externú utilitu):
$ docker image save uptimer | gzip | pv | ssh production-server 'zcat | docker image load'
25,7MiB 0:01:01 [ 425KiB/s] [ ]
Načítaný obraz: uptimer:latestRada: Ak potrebujete pre pripojenie k serveru cez SSH množstvo parametrov, možno nepoužívate súbor
~/.ssh/config.
Prenos obrazu cez docker image save/load — to je najminimalistickejšia metóda, ale nie jediná. Existujú aj ďalšie:
- Container Registry (štandard v odbore).
- Pripojiť sa k Docker daemonu servera z iného hostiteľa:
- Premenná prostredia
DOCKER_HOST. - Parametr príkazového riadku
-Halebo--hostnástrojadocker-compose. docker context
- Premenná prostredia
Druhý spôsob (s tromi variantami jeho realizácie) je dobre popísaný v článku .
deploy.sh
Teraz všetko, čo sme robili ručne, zbalíme do jedného skriptu. Začneme s funkciou na najvyššej úrovni a potom sa pozrieme na ostatné, ktoré ju používajú.
Zaujímavé techniky
${parameter?err_msg}— jedno z kúziel bash-magic (aka ). Akparameternie je zadaný, vypíšeerr_msga výjde s kódom 1.docker --log-driver journald— predvolene je ovládač logovania dockera textový súbor bez akejkoľvek rotácie. S takým prístupom rýchlo zaplnia logy celý disk, takže pre produkčné prostredie je potrebné zmeniť ovládač na inteligentnejší.
Skript nasadenia
deploy() {
local usage_msg="Použitie: ${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 "Nasadzujem '$NEW' miesto '$OLD'..."
docker run
--detach
--restart always
--log-driver journald
--name $NEW
--network web-gateway
$image_name || return 3
echo "Kontajner spustený. Kontrolujem zdravie..."
for i in {1..20}
do
sleep 1
if get-service-status $image_name $new_slot
then
echo "Nová '$NEW' služba vyzerá byť v poriadku. Prepínam hlavy..."
sleep 2 # Zabezpečte, aby bola služba pripravená
set-active-slot $image_name $new_slot || return 4
echo "'$NEW' služba je aktívna!"
sleep 2 # Zabezpečte, aby všetky požiadavky boli spracované
echo "Zabíjam '$OLD'..."
docker rm -f $OLD
docker image prune -f
echo "Nasadenie úspešné!"
return 0
fi
echo "Nová '$NEW' služba ešte nie je pripravená. Čakanie ($i)..."
done
echo "Nová '$NEW' služba sa nespustila, zabíjam ju. Nasadenie zlyhalo T_T"
docker rm -f $NEW
return 5
}Použité funkcie:
ensure-reverse-proxy— Zabezpečuje, že reverzní proxy funguje (užitočné pre prvé nasadenie)get-active-slot service_name— Určuje, ktorý slot je momentálne aktívny pre zadanú službu (BLUEaleboGREEN)get-service-status service_name deployment_slot— Určuje, či je služba pripravená na spracovanie prichádzajúcich požiadaviekset-active-slot service_name deployment_slot— Zmení konfiguráciu nginx v kontajneri reverznej proxy
Po poriadku:
ensure-reverse-proxy() {
is-container-up reverse-proxy && return 0
echo "Nasazujem reverse-proxy..."
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?"Použitie: ${FUNCNAME[0]} meno_kontejnera"}
[ -n "$(docker ps -f name=${container} -q)" ]
return $?
}
get-active-slot() {
local service=${1?"Použitie: ${FUNCNAME[0]} meno_služby"}
if is-container-up ${service}_BLUE && is-container-up ${service}_GREEN; then
echo "Zistená kolízia! Zastavujem ${service}_GREEN..."
docker rm -f ${service}_GREEN
return 0 # BLUE
fi
if is-container-up ${service}_BLUE && ! is-container-up ${service}_GREEN; then
return 0 # BLUE
fi
if ! is-container-up ${service}_BLUE; then
return 1 # GREEN
fi
}
get-service-status() {
local usage_msg="Použitie: ${FUNCNAME[0]} meno_služby deployment_slot"
local service=${1?usage_msg}
local slot=${2?$usage_msg}
case $service in
# Pridajte špecifické cesty pre healthcheck pre vaše služby tu
*) local health_check_port_path=":8080/" ;;
esac
local health_check_address="http://${service}_${slot}${health_check_port_path}"
echo "Žiadam '$health_check_address' v rámci 'web-gateway' docker siete:"
docker run --rm --network web-gateway alpine
wget --timeout=1 --quiet --server-response $health_check_address
return $?
}
set-active-slot() {
local usage_msg="Použitie: ${FUNCNAME[0]} meno_služby 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
}Funkcia get-active-slot vyžaduje malé vysvetlenie:
Prečo vracia číslo a nie vypisuje reťazec?
Aj tak v volajúcej funkcii kontrolujeme výsledok jej práce, a overovať exit kód prostriedkami bash je oveľa jednoduchšie ako reťazec. Navyše, získať z nej reťazec je veľmi jednoduché:
get-active-slot service && echo BLUE || echo GREEN.
Stačí na rozlíšenie všetkých stavov tri podmienky?
Dve stačia, posledná tu je len pre úplnosť, aby sa nemuselo písať else.
Zostala neurčená len funkcia, ktorá vracia konfigurácie nginx: get-nginx-config service_name deployment_slot. Podobne ako s healthcheckom, tu je možné nastaviť akúkoľvek konfiguráciu pre akúkoľvek službu. Zaujímavé je len, cat <<- EOF, čo umožňuje odstrániť všetky taby na začiatku. Pravda, cena za dobrou formátovanie — zmiešané taby s medzerami, čo sa dnes považuje za veľmi zlý tón. Ale bash núti taby, a v konfigurácii nginx by tiež nebolo zlé mať normálne formátovanie. Skrátka, tu sa zmiešanie tabov s medzerami zdá byť naozaj najlepším riešením spomedzi najhorších. Avšak v nižšie uvedenom snippete to neuvidíte, pretože habr „robí dobre“, mení všetky taby na 4 medzery a robí neplatný EOF. .
Aby som sa dvakrát nezastavoval, hneď poviem o
cat << 'EOF', ktorý sa ešte objaví neskôr. Ak napíšete jednoduchocat << EOF, tak v rámci heredocu prebieha interpolácia reťazca (rozpracúvajú sa premenné ($foo), volania príkazov ($(bar)) atď.), a ak uzatvoríte znak konca dokumentu do jednoduchých úvodzoviek, interpolácia sa vypne a symbol$sa vypíše tak, ako je. To, čo potrebujete na vloženie skriptu do iného skriptu.
get-nginx-config() {
local usage_msg="Použitie: ${FUNCNAME[0]} názov_služby nasadenie_slot"
local service=${1?$usage_msg}
local slot=${2?$usage_msg}
[ "$slot" == BLUE ] || [ "$slot" == GREEN ] || return 1
local container_name=${service}_${slot}
case $service in
# Pridajte konkrétne nginx konfigurácie pre vaše služby tu
*) nginx-config-simple-service $container_name:8080 ;;
esac
}
nginx-config-simple-service() {
local usage_msg="Použitie: ${FUNCNAME[0]} proxy_pass"
local proxy_pass=${1?$usage_msg}
cat << EOF
server {
listen 80;
location / {
proxy_pass http://$proxy_pass;
}
}
EOF
}To je celý skript. A toto na stiahnutie cez wget alebo curl.
Vykonávanie parametrových skriptov na vzdialenom serveri
Prišiel čas zaklopať na cieľový server. Tentoraz localhost sa úplne hodí:
$ ssh-copy-id localhost
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
himura@localhost's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'localhost'"
and check to make sure that only the key(s) you wanted were added.Napísali sme skript na nasadenie, ktorý prenáša predom zostavený obraz na cieľový server a bezproblémovo nahrádza kontajner služby, ale ako ho vykonať na vzdialenom stroji? Skript má argumenty, pretože je univerzálny a môže nasadzovať viacero služieb pre jeden reverzný proxy (v konfiguráciách Nginx môžeme vyriešiť, na akú url aká služba bude). Skript nemožno uchovávať na serveri, pretože v takom prípade ho nebudeme môcť automaticky aktualizovať (s cieľom opravy chýb a pridávania nových služieb) a celkovo, stav = zlo.
Riešenie 1: Takže uchovávať skript na serveri, ale každýkrát ho kopírovať cez scp. Potom sa pripojiť cez ssh a vykonať skript s potrebnými argumentmi.
Nevýhody:
- Dve akcie namiesto jednej
- Miesta, kam kopírujete, nemusí existovať, alebo nemusí byť možné k nemu získať prístup, alebo skript sa môže vykonávať v čase nahradenia.
- Odporúča sa po sebe upratať (vymazať skript).
- Už tri akcie.
Riešenie 2:
- V skripte mať len definície funkcií a vôbec nič nespúšťať,
- S pomocou
seddodať na koniec volanie funkcie. - Poslať to všetko priamo do shh cez pipe (
|)
Výhody:
- Skutočne bezstavový
- Žiadne boilerplate entity
- Cítim sa skvele
Ale bez Ansible. Áno, už je to vymyslené. Áno, bicykel. Pozrite sa, aký jednoduchý, elegantný a minimalistický bicykel je:
$ 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
Pripojenie na localhost...
Hurá! Funkcia 'deploy' sa vykonáva na 'hut' s argumentom 'magic-porridge-pot'Avšak nemôžeme si byť istí, že na vzdialenom hoste je adekvátny bash, takže na začiatok pridáme malú overovaciu kontrolu (to je na mieste ):
if [ "$SHELL" != "/bin/bash" ]
then
echo "Shell '$SHELL' nie je podporovaný 'deploy.sh'. Nastavte shell '/bin/bash' pre '$USER@$HOSTNAME'."
exit 1
fiA teraz všetko naozaj:
$ 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
Odosielanie komprimovaného obrazu 'uptimer' na 'localhost' prostredníctvom ssh...
Načítaný obraz: uptimer:latest
Pripojenie k 'localhost' prostredníctvom ssh na bezproblémové nasadenie 'uptimer'...
Nasadenie 'uptimer_GREEN' namiesto 'uptimer_BLUE'...
06f5bc70e9c4f930e7b1f826ae2ca2f536023cc01e82c2b97b2c84d68048b18a
Kontajner bol spustený. Kontrola zdravia...
Žiadosť o 'http://uptimer_GREEN:8080/' v rámci docker siete 'web-gateway':
HTTP/1.0 503 Služba nedostupná
wget: server vrátil chybu: HTTP/1.0 503 Služba nedostupná
Nová služba 'uptimer_GREEN' ešte nie je pripravená. Čakanie (1)...
Žiadosť o 'http://uptimer_GREEN:8080/' v rámci docker siete 'web-gateway':
HTTP/1.0 503 Služba nedostupná
wget: server vrátil chybu: HTTP/1.0 503 Služba nedostupná
Nová služba 'uptimer_GREEN' ešte nie je pripravená. Čakanie (2)...
Žiadosť o 'http://uptimer_GREEN:8080/' v rámci docker siete 'web-gateway':
HTTP/1.0 200 OK
Server: BaseHTTP/0.6 Python/3.8.3
Dátum: So, 22. augusta 2020 20:15:50 GMT
Typ obsahu: text/html
Nová služba 'uptimer_GREEN' sa javí byť OK. Prechádzam na hlavy...
nginx: syntax konfigurácie súboru /etc/nginx/nginx.conf je v poriadku
nginx: test konfigurácie súboru /etc/nginx/nginx.conf bol úspešný
2020/08/22 20:15:54 [oznámenie] 97#97: proces signálu bol spustený
Služba 'uptimer_GREEN' je živá!
Zabíjam 'uptimer_BLUE'...
uptimer_BLUE
Celkový uvoľnený priestor: 0B
Nasadenie úspešné!Teraz môžete otvoriť v prehliadači, spustiť nasadenie ešte raz a uistiť sa, že prebieha bezproblémovo aktualizovaním stránky klávesom F5 počas nasadenia.
Nezabúdajme upratať po práci :3
$ docker rm -f uptimer_GREEN reverse-proxy
uptimer_GREEN
reverse-proxy
$ docker network rm web-gateway
web-gateway
$ cd ..
$ rm -r blue-green-deploymentZdroj: habr.com
