แƒšแƒฃแƒ แƒฏแƒ˜-แƒ›แƒฌแƒ•แƒแƒœแƒ” แƒ’แƒแƒœแƒšแƒแƒ’แƒ”แƒ‘แƒ แƒ›แƒ˜แƒœแƒ˜แƒ›แƒแƒšแƒฃแƒ แƒ˜ แƒฎแƒ”แƒšแƒคแƒแƒกแƒ˜แƒ—

แƒแƒ› แƒกแƒขแƒแƒขแƒ˜แƒแƒจแƒ˜ แƒฉแƒ•แƒ”แƒœ แƒ•แƒ˜แƒงแƒ”แƒœแƒ”แƒ‘แƒ— Bash, แƒกแƒจ, docker ะธ nginx แƒฉแƒ•แƒ”แƒœ แƒ›แƒแƒ•แƒแƒฌแƒงแƒแƒ‘แƒ— แƒ•แƒ”แƒ‘ แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒ˜แƒก แƒฃแƒฌแƒงแƒ•แƒ”แƒข แƒ’แƒแƒœแƒšแƒแƒ’แƒ”แƒ‘แƒแƒก. แƒšแƒฃแƒ แƒฏแƒ˜-แƒ›แƒฌแƒ•แƒแƒœแƒ” แƒ’แƒแƒœแƒšแƒแƒ’แƒ”แƒ‘แƒ แƒแƒ แƒ˜แƒก แƒขแƒ”แƒฅแƒœแƒ˜แƒ™แƒ, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒกแƒแƒจแƒฃแƒแƒšแƒ”แƒ‘แƒแƒก แƒ’แƒแƒซแƒšแƒ”แƒ•แƒ— แƒ›แƒงแƒ˜แƒกแƒ˜แƒ”แƒ แƒแƒ“ แƒ’แƒแƒœแƒแƒแƒฎแƒšแƒแƒ— แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒ แƒ”แƒ แƒ—แƒ˜ แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ˜แƒก แƒฃแƒแƒ แƒงแƒแƒคแƒ˜แƒก แƒ’แƒแƒ แƒ”แƒจแƒ”. แƒ”แƒก แƒแƒ แƒ˜แƒก แƒ”แƒ แƒ—-แƒ”แƒ แƒ—แƒ˜ แƒœแƒฃแƒšแƒแƒ•แƒแƒœแƒ˜ แƒจแƒ”แƒคแƒ”แƒ แƒฎแƒ”แƒ‘แƒ˜แƒก แƒ’แƒแƒœแƒšแƒแƒ’แƒ”แƒ‘แƒ˜แƒก แƒกแƒขแƒ แƒแƒขแƒ”แƒ’แƒ˜แƒ แƒ“แƒ แƒกแƒแƒฃแƒ™แƒ”แƒ—แƒ”แƒกแƒแƒ“ แƒจแƒ”แƒ”แƒคแƒ”แƒ แƒ”แƒ‘แƒ แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒ”แƒ‘แƒก แƒ”แƒ แƒ—แƒ˜ แƒ”แƒ’แƒ–แƒ”แƒ›แƒžแƒšแƒแƒ แƒ˜แƒ—, แƒ›แƒแƒ’แƒ แƒแƒ› แƒ›แƒแƒฎแƒšแƒแƒ‘แƒšแƒแƒ“ แƒ›แƒ”แƒแƒ แƒ”, แƒ’แƒแƒกแƒแƒจแƒ•แƒ”แƒ‘แƒแƒ“ แƒ›แƒ–แƒ แƒ˜แƒœแƒกแƒขแƒแƒœแƒชแƒ˜แƒ˜แƒก แƒฉแƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ˜แƒก แƒจแƒ”แƒกแƒแƒซแƒšแƒ”แƒ‘แƒšแƒแƒ‘แƒ˜แƒ—.

แƒ“แƒแƒ•แƒฃแƒจแƒ•แƒแƒ—, แƒ แƒแƒ› แƒ—แƒฅแƒ•แƒ”แƒœ แƒ’แƒแƒฅแƒ•แƒ— แƒ•แƒ”แƒ‘ แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒ, แƒ แƒแƒ›แƒšแƒ˜แƒ—แƒแƒช แƒ‘แƒ”แƒ•แƒ แƒ˜ แƒ™แƒšแƒ˜แƒ”แƒœแƒขแƒ˜ แƒแƒฅแƒขแƒ˜แƒฃแƒ แƒแƒ“ แƒ›แƒฃแƒจแƒแƒแƒ‘แƒก แƒ“แƒ แƒ›แƒ˜แƒกแƒ˜ แƒ“แƒแƒฌแƒแƒšแƒ แƒ แƒแƒ›แƒ“แƒ”แƒœแƒ˜แƒ›แƒ” แƒฌแƒแƒ›แƒ˜แƒก แƒ’แƒแƒœแƒ›แƒแƒ•แƒšแƒแƒ‘แƒแƒจแƒ˜ แƒแƒ‘แƒกแƒแƒšแƒฃแƒขแƒฃแƒ แƒแƒ“ แƒแƒ  แƒแƒ แƒ˜แƒก. แƒ“แƒ แƒ—แƒฅแƒ•แƒ”แƒœ แƒœแƒแƒ›แƒ“แƒ•แƒ˜แƒšแƒแƒ“ แƒ’แƒญแƒ˜แƒ แƒ“แƒ”แƒ‘แƒแƒ— แƒ‘แƒ˜แƒ‘แƒšแƒ˜แƒแƒ—แƒ”แƒ™แƒ˜แƒก แƒ’แƒแƒœแƒแƒฎแƒšแƒ”แƒ‘แƒ, แƒจแƒ”แƒชแƒ“แƒแƒ›แƒ”แƒ‘แƒ˜แƒก แƒ’แƒแƒ›แƒแƒกแƒฌแƒแƒ แƒ”แƒ‘แƒ แƒแƒœ แƒแƒฎแƒแƒšแƒ˜ แƒ›แƒแƒ’แƒแƒ แƒ˜ แƒคแƒฃแƒœแƒฅแƒชแƒ˜แƒ. แƒœแƒแƒ แƒ›แƒแƒšแƒฃแƒ  แƒกแƒ˜แƒขแƒฃแƒแƒชแƒ˜แƒแƒจแƒ˜ แƒ›แƒแƒ’แƒ˜แƒฌแƒ”แƒ•แƒ— แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒ˜แƒก แƒจแƒ”แƒฉแƒ”แƒ แƒ”แƒ‘แƒ, แƒจแƒ”แƒชแƒ•แƒšแƒ แƒ“แƒ แƒฎแƒ”แƒšแƒแƒฎแƒšแƒ แƒ“แƒแƒฌแƒงแƒ”แƒ‘แƒ. แƒ“แƒแƒ™แƒ”แƒ แƒ˜แƒก แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜, แƒ—แƒฅแƒ•แƒ”แƒœ แƒจแƒ”แƒ’แƒ˜แƒซแƒšแƒ˜แƒแƒ— แƒฏแƒ”แƒ  แƒจแƒ”แƒชแƒ•แƒแƒšแƒแƒ— แƒ˜แƒ’แƒ˜, แƒจแƒ”แƒ›แƒ“แƒ”แƒ’ แƒ’แƒแƒ“แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒแƒ—, แƒ›แƒแƒ’แƒ แƒแƒ› แƒ›แƒแƒ˜แƒœแƒช แƒ˜แƒฅแƒœแƒ”แƒ‘แƒ แƒžแƒ”แƒ แƒ˜แƒแƒ“แƒ˜, แƒ แƒแƒ“แƒ”แƒกแƒแƒช แƒ’แƒแƒœแƒแƒชแƒฎแƒแƒ“แƒ˜แƒก แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ แƒแƒ  แƒ’แƒแƒœแƒ˜แƒฎแƒ˜แƒšแƒ”แƒ‘แƒ, แƒ แƒแƒ“แƒ’แƒแƒœ, แƒ แƒแƒ’แƒแƒ แƒช แƒฌแƒ”แƒกแƒ˜, แƒ’แƒแƒœแƒแƒชแƒฎแƒแƒ“แƒ˜แƒก แƒ—แƒแƒ•แƒ˜แƒ“แƒแƒœ แƒฉแƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒแƒก แƒ’แƒแƒ แƒ™แƒ•แƒ”แƒฃแƒšแƒ˜ แƒ“แƒ แƒ แƒกแƒญแƒ˜แƒ แƒ“แƒ”แƒ‘แƒ. แƒ แƒ แƒ›แƒแƒฎแƒ“แƒ”แƒ‘แƒ, แƒ—แƒฃ แƒ˜แƒก แƒ˜แƒฌแƒงแƒ”แƒ‘แƒ, แƒ›แƒแƒ’แƒ แƒแƒ› แƒแƒฆแƒ›แƒแƒฉแƒœแƒ“แƒ”แƒ‘แƒ, แƒ แƒแƒ› แƒฃแƒ›แƒแƒฅแƒ›แƒ”แƒ“แƒแƒ? แƒ”แƒก แƒแƒ แƒ˜แƒก แƒžแƒ แƒแƒ‘แƒšแƒ”แƒ›แƒ, แƒ›แƒแƒ•แƒแƒ’แƒ•แƒแƒ แƒแƒ— แƒ›แƒ˜แƒœแƒ˜แƒ›แƒแƒšแƒฃแƒ แƒ˜ แƒกแƒแƒจแƒฃแƒแƒšแƒ”แƒ‘แƒ”แƒ‘แƒ˜แƒ— แƒ“แƒ แƒ แƒแƒช แƒจแƒ”แƒ˜แƒซแƒšแƒ”แƒ‘แƒ แƒ”แƒšแƒ”แƒ’แƒแƒœแƒขแƒฃแƒ แƒแƒ“.

แƒžแƒแƒกแƒฃแƒฎแƒ˜แƒกแƒ›แƒ’แƒ”แƒ‘แƒšแƒแƒ‘แƒ˜แƒก แƒฃแƒแƒ แƒงแƒแƒคแƒ: แƒกแƒขแƒแƒขแƒ˜แƒ˜แƒก แƒฃแƒ›แƒ”แƒขแƒ”แƒกแƒแƒ‘แƒ แƒฌแƒแƒ แƒ›แƒแƒ“แƒ’แƒ”แƒœแƒ˜แƒšแƒ˜แƒ แƒ”แƒฅแƒกแƒžแƒ”แƒ แƒ˜แƒ›แƒ”แƒœแƒขแƒฃแƒš แƒคแƒแƒ แƒ›แƒแƒขแƒจแƒ˜ - แƒ™แƒแƒœแƒกแƒแƒšแƒ˜แƒก แƒกแƒ”แƒกแƒ˜แƒ˜แƒก แƒฉแƒแƒœแƒแƒฌแƒ”แƒ แƒ˜แƒก แƒกแƒแƒฎแƒ˜แƒ—. แƒ•แƒ˜แƒ›แƒ”แƒ“แƒแƒ•แƒœแƒ”แƒ‘แƒ—, แƒ แƒแƒ› แƒ”แƒก แƒแƒ  แƒ˜แƒฅแƒœแƒ”แƒ‘แƒ แƒซแƒแƒšแƒ˜แƒแƒœ แƒ แƒ—แƒฃแƒšแƒ˜ แƒ’แƒแƒกแƒแƒ’แƒ”แƒ‘แƒ˜ แƒ“แƒ แƒ™แƒแƒ“แƒ˜ แƒกแƒแƒ™แƒ›แƒแƒ แƒ˜แƒกแƒแƒ“ แƒ˜แƒฅแƒœแƒ”แƒ‘แƒ แƒ“แƒแƒ™แƒฃแƒ›แƒ”แƒœแƒขแƒ˜แƒ แƒ”แƒ‘แƒฃแƒšแƒ˜. แƒแƒขแƒ›แƒแƒกแƒคแƒ”แƒ แƒแƒกแƒ—แƒ•แƒ˜แƒก แƒฌแƒแƒ แƒ›แƒแƒ˜แƒ“แƒ’แƒ˜แƒœแƒ”แƒ—, แƒ แƒแƒ› แƒ”แƒก แƒแƒ  แƒแƒ แƒ˜แƒก แƒ›แƒฎแƒแƒšแƒแƒ“ แƒ™แƒแƒ“แƒ˜แƒก แƒคแƒ แƒแƒ’แƒ›แƒ”แƒœแƒขแƒ”แƒ‘แƒ˜, แƒแƒ แƒแƒ›แƒ”แƒ“ แƒฅแƒแƒฆแƒแƒšแƒ“แƒ˜ "แƒ แƒ™แƒ˜แƒœแƒ˜แƒก" แƒขแƒ”แƒšแƒ”แƒขแƒ˜แƒžแƒ˜แƒ“แƒแƒœ.

แƒšแƒฃแƒ แƒฏแƒ˜-แƒ›แƒฌแƒ•แƒแƒœแƒ” แƒ’แƒแƒœแƒšแƒแƒ’แƒ”แƒ‘แƒ แƒ›แƒ˜แƒœแƒ˜แƒ›แƒแƒšแƒฃแƒ แƒ˜ แƒฎแƒ”แƒšแƒคแƒแƒกแƒ˜แƒ—

แƒกแƒแƒ˜แƒœแƒขแƒ”แƒ แƒ”แƒกแƒ แƒขแƒ”แƒฅแƒœแƒ˜แƒ™แƒ”แƒ‘แƒ˜, แƒ แƒแƒ›แƒšแƒ”แƒ‘แƒ˜แƒช แƒ แƒ—แƒฃแƒšแƒ˜แƒ Google-แƒ˜แƒกแƒ—แƒ•แƒ˜แƒก แƒ›แƒฎแƒแƒšแƒแƒ“ แƒ™แƒแƒ“แƒ˜แƒก แƒฌแƒแƒ™แƒ˜แƒ—แƒฎแƒ•แƒ˜แƒ—, แƒแƒฆแƒฌแƒ”แƒ แƒ˜แƒšแƒ˜แƒ แƒงแƒแƒ•แƒ”แƒšแƒ˜ แƒ’แƒแƒœแƒงแƒแƒคแƒ˜แƒšแƒ”แƒ‘แƒ˜แƒก แƒ“แƒแƒกแƒแƒฌแƒงแƒ˜แƒกแƒจแƒ˜. แƒ—แƒฃ แƒ™แƒ˜แƒ“แƒ”แƒ• แƒ แƒแƒ›แƒ” แƒ’แƒแƒฃแƒ แƒ™แƒ•แƒ”แƒ•แƒ”แƒšแƒ˜แƒ, แƒ“แƒแƒ’แƒฃแƒ’แƒšแƒ” แƒ“แƒ แƒจแƒ”แƒแƒ›แƒแƒฌแƒ›แƒ”. แƒ’แƒแƒœแƒ›แƒแƒ แƒขแƒ”แƒ‘แƒ (แƒกแƒแƒ‘แƒ”แƒ“แƒœแƒ˜แƒ”แƒ แƒแƒ“, แƒ˜แƒกแƒ”แƒ• แƒ›แƒฃแƒจแƒแƒแƒ‘แƒก, แƒขแƒ”แƒšแƒ”แƒ’แƒ แƒแƒ›แƒ˜แƒก แƒ’แƒแƒœแƒ‘แƒšแƒแƒ™แƒ•แƒ˜แƒก แƒ’แƒแƒ›แƒ). แƒ—แƒฃ แƒ’แƒฃแƒ’แƒšแƒจแƒ˜ แƒ•แƒ”แƒ แƒแƒคแƒ”แƒ แƒก แƒ˜แƒซแƒ˜แƒ”แƒ‘แƒ—, แƒฐแƒ™แƒ˜แƒ—แƒฎแƒ”แƒ— แƒ™แƒแƒ›แƒ”แƒœแƒขแƒแƒ แƒ”แƒ‘แƒจแƒ˜. แƒกแƒ˜แƒแƒ›แƒแƒ•แƒœแƒ”แƒ‘แƒ˜แƒ— แƒ“แƒแƒ•แƒแƒ›แƒแƒขแƒ”แƒ‘ แƒจแƒ”แƒกแƒแƒ‘แƒแƒ›แƒ˜แƒก แƒ’แƒแƒœแƒงแƒแƒคแƒ˜แƒšแƒ”แƒ‘แƒแƒก "แƒกแƒแƒ˜แƒœแƒขแƒ”แƒ แƒ”แƒกแƒ แƒขแƒ”แƒฅแƒœแƒ˜แƒ™แƒ".

แƒ“แƒแƒ•แƒ˜แƒฌแƒงแƒแƒ—

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

แƒกแƒแƒ›แƒกแƒแƒฎแƒฃแƒ แƒ˜แƒก

แƒ’แƒแƒ•แƒแƒ™แƒ”แƒ—แƒแƒ— แƒ”แƒฅแƒกแƒžแƒ”แƒ แƒ˜แƒ›แƒ”แƒœแƒขแƒฃแƒšแƒ˜ แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜ แƒ“แƒ แƒ›แƒแƒ•แƒแƒ—แƒแƒ•แƒกแƒแƒ— แƒ™แƒแƒœแƒขแƒ”แƒ˜แƒœแƒ”แƒ แƒจแƒ˜.

แƒกแƒแƒ˜แƒœแƒขแƒ”แƒ แƒ”แƒกแƒ แƒขแƒ”แƒฅแƒœแƒ˜แƒ™แƒ

แฒแƒ›แƒแƒ‘แƒ”แƒญแƒ“แƒ”

แƒ›แƒ” แƒ™แƒแƒœแƒ™แƒ แƒ”แƒขแƒฃแƒšแƒแƒ“ แƒ•แƒแƒ แƒฆแƒ•แƒ”แƒ• แƒคแƒ แƒแƒ’แƒ›แƒ”แƒœแƒขแƒก, แƒ แƒแƒ—แƒ แƒฉแƒแƒ•แƒ แƒ—แƒ แƒžแƒ˜แƒ—แƒแƒœแƒ˜แƒก แƒฎแƒแƒ–แƒ’แƒแƒกแƒ›แƒ. แƒ“แƒแƒกแƒแƒกแƒ แƒฃแƒšแƒก แƒ˜แƒฅแƒœแƒ”แƒ‘แƒ แƒ™แƒ˜แƒ“แƒ”แƒ• แƒ”แƒ แƒ—แƒ˜ แƒแƒกแƒ”แƒ—แƒ˜ แƒœแƒแƒฌแƒ˜แƒšแƒ˜. แƒฉแƒแƒ—แƒ•แƒแƒšแƒ”แƒ—, แƒ แƒแƒ› แƒแƒ› แƒแƒ“แƒ’แƒ˜แƒšแƒ”แƒ‘แƒจแƒ˜ แƒฅแƒแƒฆแƒแƒšแƒ“แƒ˜ แƒ˜แƒญแƒ แƒ”แƒ‘แƒแƒ“แƒ แƒฎแƒแƒ–แƒ’แƒแƒกแƒ›แƒ˜แƒก แƒ’แƒแƒœแƒงแƒแƒคแƒ˜แƒšแƒ”แƒ‘แƒแƒจแƒ˜ แƒ’แƒแƒกแƒแƒ’แƒ–แƒแƒ•แƒœแƒแƒ“ (แƒกแƒแƒ“แƒแƒช แƒ™แƒแƒ“แƒ˜ แƒฎแƒ”แƒšแƒ˜แƒ— แƒ˜แƒงแƒ แƒจแƒ”แƒฆแƒ”แƒ‘แƒ˜แƒšแƒ˜ แƒฐแƒแƒ˜แƒšแƒแƒ˜แƒ—แƒ”แƒ แƒ”แƒ‘แƒ˜แƒ—), แƒจแƒ”แƒ›แƒ“แƒ”แƒ’ แƒ™แƒ˜ แƒแƒ› แƒœแƒแƒญแƒ แƒ”แƒ‘แƒก แƒฃแƒ™แƒแƒœ แƒแƒฌแƒ”แƒ‘แƒ”แƒ‘แƒ“แƒœแƒ”แƒœ.

$ 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

แƒกแƒแƒžแƒ˜แƒ แƒ˜แƒกแƒžแƒ˜แƒ แƒ แƒžแƒ แƒแƒฅแƒกแƒ˜

แƒ˜แƒ›แƒ˜แƒกแƒแƒ—แƒ•แƒ˜แƒก, แƒ แƒแƒ› แƒฉแƒ•แƒ”แƒœแƒ›แƒ แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒแƒ› แƒจแƒ”แƒฃแƒ›แƒฉแƒœแƒ”แƒ•แƒšแƒแƒ“ แƒจแƒ”แƒ˜แƒชแƒ•แƒแƒšแƒแƒก, แƒแƒฃแƒชแƒ˜แƒšแƒ”แƒ‘แƒ”แƒšแƒ˜แƒ, แƒ แƒแƒ› แƒ›แƒ˜แƒก แƒฌแƒ˜แƒœ แƒ˜แƒงแƒแƒก แƒกแƒฎแƒ•แƒ แƒกแƒฃแƒ‘แƒ˜แƒ”แƒฅแƒขแƒ˜, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒ“แƒแƒ›แƒแƒšแƒแƒ•แƒก แƒ›แƒ˜แƒก แƒฉแƒแƒœแƒแƒชแƒ•แƒšแƒ”แƒ‘แƒแƒก. แƒ”แƒก แƒจแƒ”แƒ˜แƒซแƒšแƒ”แƒ‘แƒ แƒ˜แƒงแƒแƒก แƒ•แƒ”แƒ‘ แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒ˜ nginx ะฒ แƒกแƒแƒžแƒ˜แƒ แƒ˜แƒกแƒžแƒ˜แƒ แƒ แƒžแƒ แƒแƒฅแƒกแƒ˜ แƒ แƒ”แƒŸแƒ˜แƒ›แƒ˜. แƒ™แƒšแƒ˜แƒ”แƒœแƒขแƒกแƒ แƒ“แƒ แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒแƒก แƒจแƒแƒ แƒ˜แƒก แƒ˜แƒฅแƒ›แƒœแƒ”แƒ‘แƒ แƒกแƒแƒžแƒ˜แƒ แƒ˜แƒกแƒžแƒ˜แƒ แƒ แƒžแƒ แƒแƒฅแƒกแƒ˜. แƒ˜แƒก แƒ˜แƒฆแƒ”แƒ‘แƒก แƒ™แƒšแƒ˜แƒ”แƒœแƒขแƒ”แƒ‘แƒ˜แƒก แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ”แƒ‘แƒก แƒ“แƒ แƒแƒ’แƒ–แƒแƒ•แƒœแƒ˜แƒก แƒ›แƒแƒ— แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒแƒจแƒ˜ แƒ“แƒ แƒแƒ’แƒ–แƒแƒ•แƒœแƒ˜แƒก แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒ˜แƒก แƒžแƒแƒกแƒฃแƒฎแƒ”แƒ‘แƒก แƒ™แƒšแƒ˜แƒ”แƒœแƒขแƒ”แƒ‘แƒก.

แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒ แƒ“แƒ แƒกแƒแƒžแƒ˜แƒ แƒ˜แƒกแƒžแƒ˜แƒ แƒ แƒžแƒ แƒแƒฅแƒกแƒ˜ แƒจแƒ”แƒ˜แƒซแƒšแƒ”แƒ‘แƒ แƒ“แƒแƒฃแƒ™แƒแƒ•แƒจแƒ˜แƒ แƒ“แƒ”แƒก แƒ“แƒแƒ™แƒ”แƒ แƒ˜แƒก แƒจแƒ˜แƒ’แƒœแƒ˜แƒ— แƒ“แƒแƒ™แƒ”แƒ แƒ˜แƒก แƒฅแƒกแƒ”แƒšแƒ˜. แƒแƒ›แƒ แƒ˜แƒ’แƒแƒ“, แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒ˜แƒก แƒ™แƒแƒœแƒขแƒ”แƒ˜แƒœแƒ”แƒ แƒก แƒแƒ แƒช แƒ™แƒ˜ แƒกแƒญแƒ˜แƒ แƒ“แƒ”แƒ‘แƒ แƒžแƒแƒ แƒขแƒ˜แƒก แƒ’แƒแƒ“แƒแƒ’แƒ–แƒแƒ•แƒœแƒ แƒ›แƒแƒกแƒžแƒ˜แƒœแƒซแƒ”แƒš แƒกแƒ˜แƒกแƒขแƒ”แƒ›แƒแƒ–แƒ”; แƒ”แƒก แƒกแƒแƒจแƒฃแƒแƒšแƒ”แƒ‘แƒแƒก แƒแƒซแƒšแƒ”แƒ•แƒก แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒแƒก แƒ›แƒแƒฅแƒกแƒ˜แƒ›แƒแƒšแƒฃแƒ แƒแƒ“ แƒ˜แƒ–แƒแƒšแƒ˜แƒ แƒ”แƒ‘แƒฃแƒšแƒ˜ แƒ˜แƒงแƒแƒก แƒ’แƒแƒ แƒ” แƒกแƒแƒคแƒ แƒ—แƒฎแƒ”แƒ”แƒ‘แƒ˜แƒกแƒ’แƒแƒœ.

แƒ—แƒฃ แƒกแƒแƒžแƒ˜แƒ แƒ˜แƒกแƒžแƒ˜แƒ แƒ แƒžแƒ แƒแƒฅแƒกแƒ˜ แƒชแƒฎแƒแƒ•แƒ แƒแƒ‘แƒก แƒกแƒฎแƒ•แƒ แƒฐแƒแƒกแƒขแƒ–แƒ”, แƒ—แƒฅแƒ•แƒ”แƒœ แƒ›แƒแƒ’แƒ˜แƒฌแƒ”แƒ•แƒ— แƒ›แƒ˜แƒแƒขแƒแƒ•แƒแƒ— แƒ“แƒแƒ™แƒ”แƒ แƒ˜แƒก แƒฅแƒกแƒ”แƒšแƒ˜ แƒ“แƒ แƒ“แƒแƒแƒ™แƒแƒ•แƒจแƒ˜แƒ แƒแƒ— แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒ แƒกแƒแƒžแƒ˜แƒ แƒ˜แƒกแƒžแƒ˜แƒ แƒ แƒžแƒ แƒแƒฅแƒกแƒ˜แƒก แƒฐแƒแƒกแƒขแƒ˜แƒก แƒฅแƒกแƒ”แƒšแƒ˜แƒก แƒ›แƒ”แƒจแƒ•แƒ”แƒแƒ‘แƒ˜แƒ—, แƒžแƒแƒ แƒขแƒ˜แƒก แƒ’แƒแƒ“แƒแƒ›แƒ˜แƒกแƒแƒ›แƒแƒ แƒ—แƒ”แƒ‘แƒ˜แƒ—. apps แƒžแƒแƒ แƒแƒ›แƒ”แƒขแƒ แƒ˜ --publish, แƒ แƒแƒ’แƒแƒ แƒช แƒžแƒ˜แƒ แƒ•แƒ”แƒšแƒ˜ แƒ“แƒแƒฌแƒงแƒ”แƒ‘แƒ˜แƒกแƒแƒก แƒ“แƒ แƒ แƒแƒ’แƒแƒ แƒช แƒกแƒแƒžแƒ˜แƒ แƒ˜แƒกแƒžแƒ˜แƒ แƒ แƒžแƒ แƒแƒฅแƒกแƒ˜แƒก แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜.

แƒฉแƒ•แƒ”แƒœ แƒ’แƒแƒ•แƒฃแƒจแƒ•แƒ˜แƒ— แƒกแƒแƒžแƒ˜แƒ แƒ˜แƒกแƒžแƒ˜แƒ แƒ แƒžแƒ แƒแƒฅแƒกแƒ˜ 80-แƒ” แƒžแƒแƒ แƒขแƒ–แƒ”, แƒ แƒแƒ“แƒ’แƒแƒœ แƒ”แƒก แƒแƒ แƒ˜แƒก แƒ–แƒฃแƒกแƒขแƒแƒ“ แƒ˜แƒก แƒžแƒ˜แƒ แƒ˜, แƒ แƒแƒ›แƒ”แƒšแƒ›แƒแƒช แƒฃแƒœแƒ“แƒ แƒ›แƒแƒฃแƒกแƒ›แƒ˜แƒœแƒแƒก แƒ’แƒแƒ แƒ” แƒฅแƒกแƒ”แƒšแƒก. แƒ—แƒฃ แƒžแƒแƒ แƒขแƒ˜ 80 แƒ“แƒแƒ™แƒแƒ•แƒ”แƒ‘แƒฃแƒšแƒ˜แƒ แƒ—แƒฅแƒ•แƒ”แƒœแƒก แƒกแƒแƒขแƒ”แƒกแƒขแƒ แƒฐแƒแƒกแƒขแƒ–แƒ”, แƒจแƒ”แƒชแƒ•แƒแƒšแƒ”แƒ— แƒžแƒแƒ แƒแƒ›แƒ”แƒขแƒ แƒ˜ --publish 80:80 on --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>

แƒฃแƒฌแƒงแƒ•แƒ”แƒขแƒ˜ แƒ’แƒแƒœแƒšแƒแƒ’แƒ”แƒ‘แƒ

แƒ›แƒแƒ“แƒ˜แƒ— แƒ’แƒแƒ›แƒแƒ•แƒแƒฅแƒ•แƒ”แƒงแƒœแƒแƒ— แƒแƒžแƒšแƒ˜แƒ™แƒแƒชแƒ˜แƒ˜แƒก แƒแƒฎแƒแƒšแƒ˜ แƒ•แƒ”แƒ แƒกแƒ˜แƒ (แƒ’แƒแƒจแƒ•แƒ”แƒ‘แƒ˜แƒก แƒ›แƒฃแƒจแƒแƒแƒ‘แƒ˜แƒก แƒแƒ แƒ›แƒแƒ’แƒ˜ แƒ’แƒแƒ–แƒ แƒ“แƒ˜แƒ—) แƒ“แƒ แƒจแƒ”แƒ•แƒ”แƒชแƒแƒ“แƒแƒ— แƒ›แƒ˜แƒกแƒ˜ แƒฃแƒžแƒ แƒแƒ‘แƒšแƒ”แƒ›แƒแƒ“ แƒ’แƒแƒœแƒ—แƒแƒ•แƒกแƒ”แƒ‘แƒ.

แƒกแƒแƒ˜แƒœแƒขแƒ”แƒ แƒ”แƒกแƒ แƒขแƒ”แƒฅแƒœแƒ˜แƒ™แƒ

  • 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 แƒกแƒ˜แƒกแƒขแƒ”แƒ›แƒแƒ–แƒ”) แƒ“แƒ แƒจแƒ”แƒ›แƒ“แƒ”แƒ’ แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒ–แƒ” แƒ’แƒแƒ“แƒแƒขแƒแƒœแƒ.

แƒกแƒฃแƒ แƒแƒ—แƒ”แƒ‘แƒ˜แƒก แƒ’แƒแƒ“แƒแƒขแƒแƒœแƒ

แƒกแƒแƒ›แƒฌแƒฃแƒฎแƒแƒ แƒแƒ“, แƒกแƒฃแƒ แƒแƒ—แƒ”แƒ‘แƒ˜แƒก แƒšแƒแƒ™แƒแƒšแƒฐแƒแƒกแƒขแƒ˜แƒ“แƒแƒœ แƒšแƒแƒ™แƒแƒšแƒฐแƒแƒกแƒขแƒ–แƒ” แƒ’แƒแƒ“แƒแƒขแƒแƒœแƒแƒก แƒแƒ–แƒ แƒ˜ แƒแƒ  แƒแƒฅแƒ•แƒก, แƒแƒ›แƒ˜แƒขแƒแƒ› แƒแƒ› แƒ’แƒแƒœแƒงแƒแƒคแƒ˜แƒšแƒ”แƒ‘แƒ˜แƒก แƒจแƒ”แƒกแƒฌแƒแƒ•แƒšแƒ แƒจแƒ”แƒกแƒแƒซแƒšแƒ”แƒ‘แƒ”แƒšแƒ˜แƒ แƒ›แƒฎแƒแƒšแƒแƒ“ แƒ˜แƒ› แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜, แƒ—แƒฃ แƒฎแƒ”แƒšแƒ— แƒ’แƒแƒฅแƒ•แƒ— แƒแƒ แƒ˜ แƒฐแƒแƒกแƒขแƒ˜ Docker-แƒ˜แƒ—. แƒ›แƒ˜แƒœแƒ˜แƒ›แƒฃแƒ› แƒแƒกแƒ” แƒ’แƒแƒ›แƒแƒ˜แƒงแƒฃแƒ แƒ”แƒ‘แƒ:

$ 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 - แƒ”แƒก แƒงแƒ•แƒ”แƒšแƒแƒ–แƒ” แƒ›แƒ˜แƒœแƒ˜แƒ›แƒแƒšแƒ˜แƒกแƒขแƒฃแƒ แƒ˜ แƒ›แƒ”แƒ—แƒแƒ“แƒ˜แƒ, แƒ›แƒแƒ’แƒ แƒแƒ› แƒแƒ แƒ แƒ”แƒ แƒ—แƒแƒ“แƒ”แƒ แƒ—แƒ˜. แƒแƒ แƒ˜แƒก แƒกแƒฎแƒ•แƒ”แƒ‘แƒ˜แƒช:

  1. แƒ™แƒแƒœแƒขแƒ”แƒ˜แƒœแƒ”แƒ แƒ”แƒ‘แƒ˜แƒก แƒ แƒ”แƒ”แƒกแƒขแƒ แƒ˜ (แƒ˜แƒœแƒ“แƒฃแƒกแƒขแƒ แƒ˜แƒ˜แƒก แƒกแƒขแƒแƒœแƒ“แƒแƒ แƒขแƒ˜).
  2. แƒ“แƒแƒฃแƒ™แƒแƒ•แƒจแƒ˜แƒ แƒ“แƒ˜แƒ— docker daemon แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒก แƒกแƒฎแƒ•แƒ แƒฐแƒแƒกแƒขแƒ˜แƒ“แƒแƒœ:
    1. แƒ’แƒแƒ แƒ”แƒ›แƒแƒก แƒชแƒ•แƒšแƒแƒ“แƒ˜ DOCKER_HOST.
    2. แƒ‘แƒ แƒซแƒแƒœแƒ”แƒ‘แƒ˜แƒก แƒฎแƒแƒ–แƒ˜แƒก แƒ•แƒแƒ แƒ˜แƒแƒœแƒขแƒ˜ -H แƒแƒœ --host แƒ˜แƒœแƒกแƒขแƒ แƒฃแƒ›แƒ”แƒœแƒขแƒ˜ docker-compose.
    3. docker context

แƒ›แƒ”แƒแƒ แƒ” แƒ›แƒ”แƒ—แƒแƒ“แƒ˜ (แƒ›แƒ˜แƒกแƒ˜ แƒ’แƒแƒœแƒฎแƒแƒ แƒชแƒ˜แƒ”แƒšแƒ”แƒ‘แƒ˜แƒก แƒกแƒแƒ›แƒ˜ แƒ•แƒแƒ แƒ˜แƒแƒœแƒขแƒ˜แƒ—) แƒ™แƒแƒ แƒ’แƒแƒ“ แƒแƒ แƒ˜แƒก แƒแƒฆแƒฌแƒ”แƒ แƒ˜แƒšแƒ˜ แƒกแƒขแƒแƒขแƒ˜แƒแƒจแƒ˜ แƒ แƒแƒ’แƒแƒ  แƒ’แƒแƒœแƒ•แƒแƒ—แƒแƒ•แƒกแƒแƒ— Docker-แƒ˜แƒก แƒ“แƒ˜แƒกแƒขแƒแƒœแƒชแƒ˜แƒฃแƒ  แƒฐแƒแƒกแƒขแƒ”แƒ‘แƒ–แƒ” docker-compose-แƒ˜แƒ—.

deploy.sh

แƒแƒฎแƒšแƒ แƒ›แƒแƒ“แƒ˜แƒ— แƒจแƒ”แƒ•แƒแƒ’แƒ แƒแƒ•แƒแƒ— แƒงแƒ•แƒ”แƒšแƒแƒคแƒ”แƒ แƒ˜, แƒ แƒแƒช แƒฎแƒ”แƒšแƒ˜แƒ— แƒ’แƒแƒ•แƒแƒ™แƒ”แƒ—แƒ”แƒ— แƒ”แƒ แƒ— แƒกแƒ™แƒ แƒ˜แƒžแƒขแƒจแƒ˜. แƒ“แƒแƒ•แƒ˜แƒฌแƒงแƒแƒ— แƒฃแƒ›แƒแƒฆแƒšแƒ”แƒกแƒ˜ แƒ“แƒแƒœแƒ˜แƒก แƒคแƒฃแƒœแƒฅแƒชแƒ˜แƒ˜แƒ— แƒ“แƒ แƒจแƒ”แƒ›แƒ“แƒ”แƒ’ แƒ’แƒแƒ“แƒแƒ•แƒฎแƒ”แƒ“แƒแƒ— แƒ›แƒแƒกแƒจแƒ˜ แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒฃแƒš แƒ“แƒแƒœแƒแƒ แƒฉแƒ”แƒœแƒ”แƒ‘แƒก.

แƒกแƒแƒ˜แƒœแƒขแƒ”แƒ แƒ”แƒกแƒ แƒขแƒ”แƒฅแƒœแƒ˜แƒ™แƒ

  • ${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
}

แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒฃแƒšแƒ˜ แƒ—แƒ•แƒ˜แƒกแƒ”แƒ‘แƒ”แƒ‘แƒ˜:

  • 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 แƒชแƒแƒขแƒ แƒแƒฎแƒกแƒœแƒแƒก แƒ›แƒแƒ˜แƒ—แƒฎแƒแƒ•แƒก:

แƒ แƒแƒขแƒแƒ› แƒแƒ‘แƒ แƒฃแƒœแƒ”แƒ‘แƒก แƒ แƒ˜แƒชแƒฎแƒ•แƒก แƒ“แƒ แƒแƒ  แƒ’แƒแƒ›แƒแƒกแƒชแƒ”แƒ›แƒก แƒกแƒขแƒ แƒ˜แƒฅแƒแƒœแƒก?

แƒงแƒแƒ•แƒ”แƒš แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜, แƒ“แƒแƒ แƒ”แƒ™แƒ•แƒ˜แƒก แƒคแƒฃแƒœแƒฅแƒชแƒ˜แƒแƒจแƒ˜ แƒฉแƒ•แƒ”แƒœ แƒ•แƒแƒ›แƒแƒฌแƒ›แƒ”แƒ‘แƒ— แƒ›แƒ˜แƒกแƒ˜ แƒ›แƒฃแƒจแƒแƒแƒ‘แƒ˜แƒก แƒจแƒ”แƒ“แƒ”แƒ’แƒก แƒ“แƒ แƒ’แƒแƒกแƒ•แƒšแƒ˜แƒก แƒ™แƒแƒ“แƒ˜แƒก แƒจแƒ”แƒ›แƒแƒฌแƒ›แƒ”แƒ‘แƒ bash-แƒ˜แƒก แƒ’แƒแƒ›แƒแƒงแƒ”แƒœแƒ”แƒ‘แƒ˜แƒ— แƒ‘แƒ”แƒ•แƒ แƒแƒ“ แƒฃแƒคแƒ แƒ แƒแƒ“แƒ•แƒ˜แƒšแƒ˜แƒ, แƒ•แƒ˜แƒ“แƒ แƒ” แƒกแƒขแƒ แƒ˜แƒฅแƒแƒœแƒ˜แƒก แƒจแƒ”แƒ›แƒแƒฌแƒ›แƒ”แƒ‘แƒ. แƒ’แƒแƒ แƒ“แƒ แƒแƒ›แƒ˜แƒกแƒ, แƒ›แƒ˜แƒกแƒ’แƒแƒœ แƒกแƒขแƒ แƒ˜แƒฅแƒแƒœแƒ˜แƒก แƒ›แƒ˜แƒฆแƒ”แƒ‘แƒ แƒซแƒแƒšแƒ˜แƒแƒœ แƒ›แƒแƒ แƒขแƒ˜แƒ•แƒ˜แƒ:
get-active-slot service && echo BLUE || echo GREEN.

แƒกแƒแƒ›แƒ˜ แƒžแƒ˜แƒ แƒแƒ‘แƒ แƒœแƒแƒ›แƒ“แƒ•แƒ˜แƒšแƒแƒ“ แƒกแƒแƒ™แƒ›แƒแƒ แƒ˜แƒกแƒ˜แƒ แƒงแƒ•แƒ”แƒšแƒ แƒกแƒแƒฎแƒ”แƒšแƒ›แƒฌแƒ˜แƒคแƒแƒก แƒ’แƒแƒ›แƒแƒกแƒแƒงแƒแƒคแƒแƒ“?

แƒšแƒฃแƒ แƒฏแƒ˜-แƒ›แƒฌแƒ•แƒแƒœแƒ” แƒ’แƒแƒœแƒšแƒแƒ’แƒ”แƒ‘แƒ แƒ›แƒ˜แƒœแƒ˜แƒ›แƒแƒšแƒฃแƒ แƒ˜ แƒฎแƒ”แƒšแƒคแƒแƒกแƒ˜แƒ—

แƒแƒ แƒ˜แƒช แƒกแƒแƒ™แƒ›แƒแƒ แƒ˜แƒกแƒ˜ แƒ˜แƒฅแƒœแƒ”แƒ‘แƒ, แƒ‘แƒแƒšแƒ แƒแƒฅ แƒ›แƒฎแƒแƒšแƒแƒ“ แƒกแƒ˜แƒกแƒ แƒฃแƒšแƒ˜แƒกแƒ—แƒ•แƒ˜แƒกแƒแƒ, แƒ แƒแƒ› แƒแƒ  แƒ“แƒแƒ•แƒฌแƒ”แƒ แƒ else.

แƒ›แƒฎแƒแƒšแƒแƒ“ แƒคแƒฃแƒœแƒฅแƒชแƒ˜แƒ, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒแƒ‘แƒ แƒฃแƒœแƒ”แƒ‘แƒก nginx แƒ™แƒแƒœแƒคแƒ˜แƒ’แƒฃแƒ แƒแƒชแƒ˜แƒ”แƒ‘แƒก, แƒ แƒฉแƒ”แƒ‘แƒ แƒ’แƒแƒœแƒฃแƒกแƒแƒ–แƒฆแƒ•แƒ แƒ”แƒšแƒ˜: get-nginx-config service_name deployment_slot. แƒฏแƒแƒœแƒ›แƒ แƒ—แƒ”แƒšแƒแƒ‘แƒ˜แƒก แƒจแƒ”แƒ›แƒแƒฌแƒ›แƒ”แƒ‘แƒ˜แƒก แƒแƒœแƒแƒšแƒแƒ’แƒ˜แƒ˜แƒ—, แƒแƒฅ แƒจแƒ”แƒ’แƒ˜แƒซแƒšแƒ˜แƒแƒ— แƒ“แƒแƒแƒงแƒ”แƒœแƒแƒ— แƒœแƒ”แƒ‘แƒ˜แƒกแƒ›แƒ˜แƒ”แƒ แƒ˜ แƒ™แƒแƒœแƒคแƒ˜แƒ’แƒฃแƒ แƒแƒชแƒ˜แƒ แƒœแƒ”แƒ‘แƒ˜แƒกแƒ›แƒ˜แƒ”แƒ แƒ˜ แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜แƒกแƒ—แƒ•แƒ˜แƒก. แƒกแƒแƒ˜แƒœแƒขแƒ”แƒ แƒ”แƒกแƒ แƒœแƒ˜แƒ•แƒ—แƒ”แƒ‘แƒ˜แƒ“แƒแƒœ - แƒ›แƒฎแƒแƒšแƒแƒ“ cat <<- EOF, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒกแƒแƒจแƒฃแƒแƒšแƒ”แƒ‘แƒแƒก แƒ’แƒแƒซแƒšแƒ”แƒ•แƒ— แƒแƒ›แƒแƒ˜แƒฆแƒแƒ— แƒงแƒ•แƒ”แƒšแƒ แƒฉแƒแƒœแƒแƒ แƒ—แƒ˜ แƒ“แƒแƒกแƒแƒฌแƒงแƒ˜แƒกแƒจแƒ˜. แƒ›แƒแƒ แƒ—แƒแƒšแƒ˜แƒ, แƒ™แƒแƒ แƒ’แƒ˜ แƒคแƒแƒ แƒ›แƒแƒขแƒ˜แƒ แƒ”แƒ‘แƒ˜แƒก แƒคแƒแƒกแƒ˜ แƒแƒ แƒ˜แƒก แƒฉแƒแƒœแƒแƒ แƒ—แƒ”แƒ‘แƒ˜แƒก แƒจแƒ”แƒ แƒ”แƒฃแƒšแƒ˜ แƒกแƒ˜แƒ•แƒ แƒชแƒ”แƒ”แƒ‘แƒ˜, แƒ แƒแƒช แƒ“แƒฆแƒ”แƒก แƒซแƒแƒšแƒ˜แƒแƒœ แƒชแƒฃแƒ“ แƒคแƒแƒ แƒ›แƒแƒ“ แƒ˜แƒ—แƒ•แƒšแƒ”แƒ‘แƒ. แƒ›แƒแƒ’แƒ แƒแƒ› bash แƒแƒ˜แƒซแƒฃแƒšแƒ”แƒ‘แƒก แƒฉแƒแƒœแƒแƒ แƒ—แƒ”แƒ‘แƒก แƒ“แƒ แƒแƒกแƒ”แƒ•แƒ” แƒ™แƒแƒ แƒ’แƒ˜ แƒ˜แƒฅแƒœแƒ”แƒ‘แƒแƒ“แƒ แƒœแƒแƒ แƒ›แƒแƒšแƒฃแƒ แƒ˜ แƒคแƒแƒ แƒ›แƒแƒขแƒ˜แƒ แƒ”แƒ‘แƒ nginx แƒ™แƒแƒœแƒคแƒ˜แƒ’แƒฃแƒ แƒแƒชแƒ˜แƒแƒจแƒ˜. แƒ›แƒแƒ™แƒšแƒ”แƒ“, แƒฉแƒแƒœแƒแƒ แƒ—แƒ”แƒ‘แƒ˜แƒก แƒจแƒ”แƒ แƒ”แƒ•แƒ แƒกแƒ˜แƒ•แƒ แƒชแƒ”แƒ”แƒ‘แƒ—แƒแƒœ แƒแƒฅ แƒœแƒแƒ›แƒ“แƒ•แƒ˜แƒšแƒแƒ“ แƒฉแƒแƒœแƒก แƒกแƒแƒฃแƒ™แƒ”แƒ—แƒ”แƒกแƒ แƒ’แƒแƒ›แƒแƒกแƒแƒ•แƒแƒšแƒ˜ แƒฃแƒแƒ แƒ”แƒกแƒ˜แƒ“แƒแƒœ. แƒ—แƒฃแƒ›แƒชแƒ, แƒแƒ›แƒแƒก แƒ•แƒ”แƒ  แƒ˜แƒฎแƒ˜แƒšแƒแƒ•แƒ— แƒฅแƒ•แƒ”แƒ›แƒแƒ— แƒ›แƒแƒชแƒ”แƒ›แƒฃแƒš แƒคแƒ แƒแƒ’แƒ›แƒ”แƒœแƒขแƒจแƒ˜, แƒ แƒแƒ“แƒ’แƒแƒœ แƒฐแƒแƒ‘แƒ แƒ˜ โ€žแƒ™แƒแƒ แƒ’แƒแƒ“ แƒแƒ™แƒ”แƒ—แƒ”แƒ‘แƒก แƒแƒ›แƒแƒกโ€œ แƒงแƒ•แƒ”แƒšแƒ แƒฉแƒแƒœแƒแƒ แƒ—แƒ˜แƒก 4 แƒกแƒ˜แƒ•แƒ แƒชแƒ”แƒ–แƒ” แƒจแƒ”แƒชแƒ•แƒšแƒ˜แƒ— แƒ“แƒ EOF-แƒ˜แƒก แƒแƒ แƒแƒกแƒฌแƒแƒ แƒ˜ แƒฅแƒชแƒ”แƒ•แƒ˜แƒ—. แƒ“แƒ แƒแƒฅ แƒ”แƒก แƒจแƒ”แƒกแƒแƒ›แƒฉแƒœแƒ”แƒ•แƒ˜แƒ.

แƒแƒ แƒฏแƒ”แƒ  แƒ แƒแƒ› แƒแƒ  แƒแƒ“แƒ’แƒ”, แƒ›แƒแƒจแƒ˜แƒœแƒ•แƒ” แƒ’แƒ”แƒขแƒงแƒ•แƒ˜ cat << 'EOF', แƒ แƒแƒ›แƒ”แƒšแƒกแƒแƒช แƒ›แƒแƒ’แƒ•แƒ˜แƒแƒœแƒ”แƒ‘แƒ˜แƒ— แƒจแƒ”แƒ•แƒฎแƒ•แƒ“แƒ”แƒ‘แƒ˜แƒ—. แƒ—แƒฃ แƒฃแƒ‘แƒ แƒแƒšแƒแƒ“ แƒฌแƒ”แƒ  cat << EOF, แƒจแƒ”แƒ›แƒ“แƒ”แƒ’ แƒฐแƒ”แƒ แƒ”แƒ“แƒแƒ™แƒ˜แƒก แƒจแƒ˜แƒ’แƒœแƒ˜แƒ— แƒกแƒขแƒ แƒ˜แƒฅแƒแƒœแƒ˜ แƒ˜แƒœแƒขแƒ”แƒ แƒžแƒแƒšแƒ˜แƒ แƒ”แƒ‘แƒฃแƒšแƒ˜แƒ (แƒชแƒ•แƒšแƒแƒ“แƒ”แƒ‘แƒ˜ แƒ’แƒแƒคแƒแƒ แƒ—แƒแƒ”แƒ‘แƒฃแƒšแƒ˜แƒ ($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
}

แƒ”แƒก แƒแƒ แƒ˜แƒก แƒ›แƒ—แƒ”แƒšแƒ˜ แƒกแƒชแƒ”แƒœแƒแƒ แƒ˜. แฒแƒ›แƒ˜แƒขแƒแƒ›แƒแƒช แƒแƒ แƒกแƒ˜ แƒแƒ› แƒกแƒ™แƒ แƒ˜แƒžแƒขแƒ˜แƒ— แƒฉแƒแƒ›แƒแƒกแƒแƒขแƒ•แƒ˜แƒ แƒ—แƒแƒ“ wget แƒแƒœ curl-แƒ˜แƒ—.

แƒžแƒแƒ แƒแƒ›แƒ”แƒขแƒ แƒ˜แƒ–แƒ”แƒ‘แƒฃแƒšแƒ˜ แƒกแƒ™แƒ แƒ˜แƒžแƒขแƒ”แƒ‘แƒ˜แƒก แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ แƒ“แƒ˜แƒกแƒขแƒแƒœแƒชแƒ˜แƒฃแƒ  แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒ–แƒ”

แƒ“แƒ แƒแƒ แƒ“แƒแƒแƒ™แƒแƒ™แƒฃแƒœแƒแƒ— แƒกแƒแƒ›แƒ˜แƒ–แƒœแƒ” แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒ–แƒ”. แฒแƒ›แƒฏแƒ”แƒ แƒแƒ“ 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.

แƒฉแƒ•แƒ”แƒœ แƒ“แƒแƒ•แƒฌแƒ”แƒ แƒ”แƒ— แƒ’แƒแƒœแƒšแƒแƒ’แƒ”แƒ‘แƒ˜แƒก แƒกแƒ™แƒ แƒ˜แƒžแƒขแƒ˜, แƒ แƒแƒ›แƒ”แƒšแƒ˜แƒช แƒฉแƒแƒ›แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒแƒ•แƒก แƒฌแƒ˜แƒœแƒแƒกแƒฌแƒแƒ  แƒฉแƒแƒจแƒ”แƒœแƒ”แƒ‘แƒฃแƒš แƒกแƒฃแƒ แƒแƒ—แƒก แƒกแƒแƒ›แƒ˜แƒ–แƒœแƒ” แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒ–แƒ” แƒ“แƒ แƒจแƒ”แƒฃแƒคแƒ”แƒ แƒฎแƒ”แƒ‘แƒšแƒแƒ“ แƒชแƒ•แƒšแƒ˜แƒก แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜แƒก แƒ™แƒแƒœแƒขแƒ”แƒ˜แƒœแƒ”แƒ แƒก, แƒ›แƒแƒ’แƒ แƒแƒ› แƒ แƒแƒ’แƒแƒ  แƒจแƒ”แƒ’แƒ•แƒ˜แƒซแƒšแƒ˜แƒ แƒ›แƒ˜แƒกแƒ˜ แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ”แƒ‘แƒ แƒ“แƒ˜แƒกแƒขแƒแƒœแƒชแƒ˜แƒฃแƒ  แƒ›แƒแƒœแƒฅแƒแƒœแƒแƒ–แƒ”? แƒกแƒ™แƒ แƒ˜แƒžแƒขแƒก แƒแƒฅแƒ•แƒก แƒแƒ แƒ’แƒฃแƒ›แƒ”แƒœแƒขแƒ”แƒ‘แƒ˜, แƒ แƒแƒ“แƒ’แƒแƒœ แƒ˜แƒก แƒฃแƒœแƒ˜แƒ•แƒ”แƒ แƒกแƒแƒšแƒฃแƒ แƒ˜แƒ แƒ“แƒ แƒจแƒ”แƒฃแƒซแƒšแƒ˜แƒ แƒ”แƒ แƒ—แƒ“แƒ แƒแƒฃแƒšแƒแƒ“ แƒ’แƒแƒœแƒแƒ—แƒแƒ•แƒกแƒแƒก แƒ แƒแƒ›แƒ“แƒ”แƒœแƒ˜แƒ›แƒ” แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜ แƒ”แƒ แƒ—แƒ˜ แƒกแƒแƒžแƒ˜แƒ แƒ˜แƒกแƒžแƒ˜แƒ แƒ แƒžแƒ แƒแƒฅแƒกแƒ˜แƒก แƒฅแƒ•แƒ”แƒจ (แƒจแƒ”แƒ’แƒ˜แƒซแƒšแƒ˜แƒแƒ— แƒ’แƒแƒ›แƒแƒ˜แƒงแƒ”แƒœแƒแƒ— nginx แƒ™แƒแƒœแƒคแƒ˜แƒ’แƒฃแƒ แƒแƒชแƒ˜แƒ”แƒ‘แƒ˜, แƒ แƒแƒ—แƒ แƒ“แƒแƒแƒ“แƒ’แƒ˜แƒœแƒแƒ— แƒ แƒแƒ›แƒ”แƒšแƒ˜ url แƒ แƒแƒ›แƒ”แƒšแƒ˜ แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ˜ แƒ˜แƒฅแƒœแƒ”แƒ‘แƒ). แƒกแƒ™แƒ แƒ˜แƒžแƒขแƒ˜แƒก แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒ–แƒ” แƒจแƒ”แƒœแƒแƒฎแƒ•แƒ แƒจแƒ”แƒฃแƒซแƒšแƒ”แƒ‘แƒ”แƒšแƒ˜แƒ, แƒ แƒแƒ“แƒ’แƒแƒœ แƒแƒ› แƒจแƒ”แƒ›แƒ—แƒฎแƒ•แƒ”แƒ•แƒแƒจแƒ˜ แƒฉแƒ•แƒ”แƒœ แƒ•แƒ”แƒ  แƒจแƒ”แƒ•แƒซแƒšแƒ”แƒ‘แƒ— แƒ›แƒ˜แƒก แƒแƒ•แƒขแƒแƒ›แƒแƒขแƒฃแƒ แƒแƒ“ แƒ’แƒแƒœแƒแƒฎแƒšแƒ”แƒ‘แƒแƒก (แƒจแƒ”แƒชแƒ“แƒแƒ›แƒ˜แƒก แƒ’แƒแƒ›แƒแƒกแƒฌแƒแƒ แƒ”แƒ‘แƒ˜แƒก แƒ“แƒ แƒแƒฎแƒแƒšแƒ˜ แƒกแƒ”แƒ แƒ•แƒ˜แƒกแƒ”แƒ‘แƒ˜แƒก แƒ“แƒแƒ›แƒแƒขแƒ”แƒ‘แƒ˜แƒก แƒ›แƒ˜แƒ–แƒœแƒ˜แƒ—) แƒ“แƒ แƒ–แƒแƒ’แƒแƒ“แƒแƒ“, แƒ›แƒ“แƒ’แƒแƒ›แƒแƒ แƒ”แƒแƒ‘แƒ = แƒ‘แƒแƒ แƒแƒขแƒ”แƒ‘แƒ.

แƒ’แƒแƒ›แƒแƒกแƒแƒ•แƒแƒšแƒ˜ 1: แƒ›แƒแƒ˜แƒœแƒช แƒจแƒ”แƒ˜แƒœแƒแƒฎแƒ”แƒ— แƒกแƒ™แƒ แƒ˜แƒžแƒขแƒ˜ แƒกแƒ”แƒ แƒ•แƒ”แƒ แƒ–แƒ”, แƒ›แƒแƒ’แƒ แƒแƒ› แƒ“แƒแƒแƒ™แƒแƒžแƒ˜แƒ แƒ”แƒ— แƒ˜แƒ’แƒ˜ แƒงแƒแƒ•แƒ”แƒš แƒฏแƒ”แƒ แƒ–แƒ” scp. แƒจแƒ”แƒ›แƒ“แƒ”แƒ’ แƒ“แƒแƒ™แƒแƒ•แƒจแƒ˜แƒ แƒ”แƒ‘แƒ แƒ›แƒ”แƒจแƒ•แƒ”แƒแƒ‘แƒ˜แƒ— ssh แƒ“แƒ แƒจแƒ”แƒแƒกแƒ แƒฃแƒšแƒ”แƒ— แƒกแƒ™แƒ แƒ˜แƒžแƒขแƒ˜ แƒกแƒแƒญแƒ˜แƒ แƒ แƒแƒ แƒ’แƒฃแƒ›แƒ”แƒœแƒขแƒ”แƒ‘แƒ˜แƒ—.

Cons:

  • แƒแƒ แƒ˜ แƒฅแƒ›แƒ”แƒ“แƒ”แƒ‘แƒ แƒ”แƒ แƒ—แƒ˜แƒก แƒœแƒแƒชแƒ•แƒšแƒแƒ“
  • แƒจแƒ”แƒ˜แƒซแƒšแƒ”แƒ‘แƒ แƒแƒ  แƒ˜แƒงแƒแƒก แƒแƒ“แƒ’แƒ˜แƒšแƒ˜, แƒกแƒแƒ“แƒแƒช แƒ™แƒแƒžแƒ˜แƒ แƒ”แƒ‘แƒ—, แƒแƒœ แƒแƒ  แƒ˜แƒงแƒแƒก แƒฌแƒ•แƒ“แƒแƒ›แƒ แƒ›แƒแƒกแƒ–แƒ”, แƒแƒœ แƒกแƒ™แƒ แƒ˜แƒžแƒขแƒ˜ แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ“แƒ”แƒก แƒฉแƒแƒœแƒแƒชแƒ•แƒšแƒ”แƒ‘แƒ˜แƒก แƒ“แƒ แƒแƒก.
  • แƒ›แƒ˜แƒ–แƒแƒœแƒจแƒ”แƒฌแƒแƒœแƒ˜แƒšแƒ˜แƒ แƒกแƒแƒ™แƒฃแƒ—แƒแƒ แƒ˜ แƒ—แƒแƒ•แƒ˜แƒก แƒ’แƒแƒกแƒฃแƒคแƒ—แƒแƒ•แƒ”แƒ‘แƒ (แƒฌแƒแƒจแƒแƒšแƒ”แƒ— แƒกแƒ™แƒ แƒ˜แƒžแƒขแƒ˜).
  • แƒฃแƒ™แƒ•แƒ” แƒกแƒแƒ›แƒ˜ แƒ›แƒแƒฅแƒ›แƒ”แƒ“แƒ”แƒ‘แƒ.

แƒ’แƒแƒ›แƒแƒกแƒแƒ•แƒแƒšแƒ˜ 2:

  • แƒจแƒ”แƒ˜แƒœแƒแƒฎแƒ”แƒ— แƒ›แƒฎแƒแƒšแƒแƒ“ แƒคแƒฃแƒœแƒฅแƒชแƒ˜แƒ”แƒ‘แƒ˜แƒก แƒ’แƒแƒœแƒ›แƒแƒ แƒขแƒ”แƒ‘แƒ”แƒ‘แƒ˜ แƒกแƒ™แƒ แƒ˜แƒžแƒขแƒจแƒ˜ แƒ“แƒ แƒกแƒแƒ”แƒ แƒ—แƒแƒ“ แƒแƒ แƒแƒคแƒ”แƒ แƒ˜ แƒ’แƒแƒฃแƒจแƒ•แƒ˜แƒ—
  • แƒ”แƒ แƒ—แƒแƒ“ sed แƒ“แƒแƒแƒ›แƒแƒขแƒ” แƒคแƒฃแƒœแƒฅแƒชแƒ˜แƒ˜แƒก แƒ’แƒแƒ›แƒแƒซแƒแƒฎแƒ”แƒ‘แƒ แƒ‘แƒแƒšแƒแƒ›แƒ“แƒ”
  • แƒ’แƒแƒ’แƒ–แƒแƒ•แƒœแƒ”แƒ— แƒ”แƒก แƒงแƒ•แƒ”แƒšแƒแƒคแƒ”แƒ แƒ˜ แƒžแƒ˜แƒ แƒ“แƒแƒžแƒ˜แƒ  แƒจแƒจ-แƒ–แƒ” แƒ›แƒ˜แƒšแƒ˜แƒก แƒกแƒแƒจแƒฃแƒแƒšแƒ”แƒ‘แƒ˜แƒ— (|)

แƒ“แƒแƒ“แƒ”แƒ‘แƒ˜แƒ—แƒ˜:

  • แƒญแƒ”แƒจแƒ›แƒแƒ แƒ˜แƒขแƒแƒ“ แƒ›แƒแƒฅแƒแƒšแƒแƒฅแƒ”แƒแƒ‘แƒ˜แƒก แƒแƒ แƒ›แƒฅแƒแƒœแƒ”
  • แƒฅแƒ•แƒแƒ‘แƒ˜แƒก แƒ“แƒแƒœแƒแƒ“แƒ’แƒแƒ แƒ”แƒ‘แƒ˜ แƒแƒ  แƒแƒ แƒ˜แƒก
  • แƒ—แƒแƒ•แƒก แƒ›แƒแƒ’แƒ แƒแƒ“ แƒ’แƒ แƒซแƒœแƒแƒ‘แƒก

แƒ›แƒแƒ“แƒ˜แƒ— แƒ’แƒแƒ•แƒแƒ™แƒ”แƒ—แƒแƒ— แƒ”แƒก Ansible-แƒ˜แƒก แƒ’แƒแƒ แƒ”แƒจแƒ”. แƒ“แƒ˜แƒแƒฎ, แƒงแƒ•แƒ”แƒšแƒแƒคแƒ”แƒ แƒ˜ แƒฃแƒ™แƒ•แƒ” แƒ’แƒแƒ›แƒแƒ’แƒแƒœแƒ˜แƒšแƒ˜แƒ. แƒ“แƒ˜แƒแƒฎ, แƒ•แƒ”แƒšแƒแƒกแƒ˜แƒžแƒ”แƒ“แƒ˜. แƒœแƒแƒฎแƒ”แƒ—, แƒ แƒแƒ›แƒ“แƒ”แƒœแƒแƒ“ แƒ›แƒแƒ แƒขแƒ˜แƒ•แƒ˜, แƒ”แƒšแƒ”แƒ’แƒแƒœแƒขแƒฃแƒ แƒ˜ แƒ“แƒ แƒ›แƒ˜แƒœแƒ˜แƒ›แƒแƒšแƒ˜แƒกแƒขแƒฃแƒ แƒ˜แƒ แƒ•แƒ”แƒšแƒแƒกแƒ˜แƒžแƒ”แƒ“แƒ˜:

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

แƒ—แƒฃแƒ›แƒชแƒ, แƒฉแƒ•แƒ”แƒœ แƒแƒ  แƒจแƒ”แƒ’แƒ•แƒ˜แƒซแƒšแƒ˜แƒ แƒ“แƒแƒ แƒฌแƒ›แƒฃแƒœแƒ”แƒ‘แƒฃแƒšแƒ˜ แƒ•แƒ˜แƒงแƒแƒ—, แƒ แƒแƒ› แƒ“แƒ˜แƒกแƒขแƒแƒœแƒชแƒ˜แƒฃแƒ  แƒ›แƒแƒกแƒžแƒ˜แƒœแƒซแƒ”แƒšแƒก แƒแƒฅแƒ•แƒก แƒแƒ“แƒ”แƒ™แƒ•แƒแƒขแƒฃแƒ แƒ˜ แƒ‘แƒแƒจแƒ˜, แƒแƒ›แƒ˜แƒขแƒแƒ› แƒ“แƒแƒกแƒแƒฌแƒงแƒ˜แƒกแƒจแƒ˜ แƒ“แƒแƒ•แƒแƒ›แƒแƒขแƒ”แƒ‘แƒ— แƒ›แƒชแƒ˜แƒ แƒ” แƒจแƒ”แƒ›แƒแƒฌแƒ›แƒ”แƒ‘แƒแƒก (แƒ”แƒก แƒแƒ แƒ˜แƒก แƒœแƒแƒชแƒ•แƒšแƒแƒ“ 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

แƒแƒฎแƒšแƒ แƒ™แƒ˜ แƒ แƒ”แƒแƒšแƒฃแƒ แƒ˜แƒ:

$ 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-แƒ˜แƒก แƒ›แƒ˜แƒฎแƒ”แƒ“แƒ•แƒ˜แƒ— แƒ’แƒ•แƒ”แƒ แƒ“แƒ˜แƒก แƒ’แƒแƒœแƒแƒฎแƒšแƒ”แƒ‘แƒ˜แƒ—.

แƒแƒ  แƒ“แƒแƒ’แƒแƒ•แƒ˜แƒฌแƒงแƒ“แƒ”แƒ— แƒกแƒแƒ›แƒฃแƒจแƒแƒแƒก แƒจแƒ”แƒ›แƒ“แƒ”แƒ’ แƒ“แƒแƒกแƒฃแƒคแƒ—แƒแƒ•แƒ”แƒ‘แƒ :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