āĻāĻ āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§ā§ āĻāĻŽāĻ°āĻž āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻŋ
āĻ§āĻ°āĻž āĻ¯āĻžāĻ āĻāĻĒāĻ¨āĻžāĻ° āĻāĻāĻāĻŋ āĻāĻ¯āĻŧā§āĻŦ āĻ ā§āĻ¯āĻžāĻĒā§āĻ˛āĻŋāĻā§āĻļāĻ¨ āĻ°āĻ¯āĻŧā§āĻā§ āĻ¯āĻžāĻ° āĻ¸āĻžāĻĨā§ āĻ āĻ¨ā§āĻ āĻā§āĻ˛āĻžāĻ¯āĻŧā§āĻ¨ā§āĻ āĻ¸āĻā§āĻ°āĻŋāĻ¯āĻŧāĻāĻžāĻŦā§ āĻāĻžāĻ āĻāĻ°āĻā§ āĻāĻŦāĻ āĻāĻ¯āĻŧā§āĻ āĻ¸ā§āĻā§āĻ¨ā§āĻĄā§āĻ° āĻāĻ¨ā§āĻ¯ āĻļā§āĻ¯āĻŧā§ āĻĨāĻžāĻāĻžāĻ° āĻā§āĻ¨ āĻāĻĒāĻžāĻ¯āĻŧ āĻ¨ā§āĻāĨ¤ āĻāĻŦāĻ āĻāĻĒāĻ¨āĻžāĻā§ āĻ¸āĻ¤ā§āĻ¯āĻŋāĻ āĻāĻāĻāĻŋ āĻ˛āĻžāĻāĻŦā§āĻ°ā§āĻ°āĻŋ āĻāĻĒāĻĄā§āĻ, āĻāĻāĻāĻŋ āĻŦāĻžāĻ āĻĢāĻŋāĻā§āĻ¸, āĻŦāĻž āĻāĻāĻāĻŋ āĻ¨āĻ¤ā§āĻ¨ āĻĻā§āĻ°ā§āĻĻāĻžāĻ¨ā§āĻ¤ āĻŦā§āĻļāĻŋāĻˇā§āĻā§āĻ¯ āĻ°ā§āĻ˛ āĻāĻāĻ āĻāĻ°āĻ¤ā§ āĻšāĻŦā§āĨ¤ āĻāĻāĻāĻŋ āĻ¸ā§āĻŦāĻžāĻāĻžāĻŦāĻŋāĻ āĻĒāĻ°āĻŋāĻ¸ā§āĻĨāĻŋāĻ¤āĻŋāĻ¤ā§, āĻāĻĒāĻ¨āĻžāĻā§ āĻ ā§āĻ¯āĻžāĻĒā§āĻ˛āĻŋāĻā§āĻļāĻ¨āĻāĻŋ āĻŦāĻ¨ā§āĻ§ āĻāĻ°āĻ¤ā§ āĻšāĻŦā§, āĻāĻāĻŋ āĻĒā§āĻ°āĻ¤āĻŋāĻ¸ā§āĻĨāĻžāĻĒāĻ¨ āĻāĻ°āĻ¤ā§ āĻšāĻŦā§ āĻāĻŦāĻ āĻāĻāĻŋ āĻāĻŦāĻžāĻ° āĻļā§āĻ°ā§ āĻāĻ°āĻ¤ā§ āĻšāĻŦā§āĨ¤ āĻĄāĻāĻžāĻ°ā§āĻ° āĻā§āĻˇā§āĻ¤ā§āĻ°ā§, āĻāĻĒāĻ¨āĻŋ āĻĒā§āĻ°āĻĨāĻŽā§ āĻāĻāĻŋ āĻĒā§āĻ°āĻ¤āĻŋāĻ¸ā§āĻĨāĻžāĻĒāĻ¨ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨, āĻ¤āĻžāĻ°āĻĒāĻ°ā§ āĻāĻāĻŋ āĻĒā§āĻ¨āĻ°āĻžāĻ¯āĻŧ āĻāĻžāĻ˛ā§ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨, āĻ¤āĻŦā§ āĻāĻāĻ¨āĻ āĻāĻāĻāĻŋ āĻ¸āĻŽāĻ¯āĻŧ āĻĨāĻžāĻāĻŦā§ āĻ¯ā§āĻāĻžāĻ¨ā§ āĻ ā§āĻ¯āĻžāĻĒā§āĻ˛āĻŋāĻā§āĻļāĻ¨āĻāĻŋāĻ° āĻ āĻ¨ā§āĻ°ā§āĻ§āĻā§āĻ˛āĻŋ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻāĻ°āĻž āĻšāĻŦā§ āĻ¨āĻž, āĻāĻžāĻ°āĻŖ āĻ¸āĻžāĻ§āĻžāĻ°āĻŖāĻ¤ āĻ ā§āĻ¯āĻžāĻĒā§āĻ˛āĻŋāĻā§āĻļāĻ¨āĻāĻŋ āĻĒā§āĻ°āĻžāĻĨāĻŽāĻŋāĻāĻāĻžāĻŦā§ āĻ˛ā§āĻĄ āĻšāĻ¤ā§ āĻāĻŋāĻā§āĻāĻž āĻ¸āĻŽāĻ¯āĻŧ āĻ¨ā§āĻ¯āĻŧāĨ¤ āĻāĻāĻž āĻļā§āĻ°ā§ āĻšāĻ˛ā§ āĻāĻŋ āĻšāĻŦā§, āĻāĻŋāĻ¨ā§āĻ¤ā§ āĻ āĻāĻžāĻ°ā§āĻ¯āĻāĻ° āĻšāĻ¤ā§ āĻĻā§āĻāĻž āĻ¯āĻžāĻā§āĻā§? āĻāĻāĻŋ āĻāĻāĻāĻŋ āĻ¸āĻŽāĻ¸ā§āĻ¯āĻž, āĻāĻ¸ā§āĻ¨ āĻāĻāĻŋāĻā§ āĻ¨ā§āĻ¯ā§āĻ¨āĻ¤āĻŽ āĻāĻĒāĻžāĻ¯āĻŧā§ āĻāĻŦāĻ āĻ¯āĻ¤āĻāĻž āĻ¸āĻŽā§āĻāĻŦ āĻŽāĻžāĻ°ā§āĻāĻŋāĻ¤āĻāĻžāĻŦā§ āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ āĻāĻ°āĻŋāĨ¤
āĻ āĻ¸ā§āĻŦā§āĻā§āĻ¤āĻŋ: āĻŦā§āĻļāĻŋāĻ°āĻāĻžāĻ āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§ āĻāĻāĻāĻŋ āĻĒāĻ°ā§āĻā§āĻˇāĻžāĻŽā§āĻ˛āĻ āĻŦāĻŋāĻ¨ā§āĻ¯āĻžāĻ¸ā§ āĻāĻĒāĻ¸ā§āĻĨāĻžāĻĒāĻ¨ āĻāĻ°āĻž āĻšāĻ¯āĻŧā§āĻā§ - āĻāĻāĻāĻŋ āĻāĻ¨āĻ¸ā§āĻ˛ āĻ¸ā§āĻļāĻ¨ā§āĻ° āĻ°ā§āĻāĻ°ā§āĻĄāĻŋāĻāĻ¯āĻŧā§āĻ° āĻāĻāĻžāĻ°ā§āĨ¤ āĻāĻļāĻž āĻāĻ°āĻŋ āĻāĻāĻŋ āĻŦā§āĻāĻž āĻā§āĻŦ āĻāĻ āĻŋāĻ¨ āĻšāĻŦā§ āĻ¨āĻž āĻāĻŦāĻ āĻā§āĻĄāĻāĻŋ āĻ¯āĻĨā§āĻˇā§āĻ āĻ¨āĻĨāĻŋāĻā§āĻā§āĻ¤ āĻāĻ°āĻŦā§āĨ¤ āĻŦāĻžāĻ¯āĻŧā§āĻŽāĻŖā§āĻĄāĻ˛ā§āĻ° āĻāĻ¨ā§āĻ¯, āĻāĻ˛ā§āĻĒāĻ¨āĻž āĻāĻ°ā§āĻ¨ āĻ¯ā§ āĻāĻā§āĻ˛āĻŋ āĻā§āĻŦāĻ˛ āĻā§āĻĄ āĻ¸ā§āĻ¨āĻŋāĻĒā§āĻ āĻ¨āĻ¯āĻŧ, āĻāĻāĻāĻŋ "āĻ˛ā§āĻšāĻž" āĻā§āĻ˛āĻŋāĻāĻžāĻāĻĒ āĻĨā§āĻā§ āĻāĻžāĻāĻāĨ¤
āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻā§āĻĄ āĻĒāĻĄāĻŧā§ Google-āĻāĻ° āĻāĻžāĻā§ āĻāĻ āĻŋāĻ¨ āĻāĻŽāĻ¨ āĻāĻāĻ°ā§āĻˇāĻŖā§āĻ¯āĻŧ āĻā§āĻļāĻ˛ āĻĒā§āĻ°āĻ¤āĻŋāĻāĻŋ āĻŦāĻŋāĻāĻžāĻā§āĻ° āĻļā§āĻ°ā§āĻ¤ā§ āĻŦāĻ°ā§āĻŖāĻ¨āĻž āĻāĻ°āĻž āĻšāĻ¯āĻŧā§āĻā§āĨ¤ āĻ
āĻ¨ā§āĻ¯ āĻāĻŋāĻā§ āĻ
āĻ¸ā§āĻĒāĻˇā§āĻ āĻšāĻ˛ā§, āĻāĻāĻŋ āĻā§āĻāĻ˛ āĻāĻ°ā§āĻ¨ āĻāĻŦāĻ āĻāĻāĻŋ āĻĒāĻ°ā§āĻā§āĻˇāĻž āĻāĻ°ā§ āĻĻā§āĻā§āĻ¨.
āĻļā§āĻ°ā§ āĻāĻ°āĻž āĻ¯āĻžāĻāĨ¤
$ mkdir blue-green-deployment && cd $_
āĻ¸ā§āĻŦāĻž
āĻāĻ¸ā§āĻ¨ āĻāĻāĻāĻŋ āĻĒāĻ°ā§āĻā§āĻˇāĻžāĻŽā§āĻ˛āĻ āĻĒāĻ°āĻŋāĻˇā§āĻŦāĻž āĻ¤ā§āĻ°āĻŋ āĻāĻ°āĻŋ āĻāĻŦāĻ āĻāĻāĻŋ āĻāĻāĻāĻŋ āĻĒāĻžāĻ¤ā§āĻ°ā§ āĻ°āĻžāĻāĻŋāĨ¤
āĻāĻāĻ°ā§āĻˇāĻŖā§āĻ¯āĻŧ āĻā§āĻļāĻ˛
cat << EOF > file-name
(āĻāĻāĻžāĻ¨ā§ āĻĄāĻā§āĻŽā§āĻ¨ā§āĻ +I/O āĻĒā§āĻ¨āĻ°ā§āĻ¨āĻŋāĻ°ā§āĻĻā§āĻļ ) āĻšāĻ˛ āĻāĻāĻāĻŋ āĻāĻŽāĻžāĻ¨ā§āĻĄ āĻ¸āĻš āĻāĻāĻāĻŋ āĻŽāĻžāĻ˛ā§āĻāĻŋ-āĻ˛āĻžāĻāĻ¨ āĻĢāĻžāĻāĻ˛ āĻ¤ā§āĻ°āĻŋ āĻāĻ°āĻžāĻ° āĻāĻāĻāĻŋ āĻāĻĒāĻžāĻ¯āĻŧāĨ¤ āĻ¸āĻŦāĻāĻŋāĻā§ āĻŦāĻžāĻļ āĻĨā§āĻā§ āĻĒāĻĄāĻŧāĻž/dev/stdin
āĻāĻ āĻ˛āĻžāĻāĻ¨ā§āĻ° āĻĒāĻ°ā§ āĻāĻŦāĻ āĻ˛āĻžāĻāĻ¨ā§āĻ° āĻāĻā§EOF
āĻŽāĻ§ā§āĻ¯ā§ āĻ°ā§āĻāĻ°ā§āĻĄ āĻāĻ°āĻž āĻšāĻŦā§file-name
.wget -qO- URL
(āĻŦā§āĻ¯āĻžāĻā§āĻ¯āĻž ) â HTTP āĻāĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻĒā§āĻ°āĻžāĻĒā§āĻ¤ āĻāĻāĻāĻŋ āĻ¨āĻĨāĻŋ āĻāĻāĻāĻĒā§āĻ āĻāĻ°ā§/dev/stdout
(āĻ ā§āĻ¯āĻžāĻ¨āĻžāĻ˛āĻcurl URL
).
āĻĒā§āĻ°āĻŋāĻ¨ā§āĻāĻāĻāĻ
āĻĒāĻžāĻāĻĨāĻ¨ā§āĻ° āĻāĻ¨ā§āĻ¯ āĻšāĻžāĻāĻ˛āĻžāĻāĻāĻŋāĻ āĻ¸āĻā§āĻˇāĻŽ āĻāĻ°āĻ¤ā§ āĻāĻŽāĻŋ āĻŦāĻŋāĻļā§āĻˇāĻāĻžāĻŦā§ āĻ¸ā§āĻ¨āĻŋāĻĒā§āĻāĻāĻŋ āĻā§āĻā§ āĻĻāĻŋāĻāĨ¤ āĻļā§āĻˇā§ āĻāĻ āĻŽāĻ¤ āĻāĻ°ā§āĻāĻāĻŋ āĻā§āĻāĻ°āĻž āĻšāĻŦā§. āĻŦāĻŋāĻŦā§āĻāĻ¨āĻž āĻāĻ°ā§āĻ¨ āĻ¯ā§ āĻāĻ āĻāĻžāĻ¯āĻŧāĻāĻžāĻā§āĻ˛āĻŋāĻ¤ā§ āĻāĻžāĻāĻāĻāĻŋ āĻšāĻžāĻāĻ˛āĻžāĻāĻāĻŋāĻ āĻŦāĻŋāĻāĻžāĻā§ āĻĒāĻžāĻ āĻžāĻ¨ā§āĻ° āĻāĻ¨ā§āĻ¯ āĻāĻžāĻāĻž āĻšāĻ¯āĻŧā§āĻāĻŋāĻ˛ (āĻ¯ā§āĻāĻžāĻ¨ā§ āĻā§āĻĄāĻāĻŋ āĻšāĻžāĻāĻ˛āĻžāĻāĻāĻžāĻ° āĻĻāĻŋāĻ¯āĻŧā§ āĻšāĻžāĻ¤ā§ āĻ°āĻā§āĻ° āĻāĻŋāĻ˛), āĻāĻŦāĻ āĻ¤āĻžāĻ°āĻĒāĻ°ā§ āĻāĻ āĻā§āĻāĻ°ā§āĻā§āĻ˛āĻŋāĻā§ āĻāĻŦāĻžāĻ° āĻāĻ āĻžāĻ˛ā§ āĻāĻ°āĻž āĻšāĻ¯āĻŧā§āĻāĻŋāĻ˛āĨ¤
$ 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
āĻŦāĻŋāĻĒāĻ°ā§āĻ¤ āĻĒā§āĻ°āĻā§āĻ¸āĻŋ
āĻāĻŽāĻžāĻĻā§āĻ° āĻ
ā§āĻ¯āĻžāĻĒā§āĻ˛āĻŋāĻā§āĻļāĻ¨āĻāĻŋ āĻ
āĻ˛āĻā§āĻˇāĻŋāĻ¤ āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻ¨ āĻāĻ°āĻ¤ā§ āĻ¸āĻā§āĻˇāĻŽ āĻšāĻāĻ¯āĻŧāĻžāĻ° āĻāĻ¨ā§āĻ¯, āĻāĻāĻŋāĻ° āĻ¸āĻžāĻŽāĻ¨ā§ āĻ
āĻ¨ā§āĻ¯ āĻā§āĻ¨āĻ āĻ¸āĻ¤ā§āĻ¤āĻž āĻĨāĻžāĻāĻž āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ āĻ¯āĻž āĻāĻāĻŋāĻ° āĻĒā§āĻ°āĻ¤āĻŋāĻ¸ā§āĻĨāĻžāĻĒāĻ¨āĻā§ āĻāĻĄāĻŧāĻžāĻ˛ āĻāĻ°āĻŦā§āĨ¤ āĻāĻāĻŋ āĻāĻāĻāĻŋ āĻāĻ¯āĻŧā§āĻŦ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ° āĻšāĻ¤ā§ āĻĒāĻžāĻ°ā§
āĻ
ā§āĻ¯āĻžāĻĒā§āĻ˛āĻŋāĻā§āĻļāĻ¨ āĻāĻŦāĻ āĻŦāĻŋāĻĒāĻ°ā§āĻ¤ āĻĒā§āĻ°āĻā§āĻ¸āĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§ āĻĄāĻāĻžāĻ° āĻāĻŋāĻ¤āĻ°ā§ āĻ˛āĻŋāĻā§āĻ āĻāĻ°āĻž āĻ¯ā§āĻ¤ā§ āĻĒāĻžāĻ°ā§
āĻ¯āĻĻāĻŋ āĻŦāĻŋāĻĒāĻ°ā§āĻ¤ āĻĒā§āĻ°āĻā§āĻ¸āĻŋ āĻ
āĻ¨ā§āĻ¯ āĻšā§āĻ¸ā§āĻā§ āĻĨāĻžāĻā§, āĻ¤āĻžāĻšāĻ˛ā§ āĻāĻĒāĻ¨āĻžāĻā§ āĻĄāĻāĻžāĻ° āĻ¨ā§āĻāĻāĻ¯āĻŧāĻžāĻ°ā§āĻ āĻĒāĻ°āĻŋāĻ¤ā§āĻ¯āĻžāĻ āĻāĻ°āĻ¤ā§ āĻšāĻŦā§ āĻāĻŦāĻ āĻšā§āĻ¸ā§āĻ āĻ¨ā§āĻāĻāĻ¯āĻŧāĻžāĻ°ā§āĻā§āĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻ°āĻŋāĻāĻžāĻ°ā§āĻ¸ āĻĒā§āĻ°āĻā§āĻ¸āĻŋāĻ° āĻ¸āĻžāĻĨā§ āĻ
ā§āĻ¯āĻžāĻĒā§āĻ˛āĻŋāĻā§āĻļāĻ¨āĻāĻŋāĻā§ āĻ¸āĻāĻ¯ā§āĻā§āĻ¤ āĻāĻ°āĻ¤ā§ āĻšāĻŦā§, āĻĒā§āĻ°ā§āĻ āĻĢāĻ°āĻāĻ¯āĻŧāĻžāĻ°ā§āĻĄ āĻāĻ°ā§ āĻ
ā§āĻ¯āĻžāĻĒāĻ¸ āĻĒā§āĻ¯āĻžāĻ°āĻžāĻŽāĻŋāĻāĻžāĻ° --publish
, āĻĒā§āĻ°āĻĨāĻŽ āĻļā§āĻ°ā§āĻ¤ā§ āĻāĻŦāĻ āĻŦāĻŋāĻĒāĻ°ā§āĻ¤ āĻĒā§āĻ°āĻā§āĻ¸āĻŋāĻ° āĻŽāĻ¤ā§āĨ¤
āĻāĻŽāĻ°āĻž āĻĒā§āĻ°ā§āĻ 80-āĻ āĻŦāĻŋāĻĒāĻ°ā§āĻ¤ āĻĒā§āĻ°āĻā§āĻ¸āĻŋ āĻāĻžāĻ˛āĻžāĻŦ, āĻāĻžāĻ°āĻŖ āĻāĻāĻŋ āĻ āĻŋāĻ āĻ¸ā§āĻ āĻ¸āĻ¤ā§āĻ¤āĻž āĻ¯āĻž āĻŦāĻžāĻšā§āĻ¯āĻŋāĻ āĻ¨ā§āĻāĻāĻ¯āĻŧāĻžāĻ°ā§āĻ āĻļā§āĻ¨āĻ¤ā§ āĻšāĻŦā§āĨ¤ āĻ¯āĻĻāĻŋ āĻĒā§āĻ°ā§āĻ 80 āĻāĻĒāĻ¨āĻžāĻ° āĻā§āĻ¸ā§āĻ āĻšā§āĻ¸ā§āĻā§ āĻŦā§āĻ¯āĻ¸ā§āĻ¤ āĻĨāĻžāĻā§, āĻ¤āĻžāĻšāĻ˛ā§ āĻĒā§āĻ¯āĻžāĻ°āĻžāĻŽāĻŋāĻāĻžāĻ° āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻ¨ āĻāĻ°ā§āĻ¨ --publish 80:80
āĻāĻĒāĻ° --publish ANY_FREE_PORT:80
.
āĻāĻāĻ°ā§āĻˇāĻŖā§āĻ¯āĻŧ āĻā§āĻļāĻ˛
- "āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°āĻāĻžāĻ°ā§ āĻĻā§āĻŦāĻžāĻ°āĻž āĻ¤ā§āĻ°āĻŋ āĻĄāĻāĻžāĻ° āĻ¨ā§āĻāĻāĻ¯āĻŧāĻžāĻ°ā§āĻāĻā§āĻ˛āĻŋāĻ¤ā§, āĻāĻĒāĻ¨āĻŋ āĻā§āĻŦāĻ˛ āĻāĻāĻĒāĻŋ āĻ āĻŋāĻāĻžāĻ¨āĻžāĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻ¨āĻ¯āĻŧ āĻāĻ¨ā§āĻā§āĻāĻ¨āĻžāĻ°āĻā§āĻ˛āĻŋāĻ° āĻ¸āĻžāĻĨā§ āĻ¯ā§āĻāĻžāĻ¯ā§āĻ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨ā§ˇ āĻāĻ¨ā§āĻā§āĻāĻ¨āĻžāĻ°ā§āĻ° āĻ¨āĻžāĻŽāĻāĻŋ āĻ¤āĻžāĻ° IP āĻ āĻŋāĻāĻžāĻ¨āĻžāĻ¤ā§āĻ āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ āĻāĻ°āĻž āĻšāĻ¯āĻŧā§āĻā§" (
āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§ "āĻ¸ā§āĻŦāĻ¤āĻ¨ā§āĻ¤ā§āĻ° āĻāĻ¨ā§āĻā§āĻāĻ¨āĻžāĻ°āĻā§āĻ˛āĻŋāĻ° āĻ¸āĻžāĻĨā§ āĻ¨ā§āĻāĻāĻ¯āĻŧāĻžāĻ°ā§āĻāĻŋāĻ", āĻ āĻāĻļ "āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°āĻāĻžāĻ°ā§-āĻ¸āĻāĻā§āĻāĻžāĻ¯āĻŧāĻŋāĻ¤ āĻŦā§āĻ°āĻŋāĻ āĻ¨ā§āĻāĻāĻ¯āĻŧāĻžāĻ°ā§āĻ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§āĻ¨" , āĻĄāĻāĻžāĻ° āĻā§āĻĄā§āĻ° āĻĒāĻ¯āĻŧā§āĻ¨ā§āĻ 5)āĨ¤
āĻĒā§āĻ°āĻŋāĻ¨ā§āĻāĻāĻāĻ
$ 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>
āĻŦāĻŋāĻ°āĻžāĻŽāĻšā§āĻ¨ āĻ¸ā§āĻĨāĻžāĻĒāĻ¨āĻž
āĻāĻ¸ā§āĻ¨ āĻ ā§āĻ¯āĻžāĻĒā§āĻ˛āĻŋāĻā§āĻļāĻ¨āĻāĻŋāĻ° āĻāĻāĻāĻŋ āĻ¨āĻ¤ā§āĻ¨ āĻ¸āĻāĻ¸ā§āĻāĻ°āĻŖ āĻ°ā§āĻ˛ āĻāĻāĻ āĻāĻ°āĻŋ (āĻāĻāĻāĻŋ āĻĻā§āĻŦāĻŋāĻā§āĻŖ āĻ¸ā§āĻāĻžāĻ°ā§āĻāĻāĻĒ āĻĒāĻžāĻ°āĻĢāĻ°āĻŽā§āĻ¯āĻžāĻ¨ā§āĻ¸ āĻŦā§āĻ¸ā§āĻ āĻ¸āĻš) āĻāĻŦāĻ āĻāĻāĻŋ āĻ¨āĻŋāĻ°ā§āĻŦāĻŋāĻā§āĻ¨ā§ āĻ¸ā§āĻĨāĻžāĻĒāĻ¨ āĻāĻ°āĻžāĻ° āĻā§āĻˇā§āĻāĻž āĻāĻ°āĻŋāĨ¤
āĻāĻāĻ°ā§āĻˇāĻŖā§āĻ¯āĻŧ āĻā§āĻļāĻ˛
echo 'my text' | docker exec -i my-container sh -c 'cat > /my-file.txt'
- āĻĒāĻžāĻ ā§āĻ¯ āĻ˛āĻŋāĻā§āĻ¨my text
āĻ¨āĻĨāĻŋāĻ¤ā§/my-file.txt
āĻĒāĻžāĻ¤ā§āĻ°ā§āĻ° āĻāĻŋāĻ¤āĻ°ā§my-container
.cat > /my-file.txt
â āĻāĻāĻāĻŋ āĻĢāĻžāĻāĻ˛ā§ āĻ¸ā§āĻā§āĻ¯āĻžāĻ¨ā§āĻĄāĻžāĻ°ā§āĻĄ āĻāĻ¨āĻĒā§āĻā§āĻ° āĻŦāĻŋāĻˇāĻ¯āĻŧāĻŦāĻ¸ā§āĻ¤ā§ āĻ˛āĻŋāĻā§āĻ¨/dev/stdin
.
āĻĒā§āĻ°āĻŋāĻ¨ā§āĻāĻāĻāĻ
$ 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 āĻā§āĻŖ āĻŦā§āĻļāĻŋāĨ¤ āĻ¤āĻžāĻ āĻāĻ¸ā§āĻ¨ āĻ¸āĻŽāĻ¯āĻŧ āĻāĻŦāĻ āĻā§āĻ°āĻžāĻĢāĻŋāĻ āĻ¸āĻžāĻļā§āĻ°āĻ¯āĻŧā§āĻ° āĻ¨āĻžāĻŽā§ āĻāĻāĻŋāĻā§ āĻāĻžāĻāĻā§āĻ¨āĻŋ āĻĻā§āĻāĻ¯āĻŧāĻž āĻ¯āĻžāĻ:
$ docker image save uptimer | gzip | ssh production-server 'zcat | docker image load'
Loaded image: uptimer:latest
āĻāĻĒāĻ¨āĻŋ āĻĄāĻžāĻāĻ¨āĻ˛ā§āĻĄ āĻāĻ°āĻžāĻ° āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻžāĻāĻŋāĻ āĻ¨āĻŋāĻ°ā§āĻā§āĻˇāĻŖ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨ (āĻ¯āĻĻāĻŋāĻ āĻāĻāĻŋāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻāĻāĻŋ āĻ¤ā§āĻ¤ā§āĻ¯āĻŧ āĻĒāĻā§āĻˇā§āĻ° āĻāĻāĻāĻŋāĻ˛āĻŋāĻāĻŋ āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨):
$ docker image save uptimer | gzip | pv | ssh production-server 'zcat | docker image load'
25,7MiB 0:01:01 [ 425KiB/s] [ <=> ]
Loaded image: uptimer:latest
āĻāĻŋāĻĒ: SSH āĻāĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°ā§āĻ° āĻ¸āĻžāĻĨā§ āĻ¸āĻāĻ¯ā§āĻ āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻĒāĻ¨āĻžāĻ° āĻ¯āĻĻāĻŋ āĻāĻāĻā§āĻā§āĻ āĻĒā§āĻ¯āĻžāĻ°āĻžāĻŽāĻŋāĻāĻžāĻ°ā§āĻ° āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ āĻšāĻ¯āĻŧ, āĻāĻĒāĻ¨āĻŋ āĻĢāĻžāĻāĻ˛āĻāĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ¨āĻžāĻ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨
~/.ssh/config
.
āĻāĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻāĻŦāĻŋ āĻ¸ā§āĻĨāĻžāĻ¨āĻžāĻ¨ā§āĻ¤āĻ° āĻāĻ°āĻž āĻšāĻā§āĻā§ docker image save/load
- āĻāĻāĻŋ āĻ¸āĻŦāĻā§āĻ¯āĻŧā§ āĻ¸āĻāĻā§āĻˇāĻŋāĻĒā§āĻ¤ āĻĒāĻĻā§āĻ§āĻ¤āĻŋ, āĻ¤āĻŦā§ āĻāĻāĻŽāĻžāĻ¤ā§āĻ° āĻ¨āĻ¯āĻŧāĨ¤ āĻ
āĻ¨ā§āĻ¯āĻžāĻ¨ā§āĻ¯ āĻāĻā§:
- āĻāĻ¨ā§āĻā§āĻāĻ¨āĻžāĻ° āĻ°ā§āĻāĻŋāĻ¸ā§āĻā§āĻ°āĻŋ (āĻļāĻŋāĻ˛ā§āĻĒ āĻŽāĻžāĻ¨)āĨ¤
- āĻ
āĻ¨ā§āĻ¯ āĻšā§āĻ¸ā§āĻ āĻĨā§āĻā§ āĻĄāĻāĻžāĻ° āĻĄā§āĻŽāĻ¨ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°ā§āĻ° āĻ¸āĻžāĻĨā§ āĻ¸āĻāĻ¯ā§āĻ āĻāĻ°ā§āĻ¨:
- āĻĒāĻ°āĻŋāĻŦā§āĻļ āĻ¸ā§āĻāĻ
DOCKER_HOST
. - āĻāĻŽāĻžāĻ¨ā§āĻĄ āĻ˛āĻžāĻāĻ¨ āĻŦāĻŋāĻāĻ˛ā§āĻĒ
-H
āĻŦāĻž--host
āĻ¯āĻ¨ā§āĻ¤ā§āĻ°docker-compose
. docker context
- āĻĒāĻ°āĻŋāĻŦā§āĻļ āĻ¸ā§āĻāĻ
āĻĻā§āĻŦāĻŋāĻ¤ā§āĻ¯āĻŧ āĻĒāĻĻā§āĻ§āĻ¤āĻŋ (āĻāĻ° āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ā§āĻ° āĻāĻ¨ā§āĻ¯ āĻ¤āĻŋāĻ¨āĻāĻŋ āĻŦāĻŋāĻāĻ˛ā§āĻĒ āĻ¸āĻš) āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§ā§ āĻāĻžāĻ˛āĻāĻžāĻŦā§ āĻŦāĻ°ā§āĻŖāĻ¨āĻž āĻāĻ°āĻž āĻšāĻ¯āĻŧā§āĻā§
deploy.sh
āĻāĻāĻ¨ āĻāĻ āĻ¸ā§āĻā§āĻ°āĻŋāĻĒā§āĻā§ āĻŽā§āĻ¯āĻžāĻ¨ā§āĻ¯āĻŧāĻžāĻ˛āĻŋ āĻāĻ°āĻž āĻ¸āĻŦāĻāĻŋāĻā§ āĻ¸āĻāĻā§āĻ°āĻš āĻāĻ°āĻž āĻ¯āĻžāĻāĨ¤ āĻāĻ˛ā§āĻ¨ āĻļā§āĻ°ā§ āĻāĻ°āĻž āĻ¯āĻžāĻ āĻļā§āĻ°ā§āĻˇ-āĻ¸ā§āĻ¤āĻ°ā§āĻ° āĻĢāĻžāĻāĻļāĻ¨ āĻĻāĻŋāĻ¯āĻŧā§, āĻāĻŦāĻ āĻ¤āĻžāĻ°āĻĒāĻ°ā§ āĻāĻ¤ā§ āĻŦā§āĻ¯āĻŦāĻšā§āĻ¤ āĻ āĻ¨ā§āĻ¯āĻā§āĻ˛ā§ āĻĻā§āĻā§āĻ¨āĨ¤
āĻāĻāĻ°ā§āĻˇāĻŖā§āĻ¯āĻŧ āĻā§āĻļāĻ˛
${parameter?err_msg}
- āĻŦā§āĻ¯āĻžāĻļ āĻāĻžāĻĻā§ āĻŽāĻ¨ā§āĻ¤ā§āĻ°āĻā§āĻ˛āĻŋāĻ° āĻŽāĻ§ā§āĻ¯ā§ āĻāĻāĻāĻŋ (āĻāĻ°āĻĢā§āĻĒāĻ°āĻžāĻŽāĻŋāĻ¤āĻŋ āĻĒā§āĻ°āĻ¤āĻŋāĻ¸ā§āĻĨāĻžāĻĒāĻ¨ )āĨ¤ āĻ¯āĻĻāĻŋ āĻāĻāĻāĻŋ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
}
āĻŦā§āĻ¯āĻŦāĻšā§āĻ¤ āĻŦā§āĻļāĻŋāĻˇā§āĻā§āĻ¯:
ensure-reverse-proxy
- āĻ¨āĻŋāĻļā§āĻāĻŋāĻ¤ āĻāĻ°ā§āĻ¨ āĻ¯ā§ āĻŦāĻŋāĻĒāĻ°ā§āĻ¤ āĻĒā§āĻ°āĻā§āĻ¸āĻŋ āĻāĻžāĻ āĻāĻ°āĻā§ (āĻĒā§āĻ°āĻĨāĻŽ āĻ¸ā§āĻĨāĻžāĻĒāĻ¨āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻĻāĻ°āĻāĻžāĻ°ā§)get-active-slot service_name
â āĻāĻāĻāĻŋ āĻĒā§āĻ°āĻĻāĻ¤ā§āĻ¤ āĻĒāĻ°āĻŋāĻˇā§āĻŦāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻŦāĻ°ā§āĻ¤āĻŽāĻžāĻ¨ā§ āĻā§āĻ¨ āĻ¸ā§āĻ˛āĻ āĻ¸āĻā§āĻ°āĻŋāĻ¯āĻŧ āĻ¤āĻž āĻ¨āĻŋāĻ°ā§āĻ§āĻžāĻ°āĻŖ āĻāĻ°ā§ (BLUE
āĻŦāĻžGREEN
)get-service-status service_name deployment_slot
- āĻāĻāĻ¤ āĻ āĻ¨ā§āĻ°ā§āĻ§āĻā§āĻ˛āĻŋ āĻĒā§āĻ°āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻĒāĻ°āĻŋāĻˇā§āĻŦāĻž āĻĒā§āĻ°āĻ¸ā§āĻ¤ā§āĻ¤ āĻāĻŋāĻ¨āĻž āĻ¤āĻž āĻ¨āĻŋāĻ°ā§āĻ§āĻžāĻ°āĻŖ āĻāĻ°ā§set-active-slot service_name deployment_slot
- āĻŦāĻŋāĻĒāĻ°ā§āĻ¤ āĻĒā§āĻ°āĻā§āĻ¸āĻŋ āĻāĻ¨ā§āĻā§āĻāĻ¨āĻžāĻ°ā§ nginx āĻāĻ¨āĻĢāĻŋāĻāĻžāĻ°ā§āĻļāĻ¨ āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻ¨ āĻāĻ°ā§
āĻā§āĻ°āĻŽ:
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
}
āĻā§āĻ°āĻŋāĻ¯āĻŧāĻž get-active-slot
āĻāĻāĻā§ āĻŦā§āĻ¯āĻžāĻā§āĻ¯āĻž āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨:
āĻā§āĻ¨ āĻāĻāĻŋ āĻāĻāĻāĻŋ āĻ¸āĻāĻā§āĻ¯āĻž āĻĢā§āĻ°āĻ¤ āĻĻā§āĻ¯āĻŧ āĻāĻŦāĻ āĻāĻāĻāĻŋ āĻ¸ā§āĻā§āĻ°āĻŋāĻ āĻāĻāĻāĻĒā§āĻ āĻ¨āĻž?
āĻ¯āĻžāĻāĻšā§āĻ, āĻāĻ˛āĻŋāĻ āĻĢāĻžāĻāĻļāĻ¨ā§ āĻāĻŽāĻ°āĻž āĻāĻ° āĻāĻžāĻā§āĻ° āĻĢāĻ˛āĻžāĻĢāĻ˛ āĻĒāĻ°ā§āĻā§āĻˇāĻž āĻāĻ°āĻŋ āĻāĻŦāĻ āĻŦā§āĻ¯āĻžāĻļ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°ā§ āĻāĻā§āĻ¸āĻŋāĻ āĻā§āĻĄ āĻā§āĻ āĻāĻ°āĻž āĻ¸ā§āĻā§āĻ°āĻŋāĻ āĻā§āĻ āĻāĻ°āĻžāĻ° āĻā§āĻ¯āĻŧā§ āĻ
āĻ¨ā§āĻ āĻ¸āĻšāĻāĨ¤ āĻāĻĒāĻ°āĻ¨ā§āĻ¤ā§, āĻāĻāĻŋ āĻĨā§āĻā§ āĻāĻāĻāĻŋ āĻ¸ā§āĻā§āĻ°āĻŋāĻ āĻĒāĻžāĻāĻ¯āĻŧāĻž āĻā§āĻŦ āĻ¸āĻšāĻ:
get-active-slot service && echo BLUE || echo GREEN
.
āĻ¤āĻŋāĻ¨āĻāĻŋ āĻļāĻ°ā§āĻ¤ āĻāĻŋ āĻ¸āĻ¤ā§āĻ¯āĻŋāĻ āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻ°āĻžāĻā§āĻ¯āĻā§ āĻāĻ˛āĻžāĻĻāĻž āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻ¯āĻĨā§āĻˇā§āĻ?
āĻāĻŽāĻ¨āĻāĻŋ āĻĻā§āĻāĻŋ āĻ¯āĻĨā§āĻˇā§āĻ āĻšāĻŦā§, āĻļā§āĻˇāĻāĻŋ āĻāĻāĻžāĻ¨ā§ āĻ¸āĻŽā§āĻĒā§āĻ°ā§āĻŖāĻ¤āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻ°āĻ¯āĻŧā§āĻā§, āĻ¯āĻžāĻ¤ā§ āĻ˛āĻŋāĻāĻ¤ā§ āĻ¨āĻž āĻšāĻ¯āĻŧ else
.
āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻ¯ā§ āĻĢāĻžāĻāĻļāĻ¨āĻāĻŋ nginx āĻāĻ¨āĻĢāĻŋāĻāĻžāĻ°ā§āĻļāĻ¨ āĻĒā§āĻ°āĻĻāĻžāĻ¨ āĻāĻ°ā§ āĻ¤āĻž āĻ
āĻ¨āĻŋāĻ°ā§āĻ§āĻžāĻ°āĻŋāĻ¤ āĻĨāĻžāĻā§: get-nginx-config service_name deployment_slot
. āĻ¸ā§āĻŦāĻžāĻ¸ā§āĻĨā§āĻ¯ āĻĒāĻ°ā§āĻā§āĻˇāĻžāĻ° āĻ¸āĻžāĻĨā§ āĻ¸āĻžāĻĻā§āĻļā§āĻ¯ āĻĻā§āĻŦāĻžāĻ°āĻž, āĻāĻāĻžāĻ¨ā§ āĻāĻĒāĻ¨āĻŋ āĻ¯ā§ āĻā§āĻ¨āĻ āĻĒāĻ°āĻŋāĻˇā§āĻŦāĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻ¯ā§ āĻā§āĻ¨āĻ āĻāĻ¨āĻĢāĻŋāĻāĻžāĻ°ā§āĻļāĻ¨ āĻ¸ā§āĻ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨āĨ¤ āĻāĻāĻ°ā§āĻˇāĻŖā§āĻ¯āĻŧ āĻāĻŋāĻ¨āĻŋāĻ¸ - āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° cat <<- EOF
, āĻ¯āĻž āĻāĻĒāĻ¨āĻžāĻā§ āĻļā§āĻ°ā§āĻ¤ā§ āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻā§āĻ¯āĻžāĻŦ āĻ¸āĻ°āĻžāĻ¤ā§ āĻĻā§āĻ¯āĻŧāĨ¤ āĻ¸āĻ¤ā§āĻ¯, āĻāĻžāĻ˛ āĻŦāĻŋāĻ¨ā§āĻ¯āĻžāĻ¸ā§āĻ° āĻŽā§āĻ˛ā§āĻ¯ āĻšāĻ˛ āĻ¸ā§āĻĒā§āĻ¸ āĻ¸āĻš āĻŽāĻŋāĻļā§āĻ° āĻā§āĻ¯āĻžāĻŦ, āĻ¯āĻž āĻāĻāĻā§ āĻā§āĻŦ āĻāĻžāĻ°āĻžāĻĒ āĻĢāĻ°ā§āĻŽ āĻšāĻŋāĻ¸āĻžāĻŦā§ āĻŦāĻŋāĻŦā§āĻāĻŋāĻ¤ āĻšāĻ¯āĻŧāĨ¤ āĻāĻŋāĻ¨ā§āĻ¤ā§ āĻŦā§āĻ¯āĻžāĻļ āĻā§āĻ¯āĻžāĻŦāĻā§āĻ˛āĻŋāĻā§ āĻā§āĻ° āĻāĻ°ā§, āĻāĻŦāĻ nginx āĻāĻ¨āĻĢāĻŋāĻāĻžāĻ°ā§āĻļāĻ¨ā§ āĻ¸ā§āĻŦāĻžāĻāĻžāĻŦāĻŋāĻ āĻŦāĻŋāĻ¨ā§āĻ¯āĻžāĻ¸ āĻāĻ°āĻžāĻ āĻāĻžāĻ˛ āĻšāĻŦā§āĨ¤ āĻ¸āĻāĻā§āĻˇā§āĻĒā§, āĻāĻāĻžāĻ¨ā§ āĻ¸ā§āĻĒā§āĻ¸āĻā§āĻ˛āĻŋāĻ° āĻ¸āĻžāĻĨā§ āĻā§āĻ¯āĻžāĻŦāĻā§āĻ˛āĻŋāĻā§ āĻŽāĻŋāĻļā§āĻ°āĻŋāĻ¤ āĻāĻ°āĻž āĻ¸āĻ¤ā§āĻ¯āĻŋāĻ āĻāĻžāĻ°āĻžāĻĒā§āĻ° āĻŽāĻ§ā§āĻ¯ā§ āĻ¸ā§āĻ°āĻž āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ āĻŦāĻ˛ā§ āĻŽāĻ¨ā§ āĻšāĻā§āĻā§āĨ¤ āĻ¯āĻžāĻāĻšā§āĻ, āĻāĻĒāĻ¨āĻŋ āĻ¨ā§āĻā§āĻ° āĻ¸ā§āĻ¨āĻŋāĻĒā§āĻā§ āĻāĻāĻŋ āĻĻā§āĻāĻ¤ā§ āĻĒāĻžāĻŦā§āĻ¨ āĻ¨āĻž, āĻ¯ā§āĻšā§āĻ¤ā§ Habr āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻā§āĻ¯āĻžāĻŦāĻā§āĻ˛āĻŋāĻā§ 4āĻāĻŋ āĻ¸ā§āĻĒā§āĻ¸ā§ āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤āĻ¨ āĻāĻ°ā§ āĻāĻŦāĻ EOF āĻ
āĻŦā§āĻ§ āĻāĻ°ā§ "āĻāĻāĻŋ āĻāĻžāĻ˛ āĻāĻ°ā§"āĨ¤
āĻ¯āĻžāĻ¤ā§ āĻĻā§āĻŦāĻžāĻ° āĻāĻ āĻ¤ā§ āĻ¨āĻž āĻšāĻ¯āĻŧ, āĻāĻŽāĻŋ āĻāĻāĻ¨āĻ āĻāĻĒāĻ¨āĻžāĻā§ āĻŦāĻ˛āĻŦ
cat << 'EOF'
, āĻ¯āĻž āĻĒāĻ°ā§ āĻ¸āĻŽā§āĻŽā§āĻā§āĻ¨ āĻšāĻŦā§. āĻ¸āĻšāĻāĻāĻžāĻŦā§ āĻ˛āĻŋāĻāĻ˛ā§cat << EOF
, āĻ¤āĻžāĻ°āĻĒāĻ° heredoc āĻāĻ° āĻāĻŋāĻ¤āĻ°ā§ āĻ¸ā§āĻā§āĻ°āĻŋāĻāĻāĻŋ āĻāĻ¨ā§āĻāĻžāĻ°āĻĒā§āĻ˛ā§āĻ āĻāĻ°āĻž āĻšāĻ¯āĻŧ (āĻā§āĻ°āĻŋāĻ¯āĻŧā§āĻŦāĻ˛āĻā§āĻ˛āĻŋ āĻĒā§āĻ°āĻ¸āĻžāĻ°āĻŋāĻ¤ āĻšāĻ¯āĻŧ ($foo
), āĻāĻŽāĻžāĻ¨ā§āĻĄ āĻāĻ˛ ($(bar)
) āĻāĻ¤ā§āĻ¯āĻžāĻĻāĻŋ), āĻāĻŦāĻ āĻāĻĒāĻ¨āĻŋ āĻ¯āĻĻāĻŋ āĻ¨āĻĨāĻŋāĻ° āĻļā§āĻˇāĻāĻŋ āĻāĻāĻ āĻāĻĻā§āĻ§ā§āĻ¤āĻŋāĻ¤ā§ āĻāĻŦāĻĻā§āĻ§ āĻāĻ°ā§āĻ¨, āĻ¤āĻžāĻšāĻ˛ā§ āĻāĻ¨ā§āĻāĻžāĻ°āĻĒā§āĻ˛ā§āĻļāĻ¨ āĻ āĻā§āĻˇāĻŽ āĻāĻŦāĻ āĻĒā§āĻ°āĻ¤ā§āĻ$
āĻšāĻŋāĻ¸āĻžāĻŦā§ āĻĒā§āĻ°āĻĻāĻ°ā§āĻļāĻŋāĻ¤ āĻšāĻ¯āĻŧ. āĻāĻĒāĻ¨āĻŋ āĻ āĻ¨ā§āĻ¯ āĻ¸ā§āĻā§āĻ°āĻŋāĻĒā§āĻ āĻāĻŋāĻ¤āĻ°ā§ āĻāĻāĻāĻŋ āĻ¸ā§āĻā§āĻ°āĻŋāĻĒā§āĻ āĻ¸āĻ¨ā§āĻ¨āĻŋāĻŦā§āĻļ āĻāĻ°āĻž āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ āĻāĻŋ.
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.
āĻāĻŽāĻ°āĻž āĻāĻāĻāĻŋ āĻ¸ā§āĻĨāĻžāĻĒāĻ¨āĻžāĻ° āĻ¸ā§āĻā§āĻ°āĻŋāĻĒā§āĻ āĻ˛āĻŋāĻā§āĻāĻŋ āĻ¯āĻž āĻ˛āĻā§āĻˇā§āĻ¯ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°ā§ āĻāĻāĻāĻŋ āĻĒā§āĻ°ā§āĻŦ-āĻ¨āĻŋāĻ°ā§āĻŽāĻŋāĻ¤ āĻāĻŋāĻ¤ā§āĻ° āĻĄāĻžāĻāĻ¨āĻ˛ā§āĻĄ āĻāĻ°ā§ āĻāĻŦāĻ āĻ¨āĻŋāĻ°ā§āĻŦāĻŋāĻā§āĻ¨ā§ āĻĒāĻ°āĻŋāĻˇā§āĻŦāĻž āĻ§āĻžāĻ°āĻāĻāĻŋ āĻĒā§āĻ°āĻ¤āĻŋāĻ¸ā§āĻĨāĻžāĻĒāĻ¨ āĻāĻ°ā§, āĻ¤āĻŦā§ āĻāĻŽāĻ°āĻž āĻā§āĻāĻžāĻŦā§ āĻāĻāĻŋ āĻāĻāĻāĻŋ āĻĻā§āĻ°āĻŦāĻ°ā§āĻ¤ā§ āĻŽā§āĻļāĻŋāĻ¨ā§ āĻāĻžāĻ°ā§āĻ¯āĻāĻ° āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°āĻŋ? āĻ¸ā§āĻā§āĻ°āĻŋāĻĒā§āĻāĻāĻŋāĻ¤ā§ āĻ¯ā§āĻā§āĻ¤āĻŋ āĻ°āĻ¯āĻŧā§āĻā§, āĻ¯ā§āĻšā§āĻ¤ā§ āĻāĻāĻŋ āĻ¸āĻ°ā§āĻŦāĻāĻ¨ā§āĻ¨ āĻāĻŦāĻ āĻāĻāĻāĻŋ āĻŦāĻŋāĻĒāĻ°ā§āĻ¤ āĻĒā§āĻ°āĻā§āĻ¸āĻŋāĻ° āĻ āĻ§ā§āĻ¨ā§ āĻāĻāĻ¸āĻžāĻĨā§ āĻŦā§āĻļ āĻāĻ¯āĻŧā§āĻāĻāĻŋ āĻĒāĻ°āĻŋāĻˇā§āĻŦāĻž āĻ¸ā§āĻĨāĻžāĻĒāĻ¨ āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§ (āĻā§āĻ¨ url āĻā§āĻ¨ āĻĒāĻ°āĻŋāĻˇā§āĻŦāĻž āĻšāĻŦā§ āĻ¤āĻž āĻ¨āĻŋāĻ°ā§āĻ§āĻžāĻ°āĻŖ āĻāĻ°āĻ¤ā§ āĻāĻĒāĻ¨āĻŋ nginx āĻāĻ¨āĻĢāĻŋāĻāĻžāĻ°ā§āĻļāĻ¨ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻāĻ°āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨)āĨ¤ āĻ¸ā§āĻā§āĻ°āĻŋāĻĒā§āĻāĻāĻŋ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°ā§ āĻ¸āĻāĻ°āĻā§āĻˇāĻŖ āĻāĻ°āĻž āĻ¯āĻžāĻŦā§ āĻ¨āĻž, āĻ¯ā§āĻšā§āĻ¤ā§ āĻāĻ āĻā§āĻˇā§āĻ¤ā§āĻ°ā§ āĻāĻŽāĻ°āĻž āĻāĻāĻŋ āĻ¸ā§āĻŦāĻ¯āĻŧāĻāĻā§āĻ°āĻŋāĻ¯āĻŧāĻāĻžāĻŦā§ āĻāĻĒāĻĄā§āĻ āĻāĻ°āĻ¤ā§ āĻ¸āĻā§āĻˇāĻŽ āĻšāĻŦ āĻ¨āĻž (āĻŦāĻžāĻ āĻ¸āĻāĻļā§āĻ§āĻ¨ āĻāĻŦāĻ āĻ¨āĻ¤ā§āĻ¨ āĻĒāĻ°āĻŋāĻˇā§āĻŦāĻž āĻ¯ā§āĻ āĻāĻ°āĻžāĻ° āĻāĻĻā§āĻĻā§āĻļā§āĻ¯ā§), āĻāĻŦāĻ āĻ¸āĻžāĻ§āĻžāĻ°āĻŖāĻāĻžāĻŦā§, āĻ°āĻžāĻˇā§āĻā§āĻ° = āĻāĻžāĻ°āĻžāĻĒāĨ¤
āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ 1: āĻāĻāĻ¨āĻ āĻ¸āĻžāĻ°ā§āĻāĻžāĻ°ā§ āĻ¸ā§āĻā§āĻ°āĻŋāĻĒā§āĻ āĻ¸āĻāĻ°āĻā§āĻˇāĻŖ āĻāĻ°ā§āĻ¨, āĻāĻŋāĻ¨ā§āĻ¤ā§ āĻĒā§āĻ°āĻ¤āĻŋāĻŦāĻžāĻ° āĻāĻāĻŋ āĻ
āĻ¨ā§āĻ˛āĻŋāĻĒāĻŋ āĻāĻ°ā§āĻ¨ scp
. āĻ¤āĻžāĻ°āĻĒāĻ° āĻāĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻ¸āĻāĻ¯ā§āĻ āĻāĻ°ā§āĻ¨ ssh
āĻāĻŦāĻ āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ā§āĻ¯āĻŧ āĻāĻ°ā§āĻā§āĻŽā§āĻ¨ā§āĻ āĻ¸āĻš āĻ¸ā§āĻā§āĻ°āĻŋāĻĒā§āĻāĻāĻŋ āĻāĻžāĻ˛āĻžāĻ¨āĨ¤
āĻāĻ¨āĻ¸:
- āĻāĻāĻāĻŋāĻ° āĻĒāĻ°āĻŋāĻŦāĻ°ā§āĻ¤ā§ āĻĻā§āĻāĻŋ āĻāĻ°ā§āĻŽ
- āĻāĻŽāĻ¨ āĻāĻāĻāĻŋ āĻāĻžāĻ¯āĻŧāĻāĻž āĻ¨āĻžāĻ āĻĨāĻžāĻāĻ¤ā§ āĻĒāĻžāĻ°ā§ āĻ¯ā§āĻāĻžāĻ¨ā§ āĻāĻĒāĻ¨āĻŋ āĻāĻĒāĻŋ āĻāĻ°ā§āĻ¨, āĻŦāĻž āĻ¸ā§āĻāĻžāĻ¨ā§ āĻ ā§āĻ¯āĻžāĻā§āĻ¸ā§āĻ¸ āĻ¨āĻžāĻ āĻĨāĻžāĻāĻ¤ā§ āĻĒāĻžāĻ°ā§, āĻŦāĻž āĻĒā§āĻ°āĻ¤āĻŋāĻ¸ā§āĻĨāĻžāĻĒāĻ¨ā§āĻ° āĻ¸āĻŽāĻ¯āĻŧ āĻ¸ā§āĻā§āĻ°āĻŋāĻĒā§āĻāĻāĻŋ āĻāĻžāĻ°ā§āĻ¯āĻāĻ° āĻāĻ°āĻž āĻšāĻ¤ā§ āĻĒāĻžāĻ°ā§āĨ¤
- āĻ¨āĻŋāĻā§āĻ° āĻĒāĻ°ā§ āĻĒāĻ°āĻŋāĻˇā§āĻāĻžāĻ° āĻāĻ°āĻžāĻ° āĻĒāĻ°āĻžāĻŽāĻ°ā§āĻļ āĻĻā§āĻāĻ¯āĻŧāĻž āĻšāĻ¯āĻŧ (āĻ¸ā§āĻā§āĻ°āĻŋāĻĒā§āĻāĻāĻŋ āĻŽā§āĻā§āĻ¨)āĨ¤
- āĻāĻ¤āĻŋāĻŽāĻ§ā§āĻ¯ā§ āĻ¤āĻŋāĻ¨āĻāĻŋ āĻāĻ°ā§āĻŽāĨ¤
āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ 2:
- āĻ¸ā§āĻā§āĻ°āĻŋāĻĒā§āĻā§ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻĢāĻžāĻāĻļāĻ¨ āĻ¸āĻāĻā§āĻāĻž āĻ°āĻžāĻā§āĻ¨ āĻāĻŦāĻ āĻāĻŋāĻā§āĻ āĻāĻžāĻ˛āĻžāĻŦā§āĻ¨ āĻ¨āĻž
- āĻāĻ° āĻ¸āĻžāĻšāĻžāĻ¯ā§āĻ¯ā§
sed
āĻļā§āĻˇā§ āĻāĻāĻāĻŋ āĻĢāĻžāĻāĻļāĻ¨ āĻāĻ˛ āĻ¯ā§āĻ āĻāĻ°ā§āĻ¨ - āĻĒāĻžāĻāĻĒā§āĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻ¸āĻ°āĻžāĻ¸āĻ°āĻŋ shh āĻ āĻ¸āĻŦ āĻĒāĻžāĻ āĻžāĻ¨ (
|
)
āĻĒā§āĻļāĻžāĻĻāĻžāĻ°āĻ°āĻž:
- āĻ¸āĻ¤ā§āĻ¯āĻŋāĻ āĻ°āĻžāĻˇā§āĻā§āĻ°āĻšā§āĻ¨
- āĻā§āĻ¨ā§ āĻŦāĻ¯āĻŧāĻ˛āĻžāĻ°āĻĒā§āĻ˛ā§āĻ āĻ¸āĻ¤ā§āĻ¤āĻž āĻ¨ā§āĻ
- āĻ āĻžāĻŖā§āĻĄāĻž āĻ˛āĻžāĻāĻā§
āĻāĻ° āĻāĻ¤ā§āĻ¤āĻ° āĻāĻžāĻĄāĻŧāĻžāĻ āĻāĻāĻŋ āĻāĻ°āĻž āĻ¯āĻžāĻāĨ¤ āĻšā§āĻ¯āĻžāĻ, āĻ¸āĻŦāĻāĻŋāĻā§ āĻāĻ¤āĻŋāĻŽāĻ§ā§āĻ¯ā§ āĻāĻĻā§āĻāĻžāĻŦāĻŋāĻ¤ āĻšāĻ¯āĻŧā§āĻā§āĨ¤ āĻšā§āĻ¯āĻžāĻ, āĻāĻāĻāĻŋ āĻ¸āĻžāĻāĻā§āĻ˛āĨ¤ āĻŦāĻžāĻāĻāĻāĻŋ āĻāĻ¤āĻāĻž āĻ¸āĻšāĻ, āĻŽāĻžāĻ°ā§āĻāĻŋāĻ¤ āĻāĻŦāĻ āĻŽāĻŋāĻ¨āĻŋāĻŽāĻžāĻ˛āĻŋāĻ¸ā§āĻāĻŋāĻ āĻ¤āĻž āĻĻā§āĻā§āĻ¨:
$ 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!
āĻāĻāĻ¨ āĻāĻĒāĻ¨āĻŋ āĻā§āĻ˛āĻ¤ā§ āĻĒāĻžāĻ°ā§āĻ¨
āĻāĻžāĻā§āĻ° āĻĒāĻ°ā§ āĻĒāĻ°āĻŋāĻˇā§āĻāĻžāĻ° āĻāĻ°āĻ¤ā§ āĻā§āĻ˛āĻŦā§āĻ¨ āĻ¨āĻž :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
āĻāĻ¤ā§āĻ¸: www.habr.com