Ma kēia ʻatikala mākou e hoʻohana ai ke kī, kālepa, ka loea и nginx E hoʻonohonoho mākou i kahi hoʻolālā maʻalahi o ka noi pūnaewele. Polu-'ōmaʻomaʻo hoʻolaha He ʻenehana ia e hiki ai iā ʻoe ke hoʻololi koke i kahi noi me ka hōʻole ʻole i kahi noi hoʻokahi. ʻO ia kekahi o nā hoʻolālā hoʻolālā zero downtime a kūpono loa ia no nā noi me hoʻokahi laʻana, akā ʻo ka hiki ke hoʻouka i kahi lua, mākaukau e holo kokoke.
E ʻōlelo mākou he polokalamu pūnaewele kāu e hana ikaika nei nā mea kūʻai aku, a ʻaʻohe ala e moe ai i lalo no ʻelua kekona. A pono ʻoe e ʻōwili i kahi hoʻolaha waihona, hoʻoponopono bug, a i ʻole kahi hiʻohiʻona hou. Ma kahi kūlana maʻamau, pono ʻoe e hoʻōki i ka noi, hoʻololi a hoʻomaka hou. I ka hihia o docker, hiki iā ʻoe ke hoʻololi mua iā ia, a laila hoʻomaka hou, akā aia nō kahi manawa e hoʻokō ʻole ʻia ai nā noi i ka noi, no ka mea maʻamau ka manawa o ka noi e hoʻouka mua. He aha inā e hoʻomaka ana, akā ʻaʻole hiki ke hana? ʻO kēia ka pilikia, e hoʻoponopono kākou me ka liʻiliʻi a me ka nani e like me ka hiki.
NĀ HOʻOPIʻI: Hōʻike ʻia ka hapa nui o ka ʻatikala ma kahi ʻano hoʻokolohua - ma ke ʻano o ka hoʻopaʻa ʻana i kahi hālāwai console. Lana ka manaʻo ʻaʻole paʻakikī loa kēia e hoʻomaopopo a e kākau pono ke code iā ia iho. No ka lewa, e noʻonoʻo ʻaʻole kēia he snippet code wale nō, akā he pepa mai kahi teletype "hao".
Hōʻike ʻia nā ʻenehana hoihoi i paʻakikī iā Google ma ka heluhelu ʻana i ke code ma ka hoʻomaka o kēlā me kēia ʻāpana. Inā maopopo ʻole kekahi mea, google a nānā. explainshell (ʻO ka pōmaikaʻi, hana hou ia, ma muli o ka wehe ʻana o ke kelepona). Inā ʻaʻole hiki iā ʻoe ke Google i kekahi mea, e nīnau i nā manaʻo. E hauʻoli wau e hoʻohui i ka ʻāpana pili "Nā ʻenehana hoihoi".
E hoʻomaka kākou
$ mkdir blue-green-deployment && cd $_
hana
E hana kāua i lawelawe hoʻokolohua a waiho i loko o kahi pahu.
Nā ʻenehana hoihoi
cat << EOF > file-name (Eia Palapala + Hoʻoholo hou I/O) he ala ia e hana ai i kahi faila multi-line me hoʻokahi kauoha. Heluhelu mai ka bash a pau /dev/stdin ma hope o kēia laina a ma mua o ka laina EOF e hoʻopaʻa ʻia ma file-name.
wget -qO- URL (explainshell) - hoʻopuka i kahi palapala i loaʻa ma o HTTP i /dev/stdout (analogue curl URL).
Paipai
Hoʻokaʻawale wau i ka snippet e hiki ai ke hōʻike i ka Python. Ma ka hopena e loaʻa hou kahi ʻāpana e like me kēia. E noʻonoʻo i kēia mau wahi i ʻoki ʻia ai ka pepa e hoʻouna ʻia i ke keʻena hoʻokalakupua (kahi i pena lima ʻia ke code me nā mea highlighters), a laila hoʻopili ʻia kēia mau ʻāpana.
$ cat << EOF > uptimer.py
from 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} is running for {t:3.1f} seconds.</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} (loads in {loading_seconds} sec.) started.')
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 (loads in 10 sec.) started.
$ wget -qSO- http://localhost:8080
HTTP/1.0 503 Service Unavailable
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 is running for 15.4 seconds.</h2>
$ docker rm --force uptimer
uptimer
Hoʻololi i ka mea koho
I mea e hiki ai i kā mākou noi ke hoʻololi me ka ʻike ʻole ʻia, pono e loaʻa kekahi mea ʻē aʻe i mua o ia e hūnā i kāna pani. He kikowaena pūnaewele paha nginx в hoʻololi i ke ʻano koho. Hoʻokumu ʻia kahi koho hope ma waena o ka mea kūʻai aku a me ka noi. ʻAe ʻo ia i nā noi mai nā mea kūʻai aku a hoʻouna iā lākou i ka palapala noi a hoʻouna i nā pane o ka noi i nā mea kūʻai aku.
Hiki ke hoʻopili ʻia ka noi a me ka proxy reverse i loko o ka docker me ka hoʻohana ʻana ʻupena docker. No laila, ʻaʻole pono ka pahu me ka noi e hoʻouna i kahi awa ma ka ʻōnaehana hoʻokipa; hiki i kēia ke hoʻokaʻawale ʻia ka noi mai nā hoʻoweliweli o waho.
Inā noho ka mea koho hope ma luna o kahi mea hoʻokipa ʻē aʻe, pono ʻoe e haʻalele i ka pūnaewele docker a hoʻopili i ka noi i ka mea koho hope ma o ka pūnaewele host, e hoʻouna i ke awa. Apps hoʻohālikelike --publish, e like me ka hoʻomaka mua a me ka mea koho hope.
E holo mākou i ka hoʻololi hope ma ke awa 80, no ka mea, ʻo ia ka mea pono e hoʻolohe i ka pūnaewele waho. Inā paʻa ka port 80 i kāu host hoʻāʻo, e hoʻololi i ka ʻāpana --publish 80:80 maluna o --publish ANY_FREE_PORT:80.
$ 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 is running for 11.5 seconds.</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 seconds ago Up 25 seconds 0.0.0.0:80->80/tcp reverse-proxy
a1105f1b583d uptimer "python -u ./app.py" About a minute ago Up About a minute 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: Sat, 22 Aug 2020 19:56:24 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
<h2>Uptimer v1.0 is running for 104.1 seconds.</h2>
Hoʻolaha ʻole ʻia
E ʻōwili i kahi mana hou o ka noi (me ka hoʻonui ʻana i ka hana hoʻomaka ʻelua) a e hoʻāʻo e hoʻonohonoho pono.
Nā ʻenehana hoihoi
echo 'my text' | docker exec -i my-container sh -c 'cat > /my-file.txt' — Kākau kikokiko my text e waiho /my-file.txt loko o ka ipu my-container.
cat > /my-file.txt — Kākau i nā mea o ka hoʻokomo maʻamau i kahi faila /dev/stdin.
Paipai
$ 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 (loads in 5 sec.) started.
$ docker run --rm --network web-gateway alpine wget -qO- http://uptimer_BLUE:8080
<h2>Uptimer v2.0 is running for 23.9 seconds.</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 is running for 63.4 seconds.</h2>
$ docker rm -f uptimer
uptimer
$ wget -qO- http://localhost
<h2>Uptimer v2.0 is running for 84.8 seconds.</h2>
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
96932d4ca97a uptimer "python -u ./app.py" About a minute ago Up About a minute 8080/tcp uptimer_BLUE
80695a822c19 nginx:alpine "/docker-entrypoint.…" 8 minutes ago Up 8 minutes 0.0.0.0:80->80/tcp reverse-proxy
I kēia pae, kūkulu pololei ʻia ke kiʻi ma luna o ke kikowaena, kahi e pono ai nā kumu noi ma laila, a hoʻouka pū i ke kikowaena me nā hana pono ʻole. ʻO ka hana aʻe e hoʻokaʻawale i ka hui kiʻi i kahi mīkini ʻokoʻa (no ka laʻana, i kahi ʻōnaehana CI) a laila hoʻololi iā ia i ke kikowaena.
Ke hoʻololi nei i nā kiʻi
ʻO ka mea pōʻino, ʻaʻole kūpono ke hoʻololi i nā kiʻi mai localhost i localhost, no laila hiki ke ʻimi wale ʻia kēia ʻāpana inā loaʻa iā ʻoe ʻelua mau pūʻali me Docker ma ka lima. Ma ka liʻiliʻi e like me kēia:
$ 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.9MB
hui docker save mālama i ka ʻikepili kiʻi i loko o kahi waihona .tar, ʻo ia hoʻi, ʻoi aku kona kaumaha ma kahi o 1.5 mau manawa ma mua o ke kaupaona ʻana ma ke ʻano paʻi. No laila, e lulu mākou ma ka inoa o ka mālama ʻana i ka manawa a me ke kaʻa:
I kēia manawa, e hōʻiliʻili kāua i nā mea a pau a mākou i hana lima ai i hoʻokahi palapala. E hoʻomaka kākou me ka hana kiʻekiʻe, a laila e nānā i nā mea ʻē aʻe i hoʻohana ʻia i loko.
Nā ʻenehana hoihoi
${parameter?err_msg} - kekahi o nā mea kilokilo bash (aka hoʻololi hoʻohālikelike). Inā parameter aole i hoakakaia, puka err_msg a puka i waho me ke code 1.
docker --log-driver journald - ma ka paʻamau, ʻo ka mea hoʻokele logging docker he faila kikokikona me ka ʻole o ka hoʻololi ʻana. Me kēia ala, hoʻopiha koke nā lāʻau i ka diski holoʻokoʻa, no laila no kahi hana hana pono e hoʻololi i ka mea hoʻokele i kahi mea akamai.
Palapala hoʻolālā
deploy() {
local usage_msg="Usage: ${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 "Deploying '$NEW' in place of '$OLD'..."
docker run
--detach
--restart always
--log-driver journald
--name $NEW
--network web-gateway
$image_name || return 3
echo "Container started. Checking health..."
for i in {1..20}
do
sleep 1
if get-service-status $image_name $new_slot
then
echo "New '$NEW' service seems OK. Switching heads..."
sleep 2 # Ensure service is ready
set-active-slot $image_name $new_slot || return 4
echo "'$NEW' service is live!"
sleep 2 # Ensure all requests were processed
echo "Killing '$OLD'..."
docker rm -f $OLD
docker image prune -f
echo "Deployment successful!"
return 0
fi
echo "New '$NEW' service is not ready yet. Waiting ($i)..."
done
echo "New '$NEW' service did not raise, killing it. Failed to deploy T_T"
docker rm -f $NEW
return 5
}
Nā hiʻohiʻona i hoʻohana ʻia:
ensure-reverse-proxy - E hōʻoia i ka hana ʻana o ka mea koho hope (pono no ka hoʻoili mua ʻana)
get-active-slot service_name - E hoʻoholo i kahi slot e hana nei no kahi lawelawe i hāʻawi ʻia (BLUE ai ole ia, GREEN)
get-service-status service_name deployment_slot - Hoʻoholo inā mākaukau ka lawelawe e hoʻoponopono i nā noi e hiki mai ana
set-active-slot service_name deployment_slot - Hoʻololi i ka config nginx i loko o ka pahu koho hope
I ke kauoha:
ensure-reverse-proxy() {
is-container-up reverse-proxy && return 0
echo "Deploying 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?"Usage: ${FUNCNAME[0]} container_name"}
[ -n "$(docker ps -f name=${container} -q)" ]
return $?
}
get-active-slot() {
local service=${1?"Usage: ${FUNCNAME[0]} service_name"}
if is-container-up ${service}_BLUE && is-container-up ${service}_GREEN; then
echo "Collision detected! Stopping ${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="Usage: ${FUNCNAME[0]} service_name deployment_slot"
local service=${1?usage_msg}
local slot=${2?$usage_msg}
case $service in
# Add specific healthcheck paths for your services here
*) local health_check_port_path=":8080/" ;;
esac
local health_check_address="http://${service}_${slot}${health_check_port_path}"
echo "Requesting '$health_check_address' within the 'web-gateway' docker network:"
docker run --rm --network web-gateway alpine
wget --timeout=1 --quiet --server-response $health_check_address
return $?
}
set-active-slot() {
local usage_msg="Usage: ${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
}
kuleana pili i get-active-slot pono e wehewehe iki:
No ke aha e hoʻihoʻi mai ai i kahi helu a ʻaʻole hoʻopuka i kahi kaula?
Eia nō naʻe, ma ka hana kelepona ʻike mākou i ka hopena o kāna hana, a ʻoi aku ka maʻalahi o ka nānā ʻana i ke code exit me ka bash ma mua o ka nānā ʻana i kahi kaula. Eia kekahi, maʻalahi loa ka loaʻa ʻana o kahi kaula mai ia mea: get-active-slot service && echo BLUE || echo GREEN.
Ua lawa anei nā kūlana ʻekolu e hoʻokaʻawale i nā mokuʻāina āpau?
ʻO nā mea ʻelua e lawa, ʻo ka mea hope ma ʻaneʻi no ka hoʻopiha piha, i ʻole e kākau else.
ʻO ka hana wale nō e hoʻihoʻi i nā configs nginx e waiho ʻole ʻia: get-nginx-config service_name deployment_slot. Ma ka hoʻohālikelike me ka nānā ʻana i ke olakino, hiki iā ʻoe ke hoʻonohonoho i kekahi config no kekahi lawelawe. ʻO nā mea hoihoi - wale nō cat <<- EOF, hiki iā ʻoe ke wehe i nā pā āpau i ka hoʻomaka. ʻOiaʻiʻo, ʻo ke kumukūʻai o ka formatting maikaʻi e hui pū ʻia me nā hakahaka, i kēia lā i manaʻo ʻia he ʻano maikaʻi ʻole. Akā ʻo ka bash forces tabs, a he mea maikaʻi nō hoʻi ka loaʻa ʻana o ka formatting maʻamau i ka config nginx. I ka pōkole, ʻo ka hui ʻana i nā ʻaoʻao me nā hakahaka ma aneʻi e like me ka hopena maikaʻi loa mai nā mea ʻino loa. Eia naʻe, ʻaʻole ʻoe e ʻike i kēia ma ka snippet ma lalo nei, no ka mea, "hana maikaʻi" ʻo Habr ma ka hoʻololi ʻana i nā ʻaoʻao āpau i 4 mau hakahaka a hana ʻole ʻia ʻo EOF. A eia ke ike ia.
I ʻole e ala ʻelua, e haʻi koke wau iā ʻoe cat << 'EOF', e halawai ana ma hope. Inā ʻoe e kākau maʻalahi cat << EOF, a laila i loko o ka heredoc ua hoʻopili ʻia ke kaula (ua hoʻonui ʻia nā mea hoʻololi ($foo), kahea kauoha ($(bar)) a me nā mea ʻē aʻe), a inā ʻoe e hoʻopili i ka hope o ka palapala i nā huaʻōlelo hoʻokahi, a laila ua pio ka interpolation a me ka hōʻailona. $ hōʻike ʻia e like me ia. ʻO kāu mea e pono ai e hoʻokomo i kahi palapala i loko o kahi palapala ʻē aʻe.
get-nginx-config() {
local usage_msg="Usage: ${FUNCNAME[0]} service_name deployment_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
# Add specific nginx configs for your services here
*) nginx-config-simple-service $container_name:8080 ;;
esac
}
nginx-config-simple-service() {
local usage_msg="Usage: ${FUNCNAME[0]} proxy_pass"
local proxy_pass=${1?$usage_msg}
cat << EOF
server {
listen 80;
location / {
proxy_pass http://$proxy_pass;
}
}
EOF
}
ʻO kēia ka palapala holoʻokoʻa. A pēlā mea nui me kēia palapala no ka hoʻoiho ʻana ma o wget a i ʻole curl.
Ke hoʻokō ʻana i nā ʻōkuhi i hoʻohālikelike ʻia ma kahi kikowaena mamao
ʻO ka manawa kēia e kīkēkē ai i ke kikowaena kikowaena. ʻO kēia manawa localhost kūpono loa:
$ 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.
Ua kākau mākou i kahi palapala hoʻolālā e hoʻoiho i kahi kiʻi i kūkulu mua ʻia i ka server i hoʻopaʻa ʻia a hoʻololi pono i ka ipu lawelawe, akā pehea mākou e hoʻokō ai ma kahi mīkini mamao? He mau hoʻopaʻapaʻa ka palapala, no ka mea, he honua a hiki ke kau i nā lawelawe i ka manawa hoʻokahi ma lalo o hoʻokahi proxy reverse (hiki iā ʻoe ke hoʻohana i nā configs nginx e hoʻoholo ai i ka url e lawelawe ai). ʻAʻole hiki ke mālama ʻia ka ʻatikala ma ka kikowaena, no ka mea, ʻaʻole hiki iā mākou ke hoʻololi maʻalahi iā ia (no ka hoʻoponopono ʻana i ka bug a me ka hoʻohui ʻana i nā lawelawe hou), a ma ka laulā, state = evil.
Pane 1: E mālama mau i ka palapala ma ke kikowaena, akā e kope i kēlā me kēia manawa scp. A laila hoʻohui ma o ssh a hoʻokō i ka palapala me nā manaʻo kūpono.
ʻAla:
ʻElua hana ma kahi o hoʻokahi
ʻAʻohe wahi āu e kope ai, a i ʻole hiki ke komo i laila, a i ʻole e hoʻokō ʻia ka palapala i ka manawa o ka hoʻololi ʻana.
He mea pono e hoʻomaʻemaʻe ma hope o ʻoe iho (hoʻopau i ka palapala).
ʻEkolu mau hana.
Pane 2:
E mālama i nā wehewehe hana wale nō ma ka palapala a ʻaʻohe holo iki
Me ke kōkuaʻana o sed hoʻohui i kahi kelepona hana i ka hopena
E hoʻouna pololei iā shh ma o ka paipu (|)
Kākoʻo:
Mokuaina ole maoli
ʻAʻohe mea hoʻohuihui boilerplate
Manaʻo hauʻoli
E hana wale kākou me ka ʻole o Ansible. ʻAe, ua haku ʻia nā mea a pau. ʻAe, he paikikala. E nānā i ka maʻalahi, ka nani a me ka minimalistic o ke kaʻa.
$ cat << 'EOF' > 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_SCRIPT
EOF
$ chmod +x deploy.sh
$ ./deploy.sh localhost magic-porridge-pot
Connecting to localhost...
Yay! The 'deploy' function is executing on 'hut' with argument 'magic-porridge-pot'
Eia nō naʻe, ʻaʻole hiki iā mākou ke hōʻoia ua lawa ka bash i ka host mamao, no laila e hoʻohui mākou i kahi helu liʻiliʻi i ka hoʻomaka (ʻo ia ma kahi o hoʻopāpā):
if [ "$SHELL" != "/bin/bash" ]
then
echo "The '$SHELL' shell is not supported by 'deploy.sh'. Set a '/bin/bash' shell for '$USER@$HOSTNAME'."
exit 1
fi
A i kēia manawa he mea maoli:
$ 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
Sending gzipped image 'uptimer' to 'localhost' via ssh...
Loaded image: uptimer:latest
Connecting to 'localhost' via ssh to seamlessly deploy 'uptimer'...
Deploying 'uptimer_GREEN' in place of 'uptimer_BLUE'...
06f5bc70e9c4f930e7b1f826ae2ca2f536023cc01e82c2b97b2c84d68048b18a
Container started. Checking health...
Requesting 'http://uptimer_GREEN:8080/' within the 'web-gateway' docker network:
HTTP/1.0 503 Service Unavailable
wget: server returned error: HTTP/1.0 503 Service Unavailable
New 'uptimer_GREEN' service is not ready yet. Waiting (1)...
Requesting 'http://uptimer_GREEN:8080/' within the 'web-gateway' docker network:
HTTP/1.0 503 Service Unavailable
wget: server returned error: HTTP/1.0 503 Service Unavailable
New 'uptimer_GREEN' service is not ready yet. Waiting (2)...
Requesting 'http://uptimer_GREEN:8080/' within the 'web-gateway' docker network:
HTTP/1.0 200 OK
Server: BaseHTTP/0.6 Python/3.8.3
Date: Sat, 22 Aug 2020 20:15:50 GMT
Content-Type: text/html
New 'uptimer_GREEN' service seems OK. Switching heads...
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
2020/08/22 20:15:54 [notice] 97#97: signal process started
The 'uptimer_GREEN' service is live!
Killing 'uptimer_BLUE'...
uptimer_BLUE
Total reclaimed space: 0B
Deployment successful!
I kēia manawa hiki iā ʻoe ke wehe http://localhost/ i loko o ka polokalamu kele pūnaewele, e holo hou i ka hoʻolālā a e hōʻoia i ka holo pono ʻana ma ka hoʻonui ʻana i ka ʻaoʻao e like me ka CD i ka wā o ka hoʻolālā.