Gelida Buluug-cagaaran ee mushaharka ugu yar

Maqaalkan waxaan isticmaalnaa bash, ssh, docker ΠΈ nginx Waxaanu habayn doonaa qaabayn aan kala go 'lahayn ee codsiga shabakada geynta buluug-cagaaran waa farsamo kuu ogolaanaysa inaad si degdeg ah u cusboonaysiiso arjiga adigoon diidin hal codsi. Waa mid ka mid ah xeeladaha meelaynta wakhtiga dhimista ee eber waxayna ku habboon tahay codsiyada hal tusaale ah, laakiin awoodda lagu shubo hal ilbiriqsi, tusaale-u-diyaar ah oo dhow.

Aynu nidhaahno waxaad haysaa codsi shabakadeed oo ay macaamiil badani si firfircoon u shaqaynayaan, mana jirto gabi ahaanba si ay u jiifsato dhawr ilbiriqsi. Oo runtii waxaad u baahan tahay inaad soo saarto cusboonaysiinta maktabadda, hagaajinta cayayaanka, ama sifo cusub oo qabow. Xaalad caadi ah, waxaad u baahan doontaa inaad joojiso codsiga, beddelo oo dib u bilowdo. Xaaladda docker-ka, marka hore waad bedeli kartaa, ka dib dib u bilaabi kartaa, laakiin wali waxaa jiri doona xilli codsiyada codsiga aan la baari doonin, sababtoo ah inta badan codsigu wuxuu qaataa waqti in la soo geliyo bilowga. Maxaa dhacaya haddii ay bilowdo, laakiin ay noqoto mid aan shaqaynayn? Tani waa dhibka, aynu ku xalino siyaabaha ugu yar iyo sida xarrago leh ee suurtogalka ah.

AFEEF: Maqaalka intiisa badan waxaa lagu soo bandhigay qaab tijaabo ah - qaab duubitaan fadhiga console-ka. Waxaan rajeyneynaa in tani aysan aad u adkaan doonin in la fahmo oo kood uu si ku filan isu diiwaangeliyo. Jawiga, ka soo qaad in kuwani aanay ahayn oo keliya qaybo kood ah, laakiin warqad laga soo qaatay teletype β€œbirta”.

Gelida Buluug-cagaaran ee mushaharka ugu yar

Farsamooyinka xiisaha leh ee ku adag Google-ka akhrinta koodka ayaa lagu sifeeyay bilawga qayb kasta. Haddii wax kale aysan caddayn, google ka gal oo iska hubi. sharax Shell (Nasiib wanaag, mar kale ayay shaqeysaa, iyadoo ay ugu wacan tahay xannibaadda telegram-ka). Haddii aadan wax Google-ka samayn karin, weydii faallooyinka. Waxaan ku farxi doonaa inaan ku daro qaybta u dhiganta "farsamooyinka xiisaha leh".

Aynu bilowno.

$ mkdir blue-green-deployment && cd $_

adeegga

Aynu samayno adeeg tijaabo ah oo ku rid weel.

Farsamooyinka xiisaha leh

  • cat << EOF > file-name (Halkan Dukumeenti + Jihaynta I/O) waa hab lagu abuuro fayl dhawr xariiq ah oo leh hal amar. Wax kasta bash ayaa ka akhriya /dev/stdin ka bacdi xariiqan iyo ka hor inta aan la saarin EOF lagu qori doonaa gudaha file-name.
  • wget -qO- URL (sharax Shell) - u soo saar dukumeenti lagu helay HTTP /dev/stdout (analoog curl URL).

Daabacaadda

Waxaan si gaar ah u jebiyaa goos gooska si aan awood ugu yeesho muujinta Python. Dhamaadka waxaa jiri doona qayb kale oo sidan oo kale ah. Tixgeli in meelahan warqadda la gooyey si loogu diro waaxda iftiiminta (halkaas oo koodka uu ahaa mid gacan-midab leh oo iftiiminaya), ka dibna qaybahan ayaa dib loo dhajiyay.

$ 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

Dib u celi wakiil

Si codsigayagu u awoodo in uu isbeddelo iyada oo aan la dareemin, waxaa lagama maarmaan ah in ay jiraan wax kale oo hor yaal oo qarin doona beddelkiisa. Waxay noqon kartaa server-ka shabakadda nginx Π² hab wakiil ka noqosho. Wakiil gadaale ah ayaa laga dhex sameeyay macmiilka iyo arjiga. Waxay aqbashaa codsiyada macaamiisha waxayna u gudbisaa codsiga waxayna u gudbisaa jawaabaha codsiga macaamiisha.

Codsiga iyo wakiilka gadaale waxa lagu xidhidhi karaa gudaha dockerka iyadoo la isticmaalayo docker network. Markaa, weelka arjiga ku jira xitaa uma baahna inuu u gudbiyo deked ku taal nidaamka martida loo yahay; tani waxay u oggolaanaysaa codsiga in si weyn looga go'doomiyo khataraha dibadda.

Haddii wakiilka gadaale uu ku nool yahay martigeliyaha kale, waa inaad ka tagtaa shabakada docker-ka oo aad ku xidho codsiga wakiilka dambe ee shabakada martida loo yahay, u gudbinta dekeda apps halbeegga --publish, sida bilawgii hore iyo sida wakiilkii hore.

Waxaan ku socodsiin doonaa wakiilka gadaale ee dekedda 80, sababtoo ah tani waa dhab ahaan cidda ay tahay inay dhageysato shabakadda dibadda. Haddii dekedda 80 ay ku mashquulsan tahay martigeliyahaaga tijaabada, beddel cabbirka --publish 80:80 on --publish ANY_FREE_PORT:80.

Farsamooyinka xiisaha leh

Daabacaadda

$ 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>

Gelin aan sal lahayn

Aan soo saarno nooc cusub oo arjiga ah (oo leh laba laab kor u qaadista waxqabadka bilowga ah) oo aan isku dayno inaan u dirno si aan kala go 'lahayn.

Farsamooyinka xiisaha leh

  • echo 'my text' | docker exec -i my-container sh -c 'cat > /my-file.txt' - Qor qoraal my text in la xareeyo /my-file.txt gudaha weelka my-container.
  • cat > /my-file.txt - U qor waxa ku jira gelinta caadiga ah faylka /dev/stdin.

Daabacaadda

$ 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

Marxaladdan, sawirka ayaa si toos ah loogu dhisay server-ka, kaas oo u baahan ilaha codsiga si ay halkaas u joogaan, iyo sidoo kale waxay ku shubtaa server-ka shaqo aan loo baahnayn. Tallaabada xigta waa in loo qoondeeyo shirka sawirka mashiinka goonida ah (tusaale ahaan, nidaamka CI) ka dibna u wareeji serverka.

Wareejinta sawirada

Nasiib darro, macno ma samaynayso in laga wareejiyo sawirada localhost loona wareejiyo localhost, marka qaybtan waxa la baari karaa oo kaliya haddii aad haysato laba martigaliyayaasha oo gacanta ku haya Docker. Ugu yaraan waxay u egtahay wax sidan oo kale ah:

$ 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

kooxda docker save waxay ku kaydisaa xogta sawirka ee kaydka .tar, taasoo la macno ah in uu miisaankiisu ka badan yahay 1.5 jeer marka loo eego qaabka la cufan. Haddaba aan ku ruxno magaca badbaadinta wakhtiga iyo socodka:

$ docker image save uptimer | gzip | ssh production-server 'zcat | docker image load'
Loaded image: uptimer:latest

Waxa kale oo aad la socon kartaa habka soo dejinta (in kasta oo ay tani u baahan tahay utility dhinac saddexaad):

$ docker image save uptimer | gzip | pv | ssh production-server 'zcat | docker image load'
25,7MiB 0:01:01 [ 425KiB/s] [                   <=>    ]
Loaded image: uptimer:latest

Talo: Haddii aad u baahan tahay farabadan oo cabbirro ah si aad ugu xidhid server-ka adigoo isticmaalaya SSH, waxaa laga yaabaa inaadan isticmaalin faylka ~/.ssh/config.

Ku wareejinta sawirka iyada oo loo marayo docker image save/load - Tani waa habka ugu yar, laakiin ma aha ka kaliya. Waxaa jira kuwa kale:

  1. Diiwaanka weelasha (heerka warshadaha).
  2. Ku xidh server-ka daemon docker ee martigeliyaha kale:
    1. doorsooma deegaan DOCKER_HOST.
    2. Xulashada khadka taliska -H ama --host qalab docker-compose.
    3. docker context

Habka labaad (oo leh saddex doorasho oo lagu hirgelin karo) ayaa si fiican loogu sharraxay maqaalka Sida loo geeyo meelaha fog fog ee Docker host-yada leh docker-compose.

deploy.sh

Hadda aynu ku soo ururinno wax kasta oo aynu gacanta ku samaynay oo hal qoraal ka dhigno. Aan ku bilowno shaqada heerka sare, ka dibna aan eegno kuwa kale ee loo isticmaalo.

Farsamooyinka xiisaha leh

  • ${parameter?err_msg} - mid ka mid ah sixirka bash (aka beddelka halbeegga). Hadii parameter aan la cayimin, wax soo saarka err_msg oo la bax code 1.
  • docker --log-driver journald - Sida caadiga ah, dareewalka goynta docker-ka waa fayl qoraal ah oo aan wax wareeg ah lahayn. Habkan, logu wuxuu si dhakhso ah u buuxiyaa dhammaan diskka, sidaas darteed jawi wax soo saar ah waa lagama maarmaan in la beddelo darawalka mid caqli badan.

Qoraalka geynta

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
}

Sifooyinka la isticmaalay:

  • ensure-reverse-proxy - Waxay hubisaa in wakiilkii hore uu shaqaynayo (waxtar u leh hawlgelinta ugu horreysa)
  • get-active-slot service_name - Wuxuu go'aamiyaa booska hadda firfircoon ee adeegga la bixiyay (BLUE ama GREEN)
  • get-service-status service_name deployment_slot - Wuxuu go'aamiyaa haddii adeeggu diyaar u yahay inuu ka shaqeeyo codsiyada soo socda
  • set-active-slot service_name deployment_slot - Beddelayaa habaynta nginx ee weelka wakiillada

Si:

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
}

function get-active-slot waxay u baahan tahay sharraxaad yar:

Waa maxay sababta ay u soo celiso lambar oo aanay u soo saarin xadhig?

Si kastaba ha noqotee, shaqada wicitaanka waxaan ku hubineynaa natiijada shaqadeeda, iyo hubinta koodka bixista iyadoo la adeegsanayo bash aad ayey uga sahlan tahay hubinta xargaha. Intaa waxaa dheer, helitaanka xadhig ka soo baxa waa mid aad u fudud:
get-active-slot service && echo BLUE || echo GREEN.

Saddex shuruudood ma ku filan yihiin in lagu kala saaro dhammaan gobollada?

Gelida Buluug-cagaaran ee mushaharka ugu yar

Xitaa laba ayaa ku filnaan doona, kan ugu dambeeya wuxuu halkan u joogaa oo kaliya dhammaystirka, si aan loo qorin else.

Kaliya shaqada soo celisa qaabaynta nginx ayaa ah mid aan la qeexin: get-nginx-config service_name deployment_slot. Marka la barbardhigo hubinta caafimaadka, halkan waxaad dejin kartaa qaab kasta oo adeeg kasta ah. Waxyaabaha xiisaha leh - kaliya cat <<- EOF, kaas oo kuu ogolaanaya inaad ka saarto dhammaan tabs bilowga. Run, qiimaha qaabaynta wanaagsan waa tabs isku dhafan oo leh meelo bannaan, taas oo maanta loo arko qaab aad u xun. Laakiin bash Force tabs, sidoo kale way fiicnaan lahayd in qaabaynta caadiga ah lagu sameeyo qaabka nginx. Marka la soo koobo, isku darka tabsyada leh meelaha bannaan ee halkan ayaa runtii u muuqda xalka ugu fiican ee ka baxsan kuwa ugu xun. Si kastaba ha ahaatee, tan kuma arki doontid qaybta hoose, maadaama Habr "si fiican u qabto" isagoo u beddelaya dhammaan tabsiyada 4 boos oo ka dhigaya EOF mid aan sax ahayn. Oo halkan waa la dareemi karaa.

Si aanad laba jeer u kicin, isla markiiba ayaan kuu sheegi doonaa cat << 'EOF', oo hadhow la kulmi doono. Haddii aad si fudud u qorto cat << EOF, ka dibna heredoc gudihiis xadhiggu waa la isku xidhay (isbedelka waa la ballaariyay$foo), wicitaanada amarka ($(bar)iwm.), Oo haddii aad ku xidho dhamaadka dukumeenti hal xigasho, markaas dhex galka waa naafo iyo calaamada $ waxaa loo soo bandhigay sida ay tahay. Waxa aad u baahan tahay inaad geliso qoraal gudaha qoraal kale.

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
}

Tani waa qoraalka oo dhan. Iyo sidaas nuxurka qoraalkan si loogu soo dejiyo wget ama curl.

Ku-fulinta qoraallada la xaddiday ee server-ka fog

Waa waqtigii la garaaci lahaa server-ka bartilmaameedka ah. Markan localhost ku haboon:

$ 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.

Waxaan qornay qoraal diris ah oo soo dejinaya sawir horay loo dhisay server-ka bartilmaameedka oo si aan kala go 'lahayn u beddelaya weelka adeegga, laakiin sidee ayaan ugu fulin karnaa mashiinka fog? Qoraalku waxa uu leeyahay doodo, maadaama uu yahay mid caalami ah oo isla markiiba gayn kara adeegyo dhowr ah oo hoos imanaya hal wakiil oo gadaal ah (waxaad isticmaali kartaa habaynta nginx si aad u go'aamiso url-ka noqon doona adeegga). Qoraalka laguma kaydin karo server-ka, tan iyo kiiskan ma awoodi doono inaan si toos ah u cusbooneysiiyo (ujeeddada hagaajinta cayayaanka iyo ku darida adeegyo cusub), iyo guud ahaan, gobolka = shar.

Xalka 1: Wali ku kaydi qoraalka server-ka, laakiin nuqul ka samee mar kasta scp. Kadibna ku xidh ssh oo ku fuliyaan qoraalka doodaha lagama maarmaanka ah.

Ogolaansho:

  • Laba fal halkii mid
  • Waxaa laga yaabaa inaysan jirin meel aad nuqul ka sameysato, ama laga yaabo inaan la geli karin, ama qoraalka waxaa laga yaabaa in la fuliyo waqtiga beddelka.
  • Waxaa lagugula talinayaa inaad nadiifiso naftaada ka dib (tirtir qoraalka).
  • Durba saddex fal.

Xalka 2:

  • Ku hay kaliya qeexitaannada shaqada ee qoraalka oo waxba ha wada socon
  • Iyada oo gargaar ah sed ku dar baaq shaqo ilaa dhamaadka
  • Dhammaan si toos ah ugu dir shh adigoo isticmaalaya tuubo (|)

Faa'iido:

  • Runtii dawlad la'aan
  • Ma jiraan wax-kuuliyaha
  • Dareen qabow

Aan samayno la'aanteed Caqli la'aan. Haa, wax walba waa la allifay. Haa, baaskiil Fiiri sida fudud, xarrago leh oo yar oo baaskiilku u yahay:

$ 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'

Si kastaba ha ahaatee, ma hubin karno in martigeliyaha fog uu leeyahay bash ku filan, markaa waxaan ku dari doonaa jeeg yar bilawga (tani waa halkii shellbang):

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

Haddana waa dhab:

$ 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!

Hadda waad furi kartaa http://localhost/ browser-ka, ku socodsii dib-u-dejinta mar kale oo hubi in ay si aan kala go 'lahayn u socoto adiga oo cusboonaysiinaya bogga sida ku cad CD-ga inta lagu jiro qaabaynta.

Ha ilaawin inaad nadiifiso shaqada ka dib :3

$ docker rm -f uptimer_GREEN reverse-proxy 
uptimer_GREEN
reverse-proxy

$ docker network rm web-gateway 
web-gateway

$ cd ..

$ rm -r blue-green-deployment

Source: www.habr.com