$ 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
پدې مرحله کې، عکس مستقیم په سرور کې جوړ شوی، کوم چې د غوښتنلیک سرچینې ته اړتیا لري، او سرور د غیر ضروري کار سره باروي. بل ګام دا دی چې د عکس مجلس جلا ماشین ته تخصیص کړئ (د مثال په توګه د CI سیسټم ته) او بیا یې سرور ته انتقال کړئ.
د انځورونو لیږدول
له بده مرغه، دا د لوکل هوسټ څخه لوکل هوسټ ته د عکسونو لیږدولو معنی نلري ، نو دا برخه یوازې هغه وخت سپړل کیدی شي که تاسو په لاس کې د ډاکر سره دوه کوربه ولرئ. لږترلږه دا یو څه داسې ښکاري:
$ 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
ټیم docker save د عکس ډیټا په .tar آرشیف کې خوندي کوي ، پدې معنی چې دا د کمپریس شوي شکل په پرتله شاوخوا 1.5 ځله ډیر وزن لري. نو راځئ چې دا د وخت او ترافیک خوندي کولو په نوم ولګوو:
${parameter?err_msg} - د باش جادو منترونو څخه یو (aka د پیرامیټر بدیل). که parameter نه مشخص شوی، محصول err_msg او د کوډ 1 سره وتل.
docker --log-driver journald - د ډیفالټ په واسطه ، د ډاکر لاګینګ ډرایور د متن فایل دی پرته له کوم گردش. د دې طریقې سره، لاګونه په چټکۍ سره ټول ډیسک ډکوي، نو د تولید چاپیریال لپاره دا اړینه ده چې ډرایور په هوښیار ډول بدل کړئ.
د ځای پرځای کولو سکریپټ
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
}
حتی دوه به کافي وي، وروستی یو یوازې د بشپړتیا لپاره دی، نو د لیکلو لپاره نه else.
یوازې هغه فنکشن چې د نګینکس تشکیلات بیرته راګرځوي نامعلوم پاتې دي: get-nginx-config service_name deployment_slot. د روغتیا معاینې سره په ورته والي سره ، دلته تاسو کولی شئ د هر خدمت لپاره کوم ترتیب تنظیم کړئ. د زړه پورې شیانو څخه - یوازې cat <<- EOF، کوم چې تاسو ته اجازه درکوي په پیل کې ټول ټبونه لرې کړئ. ریښتیا، د ښه فارمیټ قیمت د ځایونو سره مخلوط ټبونه دي، چې نن ورځ خورا بد شکل ګڼل کیږي. مګر باش ټبونه ځواکوي، او دا به هم ښه وي چې په نګینکس ترتیب کې نورمال فارمیټ ولرئ. په لنډه توګه، دلته د ځایونو سره د ټبونو مخلوط کول واقعیا د بدترین حل په څیر ښکاري. په هرصورت، تاسو به دا په لاندې ټوټه کې ونه ګورئ، ځکه چې حبر "دا ښه کوي" د 4 ځایونو ته د ټولو ټبونو بدلولو او د EOF ناسم کولو سره. او دلته دا د پام وړ دی.
نو لکه څنګه چې دوه ځله نه پورته کیږي، زه به تاسو ته سمدستي ووایم cat << 'EOF'، چې وروسته به ورسره مخ شي. که تاسو ساده لیکئ cat << EOF، بیا د هیرډوک دننه تار مینځل کیږي (متغیرونه پراخ شوي)$fooد کمانډ زنګونه ($(bar)) etc.)، او که تاسو د سند پای په واحد نرخونو کې تړلی وي، نو انټرپولیشن غیر فعال دی او سمبول $ لکه څنګه چې دی ښودل شوی. هغه څه چې تاسو اړتیا لرئ په بل سکریپټ کې سکریپټ دننه کړئ.
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
}
دا ټول سکریپټ دی. او داسې د دې سکریپټ سره لنډیز د ویجټ یا کرل له لارې ډاونلوډ کولو لپاره.
په ریموټ سرور کې د پیرامیټر شوي سکریپټونو اجرا کول
دا وخت دی چې د هدف سرور ټک کړئ. همدا اوس localhost ډیر مناسب:
$ 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.
موږ د پلي کولو سکریپټ لیکلی دی چې د هدف سرور ته دمخه جوړ شوی عکس ډاونلوډ کوي او په بې ساري ډول د خدماتو کانټینر بدلوي ، مګر موږ څنګه کولی شو دا په ریموټ ماشین کې اجرا کړو؟ سکریپټ دلیلونه لري، ځکه چې دا نړیوال دی او کولی شي په یوځل کې د یو ریورس پراکسي لاندې ډیری خدمتونه ځای په ځای کړي (تاسو کولی شئ د نګینکس تشکیلات وکاروئ ترڅو معلومه کړئ چې کوم یو آر ایل به کوم خدمت وي). سکریپټ په سرور کې زیرمه کیدی نشي ، ځکه چې پدې حالت کې به موږ ونه شو کولی دا په اوتومات ډول تازه کړو (د بګ فکس کولو او نوي خدماتو اضافه کولو هدف لپاره) ، او په عموم کې ، حالت = بد.
1 حل: بیا هم سکریپټ په سرور کې ذخیره کړئ، مګر هر ځل یې کاپي کړئ scp. بیا له لارې وصل شئ ssh او سکریپټ د اړین دلیلونو سره اجرا کړئ.
ضمیمه:
د یو پر ځای دوه عملونه
ممکن داسې ځای شتون ونلري چیرې چې تاسو کاپي کوئ، یا ممکن ورته لاسرسی شتون ونلري، یا سکریپټ ممکن د بدیل په وخت کې اجرا شي.
راځئ چې دا د ځواب وړ پرته ترسره کړو. هو، هرڅه لا دمخه اختراع شوي دي. هو، یو بایسکل. وګورئ چې دا بایسکل څومره ساده، ښکلی او دقیق دی:
$ 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'
په هرصورت، موږ ډاډه نه یو چې لیرې کوربه کافي باش لري، نو موږ به په پیل کې یو کوچنی چک اضافه کړو (دا د دې پرځای دی شیل بنګ):
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
او اوس دا ریښتیا ده:
$ 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!
اوس تاسو کولی شئ خلاص کړئ http://localhost/ په براوزر کې، بیا ځای پرځای کول پرمخ وړئ او ډاډ ترلاسه کړئ چې دا د ترتیب په جریان کې د CD مطابق د پاڼې تازه کولو سره په بې ساري ډول پرمخ ځي.