# Docker

# 【上課筆記】【hiskio】Docker 完全實作！結合 3 大語言掌握容器實務應用

##### 上課講義

[Docker 完全實作 – Dropbox Paper](https://paper.dropbox.com/doc/Docker--BaNWxS3HDfry~X6QJb7Ze4plAg-pcGbQoyLtmiPPoIlkkK2r)

---

[![image-1642476831997.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/0giARnkNtAdZy4q4-image-1642476831997.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/0giARnkNtAdZy4q4-image-1642476831997.png)

nocopy : 存在檔案不覆蓋

# <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Docker 完全實作</span>

# <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![man teacher](https://paper.dropboxstatic.com/static/img/ace/emoji/1f468-1f3eb.png?version=6.0.0 "man teacher")</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 讓我們先複習一下 Docker 的安裝</span>

## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Windows 上的 Docker 環境建置</span>

<div id="bkmrk-https%3A%2F%2Fdocs.docker."><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://docs.docker.com/desktop/windows/install/","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://docs.docker.com/desktop/windows/install/">[https://docs.docker.com/desktop/windows/install/](https://docs.docker.com/desktop/windows/install/)  
</span></span></div><div id="bkmrk-%E4%BB%80%E9%BA%BC%E6%98%AFwsl%EF%BC%9F">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">什麼是WSL？</span>

</div><div id="bkmrk-%E9%81%A9%E7%94%A8%E6%96%BC-linux-%E7%9A%84-windows-">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">適用於 Linux 的 Windows 子系統可讓開發人員執行 GNU/Linux 環境</span> <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z h-lparen">(包括大部分的命令列工具、公用程式和應用程式)，直接在</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> Windows 上執行，不需進行修改，不會造成傳統虛擬機器或 dualboot 設定的額外負荷。 </span>

</div><div id="bkmrk-https%3A%2F%2Fdocs.microso">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://docs.microsoft.com/zh-tw/windows/wsl/about](https://docs.microsoft.com/zh-tw/windows/wsl/about)</span>

</div><div id="bkmrk--0"></div><div id="bkmrk-https%3A%2F%2Fwww.youtube."><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"youtube","url":"https://www.youtube.com/watch?v=lIkxbE_We1I&","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://www.youtube.com/watch?v=lIkxbE_We1I&">[https://www.youtube.com/watch?v=lIkxbE\_We1I&amp;](https://www.youtube.com/watch?v=lIkxbE_We1I&)  
</span></span></div><div id="bkmrk-https%3A%2F%2Fyoutu.be%2Flik"><span class="attrlink url author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://youtu.be/lIkxbE\_We1I](https://youtu.be/lIkxbE_We1I)</span></div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Mac 上的 Docker 環境建置</span>

<div id="bkmrk-https%3A%2F%2Fdocs.docker.-0"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://docs.docker.com/desktop/mac/install/","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://docs.docker.com/desktop/mac/install/">[https://docs.docker.com/desktop/mac/install/](https://docs.docker.com/desktop/mac/install/)  
</span></span></div><div id="bkmrk-%E5%A6%82%E6%9E%9C%E6%82%A8%E7%9A%84%E7%AD%86%E9%9B%BB%E6%98%AFapple-m1-%28sil">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">如果您的筆電是Apple M1</span> <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z h-lparen">(Silicon)</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> CPU的話，請參考此處的安裝方式：</span>

</div><div id="bkmrk-https%3A%2F%2Fdocs.docker.-1">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://docs.docker.com/desktop/mac/apple-silicon/](https://docs.docker.com/desktop/mac/apple-silicon/)</span>

</div><div id="bkmrk--1"></div><div id="bkmrk-apple-m1%E7%9A%84%E9%99%90%E5%88%B6"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![police car light](https://paper.dropboxstatic.com/static/img/ace/emoji/1f6a8.png?version=6.0.0 "police car light")</span> <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**Apple M1的限制**</span></div>- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">非所有映像檔都可用於 </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">ARM64</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 架構。可以使用</span> <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">--platform linux/amd64</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 模擬運行。但 </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">mysql</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 不適用於 ARM64，不過可以使用 </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">mariadb</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 解決此問題。</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">模擬Intel的容器可能會有不穩定的狀況出現，除了速度比較慢之外，也會使用更多的記憶體。</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">無法從容器內部 </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">ping</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 到 Internet。要測試網絡，我們建議使用 </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">curl</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 或 </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">wget</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">。</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">當 </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">TCP half-close</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">時，數據可能偶爾會丟失。</span>

<div id="bkmrk-%C2%A0">- 

</div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Linux 上的 Docker 環境建置</span>

<div id="bkmrk-https%3A%2F%2Fdocs.docker.-2"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://docs.docker.com/engine/install/ubuntu/","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://docs.docker.com/engine/install/ubuntu/">[https://docs.docker.com/engine/install/ubuntu/](https://docs.docker.com/engine/install/ubuntu/)  
</span></span></div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">實務上需要注意的事</span>

<div id="bkmrk--2"></div><div id="bkmrk-%E5%9C%A8%E5%A4%A7%E5%9E%8B%E7%B5%84%E7%B9%94%EF%BC%88%E8%B6%85%E9%81%8E-250-%E5%90%8D%E5%93%A1%E5%B7%A5%E6%88%96%E8%B6%85%E9%81%8E-">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![light bulb](https://paper.dropboxstatic.com/static/img/ace/emoji/1f4a1.png?version=6.0.0 "light bulb")</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 在大型組織（超過 250 名員工或超過 1000 萬美元的收入）中使用 Docker Desktop 需要付費訂閱 Docker。 雖然此條款的生效日期是 2021 年 8 月 31 日，但對於需要付費訂閱的用戶，寬限期到 2022 年 1 月 31 日。</span>

</div><div id="bkmrk--3"></div><div id="bkmrk-cpu%2Fmemory%E8%B3%87%E6%BA%90"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**CPU/Memory資源**</span></span></div><div id="bkmrk--5"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634205117720_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634205117720_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634205117720_image.png)</span></span></div><div id="bkmrk-%E6%8E%9B%E8%BC%89%E7%9B%AE%E9%8C%84"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**掛載目錄**</span></span></div><div id="bkmrk--6"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634205302746_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634205302746_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634205302746_image.png)</span></span></div><div id="bkmrk-buildkit"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**Buildkit**</span></span></div><div id="bkmrk--7"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634205247210_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634205247210_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634205247210_image.png)</span></span></div><div id="bkmrk-%E5%9B%9E%E5%BE%A9%E5%88%9D%E5%A7%8B%E8%A8%AD%E5%AE%9A"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**回復初始設定**</span></span></div><div id="bkmrk--8"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634207204490_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634207204490_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634207204490_image.png)</span></span></div># <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![whale](https://paper.dropboxstatic.com/static/img/ace/emoji/1f40b.png?version=6.0.0 "whale")</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 工欲善其事，必先利其器：Docker 技術快覽</span>

## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Docker 常用指令 </span>

<div id="bkmrk--9"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634184121714_image.png","thread-757518322229675521325990":"false","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"Source: https://docs.google.com/presentation/d/1pBBTzAbKAYTDXDE6ZDZzQkFKzFisMPQB8T96o1-N7po/pub?start=false&loop=false&delayms=3000&slide=id.g19613dd9d0_0_541\n","attribs":"*0+4e|1+1"},"pool":{"numToAttrib":{"0":["author","d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K"]},"attribToNum":{"author,d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K":0},"nextNum":1,"dirty":true,"firstDirtyNum":0}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634184121714_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634184121714_image.png)</span></span></div><div id="bkmrk-%E5%9F%B7%E8%A1%8C%E5%AE%B9%E5%99%A8"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**執行容器**</span></span></div><div id="bkmrk-%23-%E8%B7%91%E4%B8%80%E5%80%8B%E6%96%B0%E7%9A%84apache%E5%AE%B9%E5%99%A8">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># 跑一個新的apache容器</span>`</div><div id="bkmrk-docker-run-httpd%3Aalp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker run httpd:alpine</span>`</div><div id="bkmrk--10"></div><div id="bkmrk-%23-%E8%B7%91%E4%B8%80%E5%80%8B%E8%83%8C%E6%99%AF%E5%9F%B7%E8%A1%8C%E7%9A%84apache%E5%AE%B9%E5%99%A8%EF%BC%8C%E4%B8%A6">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># 跑一個背景執行的apache容器，並取名為apache</span>`</div><div id="bkmrk-docker-run--d---name">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker run -d --name apache httpd:alpine </span>`</div><div id="bkmrk--11"></div><div id="bkmrk-%23-%E8%B7%91%E4%B8%80%E5%80%8Bredis%E5%AE%B9%E5%99%A8%EF%BC%8C%E5%95%9F%E5%8B%95%E8%99%9B%E6%93%AC%E7%B5%82%E7%AB%AF%E6%A9%9F">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># 跑一個redis容器，啟動虛擬終端機，進入互動模式，在容器中執行sh</span>`</div><div id="bkmrk-docker-run--it---rm-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker run -it --rm redis:alpine sh</span>`</div>- <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">-it</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> : </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">i</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">指的就是互動模式，而 </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">t</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">就是指terminal的意示</span>
- <span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">--rm</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> :指的是當容器結束後，將容器從系統移除</span>

<div id="bkmrk--12"></div><div id="bkmrk-%E5%88%97%E5%87%BA%E5%AE%B9%E5%99%A8"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**列出容器**</span></span></div><div id="bkmrk-%23-%E5%88%97%E5%87%BA%E6%89%80%E6%9C%89%E5%9F%B7%E8%A1%8C%E4%B8%AD%E5%AE%B9%E5%99%A8">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><em># 列出所有執行中容器</em></span>`</div><div id="bkmrk-docker-ps">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker ps</span>`</div><div id="bkmrk--13"></div><div id="bkmrk-%23-%E5%88%97%E5%87%BA%E6%89%80%E6%9C%89%E5%AE%B9%E5%99%A8">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><em># 列出所有容器</em></span>`</div><div id="bkmrk-docker-ps--a">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker ps -a</span>`</div><div id="bkmrk--14"></div><div id="bkmrk-%E5%81%9C%E6%AD%A2%E5%AE%B9%E5%99%A8"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**停止容器**</span></span></div><div id="bkmrk-%23-%E5%81%9C%E6%AD%A2apache-%E5%AE%B9%E5%99%A8">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># 停止apache 容器</span>`</div><div id="bkmrk-docker-stop-apache">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker stop </span><span class="thread-988202269380550252733434 attrcomment attrcommentfirst thread-988202269380550252733434-first author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="comment-extra-inner-span">apache</span></span>`</div><div id="bkmrk--15"></div><div id="bkmrk-%E9%87%8D%E6%96%B0%E5%95%9F%E5%8B%95%E5%AE%B9%E5%99%A8"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**重新啟動容器**</span></span></div><div id="bkmrk-%23-%E9%87%8D%E6%96%B0%E5%95%9F%E5%8B%95apache">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># 重新啟動apache</span>`</div><div id="bkmrk-docker-restart-apach">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker restart </span><span class="thread-988202269380550252733434 attrcomment attrcommentfirst thread-988202269380550252733434-first author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="comment-extra-inner-span">apache</span></span>`</div><div id="bkmrk--16"></div><div id="bkmrk-kill%E5%AE%B9%E5%99%A8"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**Kill容器**</span></span></div><div id="bkmrk-%23%E5%BC%B7%E5%88%B6%E5%81%9C%E6%AD%A2%E5%AE%B9%E5%99%A8">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#強制停止容器</span>`</div><div id="bkmrk-docker-kill-apache">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker kill apache</span>`</div><div id="bkmrk--17"></div><div id="bkmrk-%E7%A7%BB%E9%99%A4%E5%AE%B9%E5%99%A8"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**移除容器**</span></span></div><div id="bkmrk-%23%E7%A7%BB%E9%99%A4apache">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#移除apache</span>`</div><div id="bkmrk-docker-rm-apache">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker rm apache</span>`</div><div id="bkmrk-%23%E6%AA%A2%E6%9F%A5%E6%89%80%E6%9C%89%E5%AE%B9%E5%99%A8">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#檢查所有容器</span>`</div><div id="bkmrk-docker-ps--a-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker ps -a</span>`</div><div id="bkmrk-%23%E7%A7%BB%E9%99%A4%E6%89%80%E6%9C%89%E5%AE%B9%E5%99%A8">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#移除所有容器</span>`</div><div id="bkmrk-docker-rm--f-%24%28docke">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker rm -f $(docker ps -a -q)</span>`</div><div id="bkmrk--18"></div><div id="bkmrk-%E8%A4%87%E8%A3%BD%E6%AA%94%E6%A1%88"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**複製檔案**</span></span></div><div id="bkmrk-%23-%E5%BB%BA%E7%AB%8B%E4%B8%80%E5%80%8Bhello.html">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># 建立一個hello.html</span>`</div><div id="bkmrk-echo-%22hello%22-%3E-hello">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">echo "hello" > hello.html</span>`</div><div id="bkmrk-%23-%E5%BB%BA%E7%AB%8Bapache">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># 建立apache</span>`</div><div id="bkmrk-docker-run--d---name-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker run -d --name apache httpd:alpine </span>`</div><div id="bkmrk-%23-%E8%A4%87%E8%A3%BD%E6%AA%94%E6%A1%88%E8%87%B3apache-%E5%AE%B9%E5%99%A8%E4%B8%AD">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># 複製檔案至apache 容器中</span>`</div><div id="bkmrk-docker-cp-hello.html">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker cp hello.html apache:/usr/local/apache2/htdocs/</span>`</div><div id="bkmrk-%23-%E8%A4%87%E8%A3%BDapache-%E5%AE%B9%E5%99%A8%E4%B8%AD%E7%9A%84%E6%AA%94%E6%A1%88%E8%87%B3%E6%9C%AC%E6%A9%9F">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># 複製apache 容器中的檔案至本機</span>`</div><div id="bkmrk-docker-cp-apache%3A%2Fus">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker cp apache:/usr/local/apache2/htdocs/index.html ./index.html</span>`</div><div id="bkmrk--19"></div><div id="bkmrk-%E5%9C%A8%E5%AE%B9%E5%99%A8%E5%85%A7%E5%9F%B7%E8%A1%8C%E7%A8%8B%E5%BC%8F"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**在容器內執行程式**</span></span></div><div id="bkmrk-%23%E5%9C%A8%E5%AE%B9%E5%99%A8%E4%B8%AD%E5%9F%B7%E8%A1%8Cshell">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#在容器中執行shell</span>`</div><div id="bkmrk-docker-exec--it-apac">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker exec -it apache sh</span>`</div><div id="bkmrk--20"></div><div id="bkmrk-%E6%8E%9B%E8%BC%89%E7%9B%AE%E9%8C%84-0"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**掛載目錄**</span></span></div><div id="bkmrk-%23%E6%8A%8Ahello.html%E6%8E%9B%E6%88%90index.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#把hello.html掛成index.html</span>`</div><div id="bkmrk-docker-run--d---name-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker run -d --name apache2 -v $PWD/hello.html:/usr/local/apache2/htdocs/index.html httpd:alpine</span>`</div><div id="bkmrk-%23-copy%E5%87%BA%E4%BE%86%E9%A9%97%E8%AD%89%E5%85%A7%E5%AE%B9%E6%98%AF%E5%90%A6%E4%B8%80%E6%A8%A3">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># copy出來驗證內容是否一樣</span>`</div><div id="bkmrk-docker-cp-apache2%3A%2Fu">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker cp apache2:/usr/local/apache2/htdocs/index.html ./index.html</span>`</div><div id="bkmrk-diff-index.html-hell">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">diff index.html hello.html</span>`</div><div id="bkmrk--21"></div><div id="bkmrk-%E5%BB%BA%E7%AB%8B%E5%A4%96%E9%83%A8%E9%80%A3%E7%B7%9A"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**建立外部連線**</span></span></div><div id="bkmrk-%23%E6%8A%8A%E3%80%8C%E6%9C%AC%E6%A9%9F%E7%9A%8480%E5%9F%A0%E3%80%8D%E5%B0%8D%E6%87%89%E5%88%B0%E3%80%8C%E5%AE%B9%E5%99%A8%E4%B8%AD%E7%9A%8480">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#把「本機的80埠」對應到「容器中的80埠」</span>`</div><div id="bkmrk-docker-run--d--v-%24pw">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker run -d -v $PWD/hello.html:/usr/local/apache2/htdocs/index.html -p 80:80 httpd:alpine</span>`</div><div id="bkmrk-http%3A%2F%2F127.0.0.1%3A80"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[http://127.0.0.1:80](http://127.0.0.1:80)</span></div><div id="bkmrk--22"></div><div id="bkmrk-%E5%A6%82%E4%BD%95%E5%BE%9E%E5%AE%B9%E5%99%A8%E4%B8%AD%EF%BC%8C%E9%80%A3%E5%88%B0%E6%9C%AC%E6%A9%9F%E4%B8%8A%E7%9A%84%E6%9C%8D%E5%8B%99%E5%91%A2%EF%BC%9F">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![light bulb](https://paper.dropboxstatic.com/static/img/ace/emoji/1f4a1.png?version=6.0.0 "light bulb")</span> <span class="attrlink url author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">[如何從容器中，連到本機上的服務呢](https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach)</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">？</span>

</div><div id="bkmrk-%E5%8F%AF%E4%BB%A5%E5%9C%A8%E5%AE%B9%E5%99%A8%E4%B8%AD%E4%BD%BF%E7%94%A8-host.docker">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">可以在容器中使用 </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">host.docker.internal</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 來連接本機上的服務喔！</span>

</div><div id="bkmrk--23"></div><div id="bkmrk--24"></div><div id="bkmrk-%E6%9F%A5%E7%9C%8B%E5%AE%B9%E5%99%A8%E7%8B%80%E6%85%8B"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**查看容器狀態**</span></span></div><div id="bkmrk-%23-%E6%9F%A5%E7%9C%8B-cpu%E3%80%81%E8%A8%98%E6%86%B6%E9%AB%94%E8%88%87%E7%B6%B2%E8%B7%AF%E7%94%A8%E9%87%8F">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><em># 查看 CPU、記憶體與網路用量</em></span>`</div><div id="bkmrk-docker-stats">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker stats</span>`</div><div id="bkmrk--25"></div><div id="bkmrk-%E6%9F%A5%E7%9C%8B%E5%AE%B9%E5%99%A8%E5%85%A7%E7%9A%84%E8%A1%8C%E7%A8%8B"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**查看容器內的行程**</span></span></div><div id="bkmrk-%23-%E6%9F%A5%E7%9C%8B%E5%AE%B9%E5%99%A8%E5%85%A7%E9%83%A8%E7%9A%84%E8%A1%8C%E7%A8%8B">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><em># 查看容器內部的行程</em></span>`</div><div id="bkmrk-docker-top-apache">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker top apache</span>`</div><div id="bkmrk-docker-top-apache2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker top apache2</span>`</div><div id="bkmrk--26"></div><div id="bkmrk-%E6%9F%A5%E7%9C%8B%E5%AE%B9%E5%99%A8logs"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**查看容器Logs**</span></span></div><div id="bkmrk-%23%E6%9F%A5%E7%9C%8Blog">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#查看log</span>`</div><div id="bkmrk-docker-logs-apache">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker logs apache</span>`</div><div id="bkmrk-%23%E6%8C%81%E7%BA%8C%E6%9F%A5%E7%9C%8B">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#持續查看</span>`</div><div id="bkmrk-docker-logs--f-apach">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker logs -f apache2</span>`</div><div id="bkmrk--27"></div><div id="bkmrk-%E5%BB%BA%E7%AB%8B%E6%98%A0%E5%83%8F%E6%AA%94"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**建立映像檔**</span></span></div><div id="bkmrk-%23-%E6%96%BC%E7%95%B6%E5%89%8D%E7%9B%AE%E9%8C%84%EF%BC%8C%E6%8C%89dockerfile.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># 於當前目錄，按Dockerfile.test中的指令，建立test:v1的映像檔</span>`</div><div id="bkmrk-docker-build-.--f-do">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker build . -f Dockerfile.test -t test:v1</span>`</div><div id="bkmrk--28"></div><div id="bkmrk-%E6%8B%89%E5%8F%96%E8%88%87%E6%8E%A8%E9%80%81%E6%98%A0%E5%83%8F%E6%AA%94"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**拉取與推送映像檔**</span></span></div><div id="bkmrk-%23%E5%BE%9Edocker-hub%E4%B8%8B%E8%BC%89-node%E7%9A%84">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#從docker hub下載 node的image</span>`</div><div id="bkmrk-docker-pull-node%3Aalp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker pull node:alpine</span>`</div><div id="bkmrk-%23%E5%B0%87%E4%B8%8B%E4%BE%86%E7%9A%84image%EF%BC%8C%E5%86%8D%E7%B5%A6%E6%96%BC%E6%96%B0%E7%9A%84%E6%A8%99%E7%B1%A4">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#將下來的image，再給於新的標籤</span>`</div><div id="bkmrk-docker-tag-node%3Aalpi">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker tag node:alpine macchiang/node:alpine</span>`</div><div id="bkmrk-%23%E6%8E%A8%E9%80%81%E6%96%B0%E7%9A%84%E6%A8%99%E7%B1%A4%E8%87%B3%E7%A7%81%E4%BA%BA%E5%80%89%E5%BA%AB">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#推送新的標籤至私人倉庫</span>`</div><div id="bkmrk-docker-push-macchian">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker push macchiang/node:alpine</span>`</div><div id="bkmrk--29"></div><div id="bkmrk-%E6%B8%85%E9%99%A4%E6%98%A0%E5%83%8F%E6%AA%94%E8%88%87%E5%AE%B9%E5%99%A8"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**清除映像檔與容器**</span></span></div><div id="bkmrk-%23%E5%81%9C%E6%8E%89%E5%85%A8%E9%83%A8container">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#停掉全部container</span>`</div><div id="bkmrk-docker-stop-%24%28docker">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker stop $(docker ps -a -q)</span>`</div><div id="bkmrk-%23%E5%88%AA%E9%99%A4%E6%89%80%E6%9C%89%E6%B2%92%E6%9C%89%E4%BD%BF%E7%94%A8%E7%9A%84container%E8%88%87">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#刪除所有沒有使用的container與image</span>`</div><div id="bkmrk-docker-system-prune">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker system prune</span>`</div><div id="bkmrk-%23%E5%88%AA%E9%99%A4%E6%89%80%E6%9C%89%E6%98%A0%E5%83%8F%E6%AA%94">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#刪除所有映像檔</span>`</div><div id="bkmrk-docker-rmi-%24%28docker-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker rmi $(docker images -a -q)</span>`</div><div id="bkmrk-%23%E6%B8%85%E9%99%A4volume">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#清除volume</span>`</div><div id="bkmrk-docker-volume-rm-%24%28d">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker volume rm $(docker volume ls)</span>`</div><div id="bkmrk--30"></div><div id="bkmrk-%23%E5%88%AA%E9%99%A4%E6%89%80%E6%9C%89%E6%B2%92%E6%9C%89%E4%BD%BF%E7%94%A8%E7%9A%84container%E3%80%81">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#刪除所有沒有使用的container、image及所有volume</span>`</div><div id="bkmrk-docker-system-prune-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker system prune -a -f --volumes</span>`</div><div id="bkmrk--31"></div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Dockerfile 起手式</span>

<div id="bkmrk-%E5%9F%BA%E6%9C%AC%E7%B5%84%E6%88%90"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**基本組成**</span></span></div><div id="bkmrk-%23-base-image---offic">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><em># Base Image - Official Alpine</em></span>`</div><div id="bkmrk-from-alpine">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>FROM</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> alpine</span>`</div><div id="bkmrk-%C2%A0-0">` `</div><div id="bkmrk-label-%22maintainer%22%3D%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>LABEL</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> "maintainer"="macchiang@gmail.com"</span>`</div><div id="bkmrk-%C2%A0-1">` `</div><div id="bkmrk-%23-upgrade-existing-p">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><em># Upgrade existing packages in the base image</em></span>`</div><div id="bkmrk-run-apk---no-cache-u">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>RUN</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> apk </span><span class="highlight author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z" data-highlight-color="#FFBFB5">--no-cache</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> upgrade</span>`</div><div id="bkmrk-%C2%A0-2">` `</div><div id="bkmrk-%23-install-apache-fro">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><em># Install apache from packages with out caching install files</em></span>`</div><div id="bkmrk-run-apk-add---no-cac">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>RUN</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> apk add --no-cache apache2</span>`</div><div id="bkmrk-%C2%A0-3">` `</div><div id="bkmrk-%23-open-port-for-http">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><em># Open port for httpd access</em></span>`</div><div id="bkmrk-expose-80">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>EXPOSE</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 80</span>`</div><div id="bkmrk-%C2%A0-6">` `</div><div id="bkmrk-%23-run-httpd-in-foreg">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><em># Run httpd in foreground</em></span>`</div><div id="bkmrk-cmd-%5B%22-d%22%2C%22foregroun">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>CMD</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> ["-D","FOREGROUND"]</span>`</div><div id="bkmrk-%C2%A0-7">` `</div><div id="bkmrk-%23-start-httpd-when-c">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><em># Start httpd when container runs</em></span>`</div><div id="bkmrk-entrypoint-%5B%22%2Fusr%2Fsb">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>ENTRYPOINT</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> ["/usr/sbin/httpd"]</span>`</div><div id="bkmrk--32"></div><div id="bkmrk-%C2%A0cmd-vs.-entrypoint">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![light bulb](https://paper.dropboxstatic.com/static/img/ace/emoji/1f4a1.png?version=6.0.0 "light bulb")</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**CMD**</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> vs. </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**ENTRYPOINT**</span>

</div><div id="bkmrk-cmd%E9%85%8D%E7%BD%AE%E7%9A%84%E6%98%AF%E9%A0%90%E8%A8%AD%E5%91%BD%E4%BB%A4%EF%BC%8C%E6%98%AF%E5%8F%AF%E4%BB%A5%E8%A2%AB%E8%A4%87%E5%AF%AB%E6%8E%89%E7%9A%84">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">CMD配置的是預設命令，是可以被複寫掉的。而ENTRYPOINT是一定會執行的命令。</span>

</div><div id="bkmrk-%E5%85%A9%E8%80%85%E5%85%B1%E7%94%A8%E7%9A%84%E8%A9%B1%EF%BC%8C%E5%AE%8C%E6%95%B4%E7%9A%84%E5%91%BD%E4%BB%A4%E6%9C%83%E6%98%AFentryp">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">兩者共用的話，完整的命令會是</span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">ENTRYPOINT + CMD</span>

</div><div id="bkmrk--33"></div><div id="bkmrk-%E5%BB%BA%E7%AB%8Bdocker-image"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">建立docker image</span></div><div id="bkmrk-docker-build-.--t-ap">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker build . -t apache:v1</span>`</div><div id="bkmrk--34"></div><div id="bkmrk-%E8%A4%87%E5%AF%ABcmd"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">複寫CMD</span></div><div id="bkmrk-%23%E7%9B%B4%E6%8E%A5%E8%A4%87%E5%AF%ABcmd%EF%BC%8C%E6%94%B9%E7%82%BA%E9%A1%AF%E7%A4%BA%E7%89%88%E8%99%9F">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#直接複寫CMD，改為顯示版號</span>`</div><div id="bkmrk-docker-run---rm-apac">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker run --rm apache:v1 -v</span>`</div><div id="bkmrk--35"></div><div id="bkmrk-env%E7%92%B0%E5%A2%83%E8%AE%8A%E6%95%B8"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**ENV環境變數**</span></span></div><div id="bkmrk-from-alpine-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>FROM</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> alpine</span>`</div><div id="bkmrk-env-node_env%3D%22develo">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>ENV</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> NODE_ENV="development"</span>`</div><div id="bkmrk--36"></div><div id="bkmrk-arg%E5%82%B3%E5%85%A5%E5%8F%83%E6%95%B8"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**ARG傳入參數**</span></span></div><div id="bkmrk-from-alpine-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>FROM</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> alpine</span>`</div><div id="bkmrk-arg-node_arg">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>ARG </strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">NODE_ARG</span>`</div><div id="bkmrk-env-node_env%3D%22%24%7Bnode">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>ENV</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> NODE_ENV="${NODE_ARG:-development}"</span>`</div><div id="bkmrk-run-echo-%22arg%3D%24%7Bnode">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>RUN</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> echo "ARG=${NODE_ARG}, ENV=${NODE_ENV}"</span>`</div><div id="bkmrk-cmd-echo-%22arg%3D%24%7Bnode">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>CMD</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> echo "ARG=${NODE_ARG}, ENV=${NODE_ENV}"</span>`</div><div id="bkmrk--37"></div><div id="bkmrk-%23-%E5%82%B3%E5%85%A5node_arg">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># 傳入NODE_ARG</span>`</div><div id="bkmrk-docker_buildkit%3D0-do">`<span class="thread-263389414338883775841008 attrcomment attrcommentfirst thread-263389414338883775841008-first author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="comment-extra-inner-span">DOCKER_BUILDKIT=0 </span></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker build --build-arg NODE_ARG=staging .</span>`</div><div id="bkmrk--38"></div><div id="bkmrk-%23-%E5%82%B3%E5%85%A5node_arg-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># 傳入NODE_ARG</span>`</div><div id="bkmrk-docker_buildkit%3D0-do-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">DOCKER_BUILDKIT=0 docker build .</span>`</div><div id="bkmrk--39"></div><div id="bkmrk-copy%E8%88%87add-%E8%A4%87%E8%A3%BD%E6%96%87%E4%BB%B6"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**COPY與ADD 複製文件**</span></span></div><div id="bkmrk-%E5%8A%9F%E8%83%BD%EF%BC%9A%E5%B0%87%E6%AA%94%E6%A1%88%E8%A4%87%E8%A3%BD%E5%88%B0image%E4%B8%AD">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">功能：將檔案複製到image中</span>

</div><div id="bkmrk-%E5%B7%AE%E7%95%B0%EF%BC%9A">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">差異：</span>

</div>- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY只能複製本機端的檔案或目錄</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">ADD可增加url的檔案到docker image</span> <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z h-lparen">(建議改用RUN</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> curl/wget)</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">ADD可將本機端認可的壓縮格式tar解開後複製進去(要小心)</span>



<div id="bkmrk-%E6%9C%80%E4%BD%B3%E5%AF%A6%E8%B8%90%EF%BC%9A-%E7%9B%A1%E9%87%8F%E4%BD%BF%E7%94%A8copy%E8%80%8C%E4%B8%8D%E6%98%AFadd">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">最佳實踐： 盡量使用</span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">而不是</span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">ADD</span>

</div><div id="bkmrk--40"></div><div id="bkmrk-%23%E8%A4%87%E8%A3%BDpackage.json%E5%88%B0%2Fapp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#複製package.json到/app下</span>`</div><div id="bkmrk-copy-package.json-%2Fa">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY package.json /app/</span>`</div><div id="bkmrk--41"></div><div id="bkmrk-%23%E8%A4%87%E8%A3%BD%E6%89%80%E6%9C%89file%E9%96%8B%E9%A0%AD%E7%9A%84%E6%AA%94%E6%A1%88%E5%88%B0%2Fapp%E4%B8%8B">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#複製所有file開頭的檔案到/app下，並改變檔案所屬用戶與群組</span>`</div><div id="bkmrk-copy---chown%3Duser%3Agr">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY --chown=user</span><span class="thread-664457574932181552801007 author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">:group</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> file* /app/</span>`</div><div id="bkmrk--42"></div><div id="bkmrk-%E8%8B%A5%E6%9C%89%E4%BA%9B%E6%AA%94%E6%A1%88%E4%B8%8D%E9%9C%80%E8%A6%81%E5%8A%A0%E5%85%A5%E5%88%B0image%E4%B8%AD%EF%BC%8C-%E5%8F%AF">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![light bulb](https://paper.dropboxstatic.com/static/img/ace/emoji/1f4a1.png?version=6.0.0 "light bulb")</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 若有些檔案不需要加入到image中， 可以建立 </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">.dockerignore</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 來忽略喔！</span>

</div><div id="bkmrk--43"></div><div id="bkmrk-workdir%E5%B7%A5%E4%BD%9C%E7%9B%AE%E9%8C%84"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**WORKDIR工作目錄**</span></span></div><div id="bkmrk-%23-hi.txt%E6%9C%83%E5%9C%A8%2F%E7%9B%AE%E9%8C%84%E4%B8%8B">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># hi.txt會在/目錄下</span>`</div><div id="bkmrk-run-echo-%22say-hi%22-%3E-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN echo "say hi" > hi.txt</span>`</div><div id="bkmrk-workdir-%2Fapp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">WORKDIR /app</span>`</div><div id="bkmrk-%23-world.txt%E6%9C%83%E5%9C%A8%2Fapp%E7%9A%84%E7%9B%AE%E9%8C%84">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># world.txt會在/app的目錄下</span>`</div><div id="bkmrk-run-echo-%22hello%22-%3E-w">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN echo "hello" > world.txt</span>`</div><div id="bkmrk--44"></div><div id="bkmrk-user%E6%8C%87%E5%AE%9A%E7%95%B6%E5%89%8D%E7%94%A8%E6%88%B6"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**USER指定當前用戶**</span></span></div><div id="bkmrk-%23%E6%96%B0%E5%A2%9Egroup%E8%88%87user">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#新增group與user</span>`</div><div id="bkmrk-run-groupadd--r-redi">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN groupadd -r redis && useradd -r -g redis redis</span>`</div><div id="bkmrk-%23%E6%8C%87%E5%AE%9A%E7%95%B6%E5%89%8D%E7%9A%84user%E7%82%BAredis">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#指定當前的user為redis</span>`</div><div id="bkmrk-user-redis">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">USER redis</span>`</div><div id="bkmrk-%23%E4%BB%A5redis%E7%9A%84%E8%BA%AB%E4%BB%BD%E5%9F%B7%E8%A1%8Credis-se">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#以redis的身份執行redis-server</span>`</div><div id="bkmrk-run-%5B-%22redis-server%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN [ "redis-server" ]</span>`</div><div id="bkmrk--45"></div><div id="bkmrk-healthcheck-%E5%81%A5%E5%BA%B7%E6%AA%A2%E6%9F%A5"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**HEALTHCHECK 健康檢查**</span></span></div><div id="bkmrk-from-nginx">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">FROM nginx</span>`</div><div id="bkmrk-run-apt-get-update-%26">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN apt-get update && apt-get install -y curl && </span><span class="thread-590770326760184689811544 attrcomment attrcommentfirst thread-590770326760184689811544-first author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="comment-extra-inner-span">rm -rf /var/lib/apt/lists/*</span></span>`</div><div id="bkmrk-healthcheck---interv">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">HEALTHCHECK --interval=5s --timeout=3s \</span>`</div><div id="bkmrk-%C2%A0-cmd-curl--fs-http%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  CMD curl -fs http://localhost/ || exit 1</span>`</div><div id="bkmrk--46"></div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">打造最小的Docker映像檔 </span>

<div id="bkmrk-%E5%A4%9A%E9%9A%8E%E6%AE%B5%E5%BB%BA%E7%BD%AEmulti-stage-bui"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**多階段建置Multi-stage Build**</span></span></div><div id="bkmrk-%23-stage-1-%E5%BB%BA%E7%BD%AE%E7%92%B0%E5%A2%83">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># Stage 1 建置環境</span>`</div><div id="bkmrk-from-alpine-as-build">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">FROM alpine </span><span class="thread-327434999775899771653400 attrcomment attrcommentfirst thread-327434999775899771653400-first author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="comment-extra-inner-span">AS</span></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> build</span>`</div><div id="bkmrk-run-echo-%22hello%22-%3E-m">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN echo "hello" > mytest</span>`</div><div id="bkmrk-%C2%A0-8">` `</div><div id="bkmrk-%23-stage-2-%E5%9F%B7%E8%A1%8C%E7%92%B0%E5%A2%83">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># Stage 2 執行環境</span>`</div><div id="bkmrk-from-alpine-%C2%A0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">FROM alpine  </span>`</div><div id="bkmrk-copy---from%3Dbuild-%2Fm">`<span class="thread-181959338896635756049539 attrcomment attrcommentfirst thread-181959338896635756049539-first author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="comment-extra-inner-span">COPY --from=build</span></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> /mytest .</span>`</div><div id="bkmrk-run-cat-%2Fmytest">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN cat /mytest</span>`</div><div id="bkmrk--47"></div><div id="bkmrk--48"></div><div id="bkmrk-distroless"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**Distroless**</span></span></div><div id="bkmrk-https%3A%2F%2Fgithub.com%2Fg"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://github.com/GoogleContainerTools/distroless","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://github.com/GoogleContainerTools/distroless">[https://github.com/GoogleContainerTools/distroless](https://github.com/GoogleContainerTools/distroless)  
</span></span></div><div id="bkmrk-https%3A%2F%2Fgithub.com%2Fg-0"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://github.com/GoogleContainerTools/distroless/tree/main/examples/go","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://github.com/GoogleContainerTools/distroless/tree/main/examples/go">[https://github.com/GoogleContainerTools/distroless/tree/main/examples/go](https://github.com/GoogleContainerTools/distroless/tree/main/examples/go)  
</span></span></div><div id="bkmrk-main.go"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">main.go</span></div><div id="bkmrk-package-main">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">package main</span>`</div><div id="bkmrk-%C2%A0-9">` `</div><div id="bkmrk-import-%22fmt%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">import "fmt"</span>`</div><div id="bkmrk-%C2%A0-10">` `</div><div id="bkmrk-func-main%28%29-%7B">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">func main() {</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-fmt.println%28">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        fmt.Println("Hello, world!")</span>`</div><div id="bkmrk-%7D">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">}</span>`</div><div id="bkmrk--49"></div><div id="bkmrk-dockerfile"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Dockerfile</span></div><div id="bkmrk-from-golang%3A1.12-as-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">FROM golang:1.12 as build-env</span>`</div><div id="bkmrk-workdir-%2Fgo%2Fsrc%2Fapp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">WORKDIR /go/src/app</span>`</div><div id="bkmrk-copy-.-%2Fgo%2Fsrc%2Fapp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY . /go/src/app</span>`</div><div id="bkmrk-run-go-get--d--v-.%2F.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN go get -d -v ./...</span>`</div><div id="bkmrk-run-go-build--o-%2Fgo%2F">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN go build -o /go/bin/app</span>`</div><div id="bkmrk-%C2%A0-11">` `</div><div id="bkmrk-from-gcr.io%2Fdistrole">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">FROM gcr.io/distroless/base</span>`</div><div id="bkmrk-copy---from%3Dbuild-en">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY --from=build-env /go/bin/app /</span>`</div><div id="bkmrk-cmd-%5B%22%2Fapp%22%5D">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">CMD ["/app"]</span>`</div><div id="bkmrk--50"></div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">建立多重系統架構的映像檔</span>

<div id="bkmrk-%E4%B8%8D%E5%90%8C%E5%9F%B7%E8%A1%8C%E7%92%B0%E5%A2%83%E7%9A%84%E5%95%8F%E9%A1%8C"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**不同執行環境的問題**</span></span></div><div id="bkmrk--51"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634268176860_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"在Apple M1上執行\n","attribs":"*0+c|1+1"},"pool":{"numToAttrib":{"0":["author","d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K"]},"attribToNum":{"author,d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K":0},"nextNum":1,"dirty":true,"firstDirtyNum":0}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634268176860_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634268176860_image.png)</span></span></div><div id="bkmrk-%E4%BD%BF%E7%94%A8buildx%E5%BB%BA%E6%A7%8B%E5%A4%9A%E9%87%8D%E7%B3%BB%E7%B5%B1%E6%9E%B6%E6%A7%8B%E7%9A%84%E6%98%A0%E5%83%8F%E6%AA%94"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**使用Buildx建構多重系統架構的映像檔**</span></span></div><div id="bkmrk-https%3A%2F%2Fdocs.docker.-3"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://docs.docker.com/desktop/multi-arch/","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://docs.docker.com/desktop/multi-arch/">[https://docs.docker.com/desktop/multi-arch/](https://docs.docker.com/desktop/multi-arch/)  
</span></span></div><div id="bkmrk--52"></div><div id="bkmrk-%23%E7%A2%BA%E8%AA%8D%E7%9B%AE%E5%89%8D%E7%9A%84builder%E7%82%BA%E4%BD%95">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#確認目前的builder為何</span>`</div><div id="bkmrk-docker-buildx-ls">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker buildx ls</span>`</div><div id="bkmrk--53"></div><div id="bkmrk-%23%E5%BB%BA%E7%AB%8B%E6%96%B0%E7%9A%84builder%E4%B8%A6%E5%88%87%E6%8F%9B%E9%81%8E%E5%8E%BB">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#建立新的builder並切換過去</span>`</div><div id="bkmrk-docker-buildx-create">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker buildx create --name multiarch --use</span>`</div><div id="bkmrk--54"></div><div id="bkmrk-%E8%8B%A5%E5%9C%A8linux%E7%92%B0%E5%A2%83%E4%B8%AD%E5%BB%BA%E7%AB%8Bbuilder%E7%9A%84"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![light bulb](https://paper.dropboxstatic.com/static/img/ace/emoji/1f4a1.png?version=6.0.0 "light bulb")</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 若在linux環境中建立builder的話，需要額外跑qemu-user-static容器，並將driver設為docker-container</span></div><div id="bkmrk-docker-run---rm---pr">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker run --rm --privileged multiarch/qemu-user-static --reset -p yes</span>`</div><div id="bkmrk-docker-buildx-create-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker buildx create --name multiarch --driver docker-container --use</span>`</div><div id="bkmrk--55"></div><div id="bkmrk-%23%E6%AA%A2%E6%9F%A5%E7%9B%AE%E5%89%8D%E7%9A%84builder">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#檢查目前的builder</span>`</div><div id="bkmrk-docker-buildx-inspec">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker buildx inspect --bootstrap</span>`</div><div id="bkmrk-%23%E5%BB%BA%E7%AB%8B%E6%94%AF%E6%8F%B4amd64%E8%88%87arm64%E7%9A%84ima">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#建立支援amd64與arm64的image，並且推送至registry</span>`</div><div id="bkmrk-docker-buildx-build-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker buildx build . --platform linux/amd64,linux/arm64 --push -t hello:v1</span>`</div># <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![orangutan](https://paper.dropboxstatic.com/static/img/ace/emoji/1f9a7.png?version=6.0.0 "orangutan")</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 一次控制多個容器：Docker Compose</span>

## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Docker Compose 的概念</span>

- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">定義和運行多個容器應用。</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">使用 YAML 文件來配置應用服務</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">使用單一命令從配置中創建和啟動所有服務</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">適用於所有環境：生產、Staging、開發、測試以及 CI 工作流</span>

<div id="bkmrk--56"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634196692841_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"Source: https://share.zabbix.com/virtualization/docker/docker-compose-yml-v2-format-for-zabbix-3-0\n","attribs":"*0+2q|1+1"},"pool":{"numToAttrib":{"0":["author","d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K"]},"attribToNum":{"author,d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K":0},"nextNum":1,"dirty":true,"firstDirtyNum":0}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634196692841_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634196692841_image.png)</span></span></div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Docker Compose 文件格式</span>

<div id="bkmrk-%E5%9F%BA%E6%9C%AC%E6%A0%BC%E5%BC%8F"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**基本格式**</span></span></div><div id="bkmrk-%E9%A0%90%E8%A8%AD%E6%96%87%E4%BB%B6%E5%90%8D%E7%A8%B1%E7%82%BA-docker-compo"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">預設文件名稱為 </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose.yml</span></div><div id="bkmrk-version%3A-%223%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">version: "3"</span>`</div><div id="bkmrk-services%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">services:</span>`</div><div id="bkmrk-%C2%A0-webapp%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  webapp:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%23%E6%8C%87%E5%AE%9Aimage">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    #指定image</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-httpd%3Aalp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: httpd:alpine </span>`</div><div id="bkmrk-%C2%A0-%C2%A0-ports%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    ports:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---%2280%3A80%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - "80:80"</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-volumes%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    volumes:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---%22%2Fdata%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - "/data"</span>`</div><div id="bkmrk--57"></div><div id="bkmrk-build-%E5%BB%BA%E7%AB%8B%E6%98%A0%E5%83%8F%E6%AA%94"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**build 建立映像檔**</span></span></div><div id="bkmrk-version%3A-%273%27">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">version: '3'</span>`</div><div id="bkmrk-services%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">services:</span>`</div><div id="bkmrk-%C2%A0-webapp%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  webapp:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%23%E5%BE%9Edockerfile-alt">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    #從Dockerfile-alternate建立映像檔</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-build%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    build:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-context%3A-.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      context: .</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-dockerfile%3A-do">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      dockerfile: Dockerfile-alternate</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-args%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      args:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-buildno%3A-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        buildno: 1</span>`</div><div id="bkmrk--58"></div><div id="bkmrk-https%3A%2F%2Fdocs.microso-0"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://docs.microsoft.com/zh-tw/visualstudio/docker/tutorials/use-docker-compose](https://docs.microsoft.com/zh-tw/visualstudio/docker/tutorials/use-docker-compose)</span></div><div id="bkmrk--59"></div><div id="bkmrk-https%3A%2F%2Fdocs.docker.-4"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://docs.docker.com/compose/compose-file/compose-file-v3/","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://docs.docker.com/compose/compose-file/compose-file-v3/">[https://docs.docker.com/compose/compose-file/compose-file-v3/](https://docs.docker.com/compose/compose-file/compose-file-v3/)  
</span></span></div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Docker Compose 命令參考</span>

<div id="bkmrk-https%3A%2F%2Fdocs.docker.-5"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://docs.docker.com/compose/reference/","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://docs.docker.com/compose/reference/">[https://docs.docker.com/compose/reference/](https://docs.docker.com/compose/reference/)  
</span></span></div><div id="bkmrk-%E5%9F%B7%E8%A1%8Cdocker-compose"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**執行docker compose**</span></span></div><div id="bkmrk-%23%E5%89%8D%E6%99%AF%E5%9F%B7%E8%A1%8C">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#前景執行</span>`</div><div id="bkmrk-docker-compose-up">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose up</span>`</div><div id="bkmrk-%23%E8%83%8C%E6%99%AF%E5%9F%B7%E8%A1%8C">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#背景執行</span>`</div><div id="bkmrk-docker-compose-up--d">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose up -d</span>`</div><div id="bkmrk--60"></div><div id="bkmrk-%E5%81%9C%E6%AD%A2%2F%E5%95%9F%E5%8B%95docker-compose"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**停止/啟動docker compose**</span></span></div><div id="bkmrk-docker-compose-stop">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose stop</span>`</div><div id="bkmrk--61"></div><div id="bkmrk-%E7%A7%BB%E9%99%A4docker-compose"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**移除docker compose**</span></span></div><div id="bkmrk-docker-compose-down">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose down</span>`</div><div id="bkmrk-%23%E4%B9%9F%E5%90%8C%E6%AD%A5%E7%A7%BB%E9%99%A4volume">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#也同步移除volume</span>`</div><div id="bkmrk-docker-compose-down-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose down -v</span>`</div><div id="bkmrk--62"></div><div id="bkmrk-%E5%88%97%E5%87%BAcontainers"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**列出containers**</span></span></div><div id="bkmrk-docker-compose-ps">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose ps</span>`</div><div id="bkmrk--63"></div><div id="bkmrk-%E7%9B%A3%E7%9C%8Blogs"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**監看logs**</span></span></div><div id="bkmrk-docker-compose-logs">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose logs</span>`</div><div id="bkmrk-%23follow-logs">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#follow logs</span>`</div><div id="bkmrk-docker-compose-logs-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose logs -f</span>`</div><div id="bkmrk--64"></div><div id="bkmrk-%E5%9F%B7%E8%A1%8C%E7%A8%8B%E5%BC%8F"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**執行程式**</span></span></div><div id="bkmrk-docker-compose-exec-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose exec webapp sh</span>`</div><div id="bkmrk--65"></div><div id="bkmrk-%E9%A1%AF%E7%A4%BA%E5%9F%B7%E8%A1%8C%E7%A8%8B%E5%BA%8F"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**顯示執行程序**</span></span></div><div id="bkmrk-docker-compose-top">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose top</span>`</div><div id="bkmrk--66"></div><div id="bkmrk--67"></div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Docker Compose 環境變數</span>

<div id="bkmrk-environment"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**environment**</span></span></div><div id="bkmrk-environment%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">environment:</span>`</div><div id="bkmrk-%C2%A0-rack_env%3A-developm">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  RACK_ENV: development</span>`</div><div id="bkmrk-%C2%A0-show%3A-%27true%27">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  SHOW: 'true'</span>`</div><div id="bkmrk-%C2%A0-session_secret%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  SESSION_SECRET:</span>`</div><div id="bkmrk--68"></div><div id="bkmrk-environment%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">environment:</span>`</div><div id="bkmrk-%C2%A0---rack_env%3Ddevelop">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  - RACK_ENV=development</span>`</div><div id="bkmrk-%C2%A0---show%3Dtrue">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  - SHOW=true</span>`</div><div id="bkmrk-%C2%A0---session_secret">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  - SESSION_SECRET</span>`</div><div id="bkmrk--69"></div><div id="bkmrk-env_file%C2%A0"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**env\_file** </span></span></div><div id="bkmrk-.env"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">.env</span></div><div id="bkmrk-var%3Dhello">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">VAR=hello</span>`</div><div id="bkmrk-myenv%3Ddevelopment">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">MYENV=development</span>`</div><div id="bkmrk--70"></div><div id="bkmrk-env_file%3A-.env">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">env_file: .env</span>`</div><div id="bkmrk--71"></div><div id="bkmrk-env_file%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">env_file:</span>`</div><div id="bkmrk-%C2%A0---.%2Fcommon.env">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  - ./common.env</span>`</div><div id="bkmrk-%C2%A0---.%2Fapps%2Fweb.env">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  - ./apps/web.env</span>`</div><div id="bkmrk-%C2%A0---%2Fopt%2Fruntime_opt">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  - /opt/runtime_opts.env</span>`</div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Docker Compose 健康檢查</span>

<div id="bkmrk-healthcheck%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">healthcheck:</span>`</div><div id="bkmrk-%C2%A0-test%3A-%5B%22cmd%22%2C-%22cur">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  test: ["CMD", "curl", "-f", "http://localhost"]</span>`</div><div id="bkmrk-%C2%A0-interval%3A-1m30s">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  interval: 1m30s</span>`</div><div id="bkmrk-%C2%A0-timeout%3A-10s">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  timeout: 10s</span>`</div><div id="bkmrk-%C2%A0-retries%3A-3">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  retries: 3</span>`</div><div id="bkmrk-%C2%A0-start_period%3A-40s">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  start_period: 40s</span>`</div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Docker Compose 起動順序</span>

<div id="bkmrk-version%3A-%223%22-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">version: "3"</span>`</div><div id="bkmrk-services%3A-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">services:</span>`</div><div id="bkmrk-%C2%A0-web%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  web:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-build%3A-.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    build: .</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-ports%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    ports:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---%2280%3A8000%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - "80:8000"</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-depends_on%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    </span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>depends_on</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---%22db%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - "db"</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-command%3A-%5B%22.%2Fwai">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    command: ["./wait-for-it.sh", "db:5432", "--", "python", "app.py"]</span>`</div><div id="bkmrk-%C2%A0-db%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  db:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-postgres">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: postgres</span>`</div><div id="bkmrk-%E5%B0%8F%E5%B7%A5%E5%85%B7"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**![hammer and pick](https://paper.dropboxstatic.com/static/img/ace/emoji/2692.png?version=6.0.0 "hammer and pick")**</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> **小工具**</span></span></div>- <span class="attrlink url author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">[wait-for-it](https://github.com/vishnubob/wait-for-it)</span>
- <span class="attrlink url author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">[wait-for](https://github.com/Eficode/wait-for)</span>

## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Docker Compose 磁碟掛載</span>

<div id="bkmrk--72"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://docs.docker.com/storage/images/types-of-mounts-volume.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"volumes on the Docker host\n","attribs":"*0+q|1+1"},"pool":{"numToAttrib":{"0":["author","d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K"]},"attribToNum":{"author,d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K":0},"nextNum":1,"dirty":true,"firstDirtyNum":0}}}}]}" data-ace-gallery-urls="https://docs.docker.com/storage/images/types-of-mounts-volume.png">![](https://docs.docker.com/storage/images/types-of-mounts-volume.png)</span></span></div><div id="bkmrk--73"></div><div id="bkmrk-long-syntax"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Long syntax</span></div><div id="bkmrk-version%3A-%223.9%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">version: "3.9"</span>`</div><div id="bkmrk-services%3A-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">services:</span>`</div><div id="bkmrk-%C2%A0-web%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  web:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-nginx%3Aalp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: nginx:alpine</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-volumes%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    </span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>volumes</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---type%3A-volume">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - type: volume</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-source%3A-myda">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        source: mydata</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-target%3A-%2Fdat">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        target: /data</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-volume%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        volume:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-nocopy%3A-tr">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">          </span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>nocopy</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">: true</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---type%3A-bind">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - type: bind</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-source%3A-.%2Fst">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        source: ./static</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-target%3A-%2Fopt">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        target: /opt/app/static</span>`</div><div id="bkmrk-%C2%A0-12">` `</div><div id="bkmrk-%C2%A0-db%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  db:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-postgres%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: postgres:latest</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-volumes%3A-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    </span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>volumes</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---%22%2Fvar%2Frun%2Fpo">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - "/var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock"</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---%22dbdata%3A%2Fvar">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - "dbdata:/var/lib/postgresql/data"</span>`</div><div id="bkmrk-%C2%A0-13">` `</div><div id="bkmrk-volumes%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>volumes</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">:</span>`</div><div id="bkmrk-%C2%A0-mydata%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  mydata:</span>`</div><div id="bkmrk-%C2%A0-dbdata%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  dbdata:</span>`</div><div id="bkmrk--74"></div><div id="bkmrk-short-syntax"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Short syntax</span></div><div id="bkmrk-volumes%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">volumes:</span>`</div><div id="bkmrk-%C2%A0-%23-just-specify-a-p">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  # Just specify a path and let the Engine create a volume</span>`</div><div id="bkmrk-%C2%A0---%2Fvar%2Flib%2Fmysql">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  - /var/lib/mysql</span>`</div><div id="bkmrk-%C2%A0-14">` `</div><div id="bkmrk-%C2%A0-%23-specify-an-absol">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  # Specify an absolute path mapping</span>`</div><div id="bkmrk-%C2%A0---%2Fopt%2Fdata%3A%2Fvar%2Fl">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  - /opt/data:/var/lib/mysql</span>`</div><div id="bkmrk-%C2%A0-15">` `</div><div id="bkmrk-%C2%A0-%23-path-on-the-host">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  # Path on the host, relative to the Compose file</span>`</div><div id="bkmrk-%C2%A0---.%2Fcache%3A%2Ftmp%2Fcac">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  - ./cache:/tmp/cache</span>`</div><div id="bkmrk-%C2%A0-16">` `</div><div id="bkmrk-%C2%A0-%23-user-relative-pa">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  # User-relative path</span>`</div><div id="bkmrk-%C2%A0---%7E%2Fconfigs%3A%2Fetc%2Fc">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  - ~/configs:/etc/configs/:ro</span>`</div><div id="bkmrk-%C2%A0-17">` `</div><div id="bkmrk-%C2%A0-%23-named-volume">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  # Named volume</span>`</div><div id="bkmrk-%C2%A0---datavolume%3A%2Fvar%2F">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  - datavolume:/var/lib/mysql</span>`</div># <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![fireworks](https://paper.dropboxstatic.com/static/img/ace/emoji/1f386.png?version=6.0.0 "fireworks")</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 如何導入Docker</span>

## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Docker導入流程</span>

1. <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">確認應用程式使用的程式語言與版本</span>
2. <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">參考相同程式語言的Dockerfile寫法</span>
3. <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">列出應用程式相依的套件(包含系統、語言、字型等等)</span>
4. <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">列出應用程式的設定(環境變數、設定檔)</span>
5. <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">撰寫Dockerfile並測試</span>
6. <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">檢查是否有檔案不該加入映像檔中( </span><span class="inline-code author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">.dockerignore</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">)</span>
7. <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">列出應用程式相依的服務(Database、Redis)</span>
8. <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">確認服務啟動順序並撰寫Docker Compose yaml</span>

## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">實作：Node.js + MongoDB打造API服務</span>

<div id="bkmrk--75"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634269999196_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"source:https://codetree.dev/node-rest-api-tutorial/\n","attribs":"*0+1f|1+1"},"pool":{"numToAttrib":{"0":["author","d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K"]},"attribToNum":{"author,d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K":0},"nextNum":1,"dirty":true,"firstDirtyNum":0}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634269999196_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1634269999196_image.png)</span></span></div><div id="bkmrk-https%3A%2F%2Fgithub.com%2Fm"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://github.com/macchiang/node-express-mongo-example","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://github.com/macchiang/node-express-mongo-example">[https://github.com/macchiang/node-express-mongo-example](https://github.com/macchiang/node-express-mongo-example)  
</span></span></div><div id="bkmrk-%E9%80%8F%E9%81%8E-dockerfile-%E9%83%A8%E7%BD%B2-nod"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**透過 Dockerfile 部署 Node.js 環境** </span></span></div><div id="bkmrk-%23-base-image">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># Base image</span>`</div><div id="bkmrk-from-node%3A16-alpine">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">FROM node:16-alpine</span>`</div><div id="bkmrk-%C2%A0-18">` `</div><div id="bkmrk-run-apk-upgrade---no">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN apk upgrade --no-cache</span>`</div><div id="bkmrk-%C2%A0-19">` `</div><div id="bkmrk-%23-create-app-directo">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># Create app directory</span>`</div><div id="bkmrk-run-mkdir--p-%2Fapp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN mkdir -p /app</span>`</div><div id="bkmrk-workdir-%2Fapp-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">WORKDIR /app</span>`</div><div id="bkmrk-%C2%A0-20">` `</div><div id="bkmrk-%23-install-app-depend">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># Install app dependencies</span>`</div><div id="bkmrk-copy-package.json-pa">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY package.json package-lock.json ./</span>`</div><div id="bkmrk-run-npm-install">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN npm install</span>`</div><div id="bkmrk-%C2%A0-21">` `</div><div id="bkmrk-%23-copy-app-source">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># copy app source</span>`</div><div id="bkmrk-copy-.-%2Fapp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY . /app</span>`</div><div id="bkmrk-%C2%A0-22">` `</div><div id="bkmrk-%23-service-port">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># service port</span>`</div><div id="bkmrk-expose-3000">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">EXPOSE 3000</span>`</div><div id="bkmrk-%C2%A0-23">` `</div><div id="bkmrk-cmd-%5B-%22node%22%2C-%22index">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">CMD [ "node", "index.js"]</span>`</div><div id="bkmrk--76"></div><div id="bkmrk-docker-compose-yaml"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**Docker Compose YAML**</span></span></div><div id="bkmrk-version%3A-%223.9%22-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">version: "3.9"</span>`</div><div id="bkmrk-services%3A-3">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">services:</span>`</div><div id="bkmrk-%C2%A0-express%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  express:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-build%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    build:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-context%3A-.%2F">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      context: ./</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-dockerfile%3A-do-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      dockerfile: Dockerfile</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-express%3Al">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: express:latest</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-ports%3A-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    ports:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---3000%3A3000">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - 3000:3000</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-depends_on%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    depends_on:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---mongo">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - mongo</span>`</div><div id="bkmrk-%C2%A0-mongo%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  mongo:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-mongo%3A5">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: mongo:5</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-ports%3A-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    ports:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---27017%3A27017">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - 27017:27017</span>`</div><div id="bkmrk-%C2%A0-24">` `</div><div id="bkmrk-volumes%3A-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">volumes:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-mongo_data%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    mongo_data:</span>`</div><div id="bkmrk--77"></div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![house with garden](https://paper.dropboxstatic.com/static/img/ace/emoji/1f3e1.png?version=6.0.0 "house with garden")</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 作業-health check的妙用</span>

<div id="bkmrk-%E8%AB%8B%E5%9C%A8node.js-%2B-mongodb%E7%9A%84">- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">請在Node.js + MongoDB的 Docker Compose YAML中加入health check，以確保當MongoDB啟動後，才啟動express</span>

</div># <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![soccer ball](https://paper.dropboxstatic.com/static/img/ace/emoji/26bd.png?version=6.0.0 "soccer ball")</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> Docker X Python實作：快速打造 LINE Bot</span>

## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">透過 Dockerfile 建立 Python 環境</span>

<div id="bkmrk-%E7%A2%BA%E8%AA%8Dpython%E7%9A%84image%E8%88%87%E7%89%88%E6%9C%AC"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**確認python的image與版本**</span></span></div><div id="bkmrk-https%3A%2F%2Fhub.docker.c"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://hub.docker.com/\_/python](https://hub.docker.com/_/python)</span></div><div id="bkmrk--78"></div><div id="bkmrk-%E4%BA%86%E8%A7%A3dockerfile"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**了解Dockerfile**</span></span></div><div id="bkmrk-from-python%3A3-slim-b">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">FROM python:3</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>-</strong></span><span class="attrlink url author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><a class="attrlink" data-target-href="https://hub.docker.com/layers/python/library/python/slim-bullseye/images/sha256-e1b23e3cca282283cfe8c7b14ab184208824337f0c9c64fce284737fa5cb0f4e?context=explore" href="https://hub.docker.com/layers/python/library/python/slim-bullseye/images/sha256-e1b23e3cca282283cfe8c7b14ab184208824337f0c9c64fce284737fa5cb0f4e?context=explore" rel="noreferrer nofollow noopener" target="_blank"><strong>slim-bullseye</strong></a></span>`</div><div id="bkmrk-%C2%A0-25">` `</div><div id="bkmrk-workdir-%2Fusr%2Fsrc%2Fapp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">WORKDIR /usr/src/app</span>`</div><div id="bkmrk-%C2%A0-26">` `</div><div id="bkmrk-copy-requirements.tx">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY requirements.txt ./</span>`</div><div id="bkmrk-run-pip-install---no">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN pip install --no-cache-dir -r requirements.txt</span>`</div><div id="bkmrk-%C2%A0-27">` `</div><div id="bkmrk-copy-.-.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY . .</span>`</div><div id="bkmrk-%C2%A0-28">` `</div><div id="bkmrk-cmd-%5B-%22python%22%2C-%22.%2Fy">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">CMD [ "python", "./your-daemon-or-script.py" ]</span>`</div><div id="bkmrk-%C2%A0-29">` `</div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Flask + Redis 打造計數器</span>

<div id="bkmrk-https%3A%2F%2Fgithub.com%2Fm-0"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://github.com/macchiang/hit-counter","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://github.com/macchiang/hit-counter">[https://github.com/macchiang/hit-counter](https://github.com/macchiang/hit-counter)  
</span></span></div><div id="bkmrk-docker-compose.yml"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose.yml</span></div><div id="bkmrk-version%3A-%272%27">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">version: '2'</span>`</div><div id="bkmrk-services%3A-4">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">services:</span>`</div><div id="bkmrk-%C2%A0-myapp%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  myapp:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-build%3A-.-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    build: .</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-ports%3A-3">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    ports:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0--%2280%3A5000%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">     - "80:5000"</span>`</div><div id="bkmrk-%C2%A0-redis-lb%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  redis-lb:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-%22redis%3Aal">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: "redis:alpine"</span>`</div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">構建 Django Web server</span>

<div id="bkmrk-https%3A%2F%2Fgithub.com%2Fm-1"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://github.com/macchiang/django-todolist","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://github.com/macchiang/django-todolist">[https://github.com/macchiang/django-todolist](https://github.com/macchiang/django-todolist)  
</span></span></div><div id="bkmrk-https%3A%2F%2Fdeveloper.mo"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://developer.mozilla.org/zh-TW/docs/Learn/Server-side/Django/Introduction","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://developer.mozilla.org/zh-TW/docs/Learn/Server-side/Django/Introduction">[https://developer.mozilla.org/zh-TW/docs/Learn/Server-side/Django/Introduction](https://developer.mozilla.org/zh-TW/docs/Learn/Server-side/Django/Introduction)  
</span></span></div><div id="bkmrk-%E5%85%88%E4%BA%86%E8%A7%A3%E5%B0%88%E6%A1%88%E7%9A%84%E5%AE%89%E8%A3%9D%E6%96%B9%E5%BC%8F"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**先了解專案的安裝方式**</span></span></div><div id="bkmrk-dockerfile-0"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**Dockerfile**</span></span></div><div id="bkmrk-from-python%3A3-slim-b-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">FROM python:3</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>-</strong></span><span class="attrlink url author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><a class="attrlink" data-target-href="https://hub.docker.com/layers/python/library/python/slim-bullseye/images/sha256-e1b23e3cca282283cfe8c7b14ab184208824337f0c9c64fce284737fa5cb0f4e?context=explore" href="https://hub.docker.com/layers/python/library/python/slim-bullseye/images/sha256-e1b23e3cca282283cfe8c7b14ab184208824337f0c9c64fce284737fa5cb0f4e?context=explore" rel="noreferrer nofollow noopener" target="_blank"><strong>slim-bullseye</strong></a></span>`</div><div id="bkmrk-%C2%A0-30">` `</div><div id="bkmrk-workdir-%2Fapp-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">WORKDIR /app</span>`</div><div id="bkmrk-%C2%A0-31">` `</div><div id="bkmrk-copy-requirements.tx-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY requirements.txt ./</span>`</div><div id="bkmrk-run-pip-install---no-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN pip install --no-cache-dir -r requirements.txt</span>`</div><div id="bkmrk-%C2%A0-32">` `</div><div id="bkmrk-copy-todo%2F%2A-.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY todo/* .</span>`</div><div id="bkmrk-run-python-manage.py">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN python manage.py migrate</span>`</div><div id="bkmrk-cmd-%5B-%22python%22%2C-%22man">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">CMD [ "python", "manage.py", "runserver" ]</span>`</div><div id="bkmrk--79"></div><div id="bkmrk-docker-compose.yaml"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**docker-compose.yaml**</span></span></div><div id="bkmrk-version%3A-%273.9%27">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">version: '3.9'</span>`</div><div id="bkmrk-services%3A-5">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">services:</span>`</div><div id="bkmrk-%C2%A0-myweb%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  myweb:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-build%3A-.-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    build: .</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-ports%3A-4">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    ports:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0--%228000%3A8000%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">     - "8000:8000"</span>`</div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">部署 LINE Bot 應用</span>

<div id="bkmrk-https%3A%2F%2Fgithub.com%2Fm-2"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://github.com/macchiang/line-bot-tutorial","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://github.com/macchiang/line-bot-tutorial">[https://github.com/macchiang/line-bot-tutorial](https://github.com/macchiang/line-bot-tutorial)  
</span></span></div><div id="bkmrk-https%3A%2F%2Fgithub.com%2Fl"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://github.com/line/line-bot-sdk-python/tree/master/examples/simple-server-echo","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://github.com/line/line-bot-sdk-python/tree/master/examples/simple-server-echo">[https://github.com/line/line-bot-sdk-python/tree/master/examples/simple-server-echo](https://github.com/line/line-bot-sdk-python/tree/master/examples/simple-server-echo)  
</span></span></div><div id="bkmrk--80"></div><div id="bkmrk-%E5%9C%A8%E4%BD%A0%E9%96%8B%E5%A7%8B%E4%B9%8B%E5%89%8D"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**在你開始之前**</span></span></div><div id="bkmrk-%E7%A2%BA%E4%BF%9D%E6%82%A8%E5%85%B7%E6%9C%89%E4%BB%A5%E4%B8%8B%E5%85%A7%E5%AE%B9%EF%BC%9A"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">確保您具有以下內容：</span></div>- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">擁有 Line 帳號</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">擁有 </span><span class="attrlink url author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">[Heroku](https://www.heroku.com/)</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 帳戶（您可以免費創建一個）</span>

<div id="bkmrk--81"></div><div id="bkmrk-%E5%BB%BA%E7%AB%8Bline-bot-%E9%A0%BB%E9%81%93"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**建立LINE Bot 頻道**</span></span></div>- <span class="attrlink url author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">[Messaging API 介紹](https://developers.line.biz/zh-hant/docs/messaging-api/overview/)</span>
- <span class="attrlink url author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">[開始使用 Messaging API](https://developers.line.biz/zh-hant/docs/messaging-api/getting-started/)</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">取得 </span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**Channel access token**</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 與 </span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**Channel secret**</span>

<div id="bkmrk--82"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636469446904_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"Channel secret\n","attribs":"*0+e|1+1"},"pool":{"numToAttrib":{"0":["author","d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K"]},"attribToNum":{"author,d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K":0},"nextNum":1,"dirty":true,"firstDirtyNum":0}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636469446904_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636469446904_image.png)</span></span></div><div id="bkmrk--83"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636469390721_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"Channel access token\n","attribs":"*0+k|1+1"},"pool":{"numToAttrib":{"0":["author","d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K"]},"attribToNum":{"author,d.iX86Va0dCNNJDjPG9iZa3ls0ROswnpuOedberDa3xTLqmSmT1K":0},"nextNum":1,"dirty":true,"firstDirtyNum":0}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636469390721_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636469390721_image.png)</span></span></div>- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">關閉預設罐頭回覆訊息</span>

<div id="bkmrk--84"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636504016837_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636504016837_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636504016837_image.png)</span></span></div><div id="bkmrk-%E5%BB%BA%E7%AB%8Bdocker-image-0"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**建立Docker Image**</span></span></div><div id="bkmrk-from-python%3A3-slim-b-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">FROM python:3-slim-bullseye</span>`</div><div id="bkmrk-workdir-%2Fapp-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">WORKDIR /app</span>`</div><div id="bkmrk-copy-requirements.tx-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY requirements.txt ./</span>`</div><div id="bkmrk-run-pip-install---no-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN pip install --no-cache-dir -r requirements.txt</span>`</div><div id="bkmrk-copy-app.py-.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY app.py .</span>`</div><div id="bkmrk-cmd-%5B-%22python%22%2C-%22app">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">CMD [ "python", "app.py"]</span>`</div><div id="bkmrk--85"></div><div id="bkmrk-docker-build-.--t-li">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker build . -t line-bot:latest</span>`</div><div id="bkmrk--86"></div><div id="bkmrk-%E5%AE%89%E8%A3%9Dheroku-cli"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**安裝Heroku CLI**</span></span></div><div id="bkmrk-https%3A%2F%2Fdevcenter.he"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://devcenter.heroku.com/articles/heroku-cli#download-and-install","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://devcenter.heroku.com/articles/heroku-cli#download-and-install">[https://devcenter.heroku.com/articles/heroku-cli#download-and-install](https://devcenter.heroku.com/articles/heroku-cli#download-and-install)  
</span></span></div><div id="bkmrk-%E5%BB%BA%E7%AB%8Bheroku-app"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**建立Heroku App**</span></span></div><div id="bkmrk-%23%E7%99%BB%E5%85%A5heroku">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#登入heroku</span>`</div><div id="bkmrk-heroku-login">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">heroku login</span>`</div><div id="bkmrk-%23%E7%99%BB%E5%85%A5heroku-registry">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#登入heroku registry</span>`</div><div id="bkmrk-heroku-container%3Alog">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">heroku container:login</span>`</div><div id="bkmrk-%23%E5%BB%BA%E7%AB%8Bapp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#建立app</span>`</div><div id="bkmrk-heroku-create">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">heroku create</span>`</div><div id="bkmrk-%C2%A0-33">` `</div><div id="bkmrk-%23creating-app...-don">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#Creating app... done, ⬢ morning-journey-43865</span>`</div><div id="bkmrk-%23https%3A%2F%2Fmorning-jou">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#</span><span class="highlight author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z" data-highlight-color="#FFBFB5"><strong>https://morning-journey-43865.herokuapp.com/</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> | https://git.heroku.com/morning-journey-43865.git</span>`</div><div id="bkmrk-%C2%A0-34">` `</div><div id="bkmrk-%23%E6%8E%A8%E9%80%81docker-image%E8%87%B3hero">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#推送docker image至heroku registry</span>`</div><div id="bkmrk-docker-tag-line-bot%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker tag line-bot:latest registry.heroku.com/</span><span class="highlight author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z" data-highlight-color="#F7CC62"><strong>morning-journey-43865</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">/web</span>`</div><div id="bkmrk-docker-push-registry">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker push registry.heroku.com/</span><span class="highlight author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z" data-highlight-color="#F7CC62"><strong>morning-journey-43865</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">/web</span>`</div><div id="bkmrk-%C2%A0-35">` `</div><div id="bkmrk-%C2%A0-36">` `</div><div id="bkmrk-%23%E8%A8%AD%E5%AE%9A%E7%92%B0%E5%A2%83%E8%AE%8A%E6%95%B8">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#設定環境變數</span>`</div><div id="bkmrk-heroku-config%3Aset-ch">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">heroku config:set CHANNEL_ACCESS_TOKEN=xxxxxxxxx</span>`</div><div id="bkmrk-heroku-config%3Aset-ch-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">heroku config:set CHANNEL_SECRET=xxxxxxxxx</span>`</div><div id="bkmrk-%C2%A0-37">` `</div><div id="bkmrk-%23deploy-docker-image">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#deploy docker image</span>`</div><div id="bkmrk-heroku-container%3Arel">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">heroku container:release web</span>`</div><div id="bkmrk--87"></div><div id="bkmrk-%E8%A8%AD%E5%AE%9Awebhook"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**設定Webhook**</span></span></div><div id="bkmrk--88"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636471948301_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636471948301_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636471948301_image.png)</span></span></div><div id="bkmrk--89"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636471973201_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636471973201_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636471973201_image.png)</span></span></div><div id="bkmrk--90"></div><div id="bkmrk--91"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636504063885_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636504063885_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636504063885_image.png)</span></span></div><div id="bkmrk-https%3A%2F%2Fdevcenter.he-0"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://devcenter.heroku.com/articles/container-registry-and-runtime","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://devcenter.heroku.com/articles/container-registry-and-runtime">[https://devcenter.heroku.com/articles/container-registry-and-runtime](https://devcenter.heroku.com/articles/container-registry-and-runtime)  
</span></span></div><div id="bkmrk-%E5%8A%A0%E5%85%A5%E5%A5%BD%E5%8F%8B%E8%88%87%E6%B8%AC%E8%A9%A6"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**加入好友與測試**</span></span></div><div id="bkmrk--92"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636504317204_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636504317204_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636504317204_image.png)</span></span></div><div id="bkmrk--93"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"image","url":"https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636504378568_image.png","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636504378568_image.png">![](https://paper-attachments.dropbox.com/s_02C5CCE7C60EF0F5CFCCC6A693EC6F4D19DF8DD8DD90E613893867B993C44DE5_1636504378568_image.png)</span></span></div><div id="bkmrk-debug"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**Debug**</span></span></div><div id="bkmrk-%E2%9D%AF-heroku-logs---tail">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">❯ </span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>heroku logs --tail</strong></span>`</div><div id="bkmrk-2021-11-09t15%3A17%3A06.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:17:06.932541+00:00 app[api]: Release v1 created by user macchiang@gmail.com</span>`</div><div id="bkmrk-2021-11-09t15%3A17%3A06.-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:17:06.932541+00:00 app[api]: Initial release by user macchiang@gmail.com</span>`</div><div id="bkmrk-2021-11-09t15%3A17%3A07.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:17:07.532399+00:00 app[api]: Release v2 created by user macchiang@gmail.com</span>`</div><div id="bkmrk-2021-11-09t15%3A17%3A07.-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:17:07.532399+00:00 app[api]: Enable Logplex by user macchiang@gmail.com</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A12.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:12.485507+00:00 app[api]: Deployed web (1be43e5135d6) by user macchiang@gmail.com</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A12.-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:12.485507+00:00 app[api]: Release v3 created by user macchiang@gmail.com</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A12.-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:12.503987+00:00 app[api]: Scaled to web@1:Free by user macchiang@gmail.com</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A15.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:15.916499+00:00 heroku[web.1]: Starting process with command `python app.py`</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A18.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:18.365293+00:00 app[web.1]: Traceback (most recent call last):</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A18.-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:18.365308+00:00 app[web.1]: File "/app/app.py", line 15, in <module></span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A18.-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:18.365410+00:00 app[web.1]: line_bot_api = LineBotApi(os.getenv('CHANNEL_ACCESS_TOKEN'))</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A18.-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:18.365411+00:00 app[web.1]: File "/usr/local/lib/python3.10/site-packages/linebot/api.py", line 63, in __init__</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A18.-3">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:18.365516+00:00 app[web.1]: 'Authorization': 'Bearer ' + channel_access_token,</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A18.-4">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:18.374292+00:00 app[web.1]: TypeError: can only concatenate str (not "NoneType") to str</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A18.-5">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:18.660220+00:00 heroku[web.1]: Process exited with status 1</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A19.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:19.074969+00:00 heroku[web.1]: State changed from starting to crashed</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A19.-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:19.218365+00:00 heroku[web.1]: State changed from crashed to starting</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A22.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:22.107500+00:00 heroku[web.1]: Starting process with command `python app.py`</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A23.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:23.219784+00:00 app[web.1]: Traceback (most recent call last):</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A23.-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:23.219806+00:00 app[web.1]: File "/app/app.py", line 15, in <module></span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A23.-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:23.219930+00:00 app[web.1]: line_bot_api = LineBotApi(os.getenv('CHANNEL_ACCESS_TOKEN'))</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A23.-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:23.219934+00:00 app[web.1]: File "/usr/local/lib/python3.10/site-packages/linebot/api.py", line 63, in __init__</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A23.-3">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:23.219959+00:00 app[web.1]: 'Authorization': 'Bearer ' + channel_access_token,</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A23.-4">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:23.219961+00:00 app[web.1]: TypeError: can only concatenate str (not "NoneType") to str</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A23.-5">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:23.417290+00:00 heroku[web.1]: Process exited with status 1</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A23.-6">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:23.492672+00:00 heroku[web.1]: State changed from starting to crashed</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A38.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:38.443725+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=morning-journey-43865.herokuapp.com request_id=b91dba06-950e-4887-840e-60fc5986866f fwd="36.227.157.168" dyno= connect= service= status=503 bytes= protocol=https</span>`</div><div id="bkmrk-2021-11-09t15%3A22%3A39.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">2021-11-09T15:22:39.424038+00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=morning-journey-43865.herokuapp.com request_id=becc5a52-35a7-4557-b751-02d382a2b67e fwd="36.227.157.168" dyno= connect= service= status=503 bytes= protocol=https</span>`</div># <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![american football](https://paper.dropboxstatic.com/static/img/ace/emoji/1f3c8.png?version=6.0.0 "american football")</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> Docker X PHP實作：架設一個 WordPress 網站</span>

## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">透過 Dockerfile 部署 PHP 環境</span>

<div id="bkmrk-%E5%85%88%E5%BE%9Ephp%E5%AE%98%E6%96%B9dockerfile%E5%AD%B8%E8%B5%B7"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**先從**</span><span class="attrlink url author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">[**Php官方**](https://hub.docker.com/_/php)</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**Dockerfile學起**</span></span></div><div id="bkmrk-https%3A%2F%2Fgithub.com%2Fm-3"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://github.com/macchiang/php-hello-world","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://github.com/macchiang/php-hello-world">[https://github.com/macchiang/php-hello-world](https://github.com/macchiang/php-hello-world)  
</span></span></div><div id="bkmrk-dockerfile-1"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Dockerfile</span></div><div id="bkmrk-from-php%3A7.3-apache">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">FROM php:7.3-apache</span>`</div><div id="bkmrk-copy-index.php-%2Fvar%2F">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY index.php /var/www/html/</span>`</div><div id="bkmrk--94"></div><div id="bkmrk-%E5%BB%BA%E7%AB%8Bdocker-image%E8%88%87conta"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">建立Docker image與Container</span></div><div id="bkmrk-docker-build-.--t-he">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker build . -t hello:latest</span>`</div><div id="bkmrk-docker-run--it---rm--0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker run -it --rm -p 8080:80 hello:latest</span>`</div><div id="bkmrk-https%3A%2F%2Fwww.astralwe"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://www.astralweb.com.tw/what-is-differences-between-fastcgi-php-fpm/","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://www.astralweb.com.tw/what-is-differences-between-fastcgi-php-fpm/">[https://www.astralweb.com.tw/what-is-differences-between-fastcgi-php-fpm/](https://www.astralweb.com.tw/what-is-differences-between-fastcgi-php-fpm/)  
</span></span></div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">將 MySQL 加入部署行列</span>

<div id="bkmrk-https%3A%2F%2Fgithub.com%2Fm-4"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://github.com/macchiang/php-docker-simple","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://github.com/macchiang/php-docker-simple">[https://github.com/macchiang/php-docker-simple](https://github.com/macchiang/php-docker-simple)  
</span></span></div><div id="bkmrk-docker-compose.yml-0"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose.yml</span></div><div id="bkmrk-%23-use-root%2Fexample-u">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># Use root/example user/password credentials</span>`</div><div id="bkmrk-version%3A-%273.1%27">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">version: '3.1'</span>`</div><div id="bkmrk-%C2%A0-38">` `</div><div id="bkmrk-services%3A-6">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">services:</span>`</div><div id="bkmrk-%C2%A0-php%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  php:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-build%3A-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    build:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-context%3A-.-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      context: .</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-dockerfile%3A-do-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      dockerfile: Dockerfile</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-ports%3A-5">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    ports:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---80%3A80">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - 80:80</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-volumes%3A-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    volumes:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---.%2Fsrc%3A%2Fvar%2Fw">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - ./src:/var/www/html/</span>`</div><div id="bkmrk-%C2%A0-39">` `</div><div id="bkmrk-%C2%A0-db%3A-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  db:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-mysql">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: mysql</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-command%3A---defau">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    command: --default-authentication-plugin=mysql_native_password</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-restart%3A-always">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    restart: always</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-environment%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    environment:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-mysql_root_pas">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      MYSQL_ROOT_PASSWORD: example</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-volumes%3A-3">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    volumes:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---mysql-data%3A%2F">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - mysql-data:/var/lib/mysql</span>`</div><div id="bkmrk-%C2%A0-40">` `</div><div id="bkmrk-%C2%A0-adminer%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  adminer:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-adminer">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: adminer</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-restart%3A-always-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    restart: always</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-ports%3A-6">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    ports:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---8080%3A8080">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - 8080:8080</span>`</div><div id="bkmrk-%C2%A0-41">` `</div><div id="bkmrk-volumes%3A-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">volumes:</span>`</div><div id="bkmrk-%C2%A0-mysql-data%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  mysql-data:</span>`</div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">建立WordPress 網站</span>

<div id="bkmrk-%E5%86%8D%E7%94%B1wordpresss%E5%AE%98%E6%96%B9docker"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**再由**</span><span class="attrlink url author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">[**WordPresss官方Dockerfile學起**](https://github.com/docker-library/wordpress/blob/master/latest/php7.3/apache/Dockerfile)</span></span></div><div id="bkmrk-%C2%A0%23">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> #</span>`</div><div id="bkmrk-%23-note%3A-this-dockerf">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"</span>`</div><div id="bkmrk-%23">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#</span>`</div><div id="bkmrk-%23-please-do-not-edit">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># PLEASE DO NOT EDIT IT DIRECTLY.</span>`</div><div id="bkmrk-%23-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">#</span>`</div><div id="bkmrk-%C2%A0-42">` `</div><div id="bkmrk-from-php%3A7.3-apache-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">FROM php:7.3-apache</span>`</div><div id="bkmrk-%C2%A0-43">` `</div><div id="bkmrk-%23-persistent-depende">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># persistent dependencies</span>`</div><div id="bkmrk-run-set--eux%3B-%5C">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN set -eux; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-apt-get-upda">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        apt-get update; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-apt-get-inst">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        apt-get install -y --no-install-recommends \</span>`</div><div id="bkmrk-%23-ghostscript-is-req">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># Ghostscript is required for rendering PDF previews</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-ghos">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                ghostscript \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%3B-%5C">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        ; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-rm--rf-%2Fvar%2F">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        rm -rf /var/lib/apt/lists/*</span>`</div><div id="bkmrk-%C2%A0-44">` `</div><div id="bkmrk-%23-install-the-php-ex">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># install the PHP extensions we need (https://make.wordpress.org/hosting/handbook/handbook/server-environment/#php-extensions)</span>`</div><div id="bkmrk-run-set--ex%3B-%5C">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN set -ex; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%5C">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-savedaptmark">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        savedAptMark="$(apt-mark showmanual)"; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%5C-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-apt-get-upda-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        apt-get update; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-apt-get-inst-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        apt-get install -y --no-install-recommends \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-libf">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                libfreetype6-dev \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-libj">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                libjpeg-dev \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-libm">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                libmagickwand-dev \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-libp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                libpng-dev \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-libw">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                libwebp-dev \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-libz">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                libzip-dev \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%3B-%5C-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        ; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%5C-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-docker-php-e">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        </span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>docker-php-ext-configure</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> gd \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0---wi">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                --with-freetype-dir=/usr \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0---wi-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                --with-jpeg-dir=/usr \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0---wi-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                --with-png-dir=/usr \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0---wi-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                --with-webp-dir=/usr \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%3B-%5C-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        ; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-docker-php-e-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        </span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>docker-php-ext-install</strong></span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> -j "$(nproc)" \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-bcma">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                bcmath \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-exif">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                exif \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-gd-%5C">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                gd \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-mysq">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                mysqli \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-zip-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                zip \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%3B-%5C-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        ; \</span>`</div><div id="bkmrk-%23-https%3A%2F%2Fpecl.php.n">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># https://pecl.php.net/package/imagick</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-pecl-install">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        pecl install imagick-3.5.0; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-docker-php-e-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        docker-php-ext-enable imagick; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-rm--r-%2Ftmp%2Fp">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        rm -r /tmp/pear; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%5C-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        \</span>`</div><div id="bkmrk-%23-reset-apt-mark%27s-%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-apt-mark-aut">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        apt-mark auto '.*' > /dev/null; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-apt-mark-man">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        apt-mark manual $savedAptMark; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-ldd-%22%24%28php--">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%7C-aw">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                | awk '/=>/ { print $3 }' \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%7C-so">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                | sort -u \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%7C-xa">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                | xargs -r dpkg-query -S \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%7C-cu">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                | cut -d: -f1 \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%7C-so-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                | sort -u \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%7C-xa-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                | xargs -rt apt-mark manual; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%5C-3">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-apt-get-purg">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-rm--rf-%2Fvar%2F-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        rm -rf /var/lib/apt/lists/*</span>`</div><div id="bkmrk-%C2%A0-45">` `</div><div id="bkmrk-%23-set-recommended-ph">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># set recommended PHP.ini settings</span>`</div><div id="bkmrk-%23-see-https%3A%2F%2Fsecure">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># see https://secure.php.net/manual/en/opcache.installation.php</span>`</div><div id="bkmrk-run-set--eux%3B-%5C-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN set -eux; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-docker-php-e-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        docker-php-ext-enable opcache; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%7B-%5C">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        { \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'opcache.memory_consumption=128'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'opcache.interned_strings_buffer=8'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'opcache.max_accelerated_files=4000'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'opcache.revalidate_freq=2'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-3">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'opcache.fast_shutdown=1'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%7D-%3E-%2Fusr%2Floc">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        } > /usr/local/etc/php/conf.d/opcache-recommended.ini</span>`</div><div id="bkmrk-%23-https%3A%2F%2Fwordpress.">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># https://wordpress.org/support/article/editing-wp-config-php/#configure-error-logging</span>`</div><div id="bkmrk-run-%7B-%5C">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN { \</span>`</div><div id="bkmrk-%23-https%3A%2F%2Fwww.php.ne">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># https://www.php.net/manual/en/errorfunc.constants.php</span>`</div><div id="bkmrk-%23-https%3A%2F%2Fgithub.com">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># https://github.com/docker-library/wordpress/issues/420#issuecomment-517839670</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-4">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'error_reporting = E_ERROR | E_WARNING | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_RECOVERABLE_ERROR'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-5">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'display_errors = Off'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-6">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'display_startup_errors = Off'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-7">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'log_errors = On'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-8">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'error_log = /dev/stderr'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-9">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'log_errors_max_len = 1024'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-10">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'ignore_repeated_errors = On'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-11">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'ignore_repeated_source = Off'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-12">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'html_errors = Off'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%7D-%3E-%2Fusr%2Floc-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        } > /usr/local/etc/php/conf.d/error-logging.ini</span>`</div><div id="bkmrk-%C2%A0-46">` `</div><div id="bkmrk-run-set--eux%3B-%5C-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN set -eux; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-a2enmod-rewr">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        a2enmod rewrite expires; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%5C-4">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        \</span>`</div><div id="bkmrk-%23-https%3A%2F%2Fhttpd.apac">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-a2enmod-remo">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        a2enmod remoteip; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%7B-%5C-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        { \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-13">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'RemoteIPHeader X-Forwarded-For'; \</span>`</div><div id="bkmrk-%23-these-ip-ranges-ar">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># these IP ranges are reserved for "private" use and should thus *usually* be safe inside Docker</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-14">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'RemoteIPTrustedProxy 10.0.0.0/8'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-15">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'RemoteIPTrustedProxy 172.16.0.0/12'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-16">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'RemoteIPTrustedProxy 192.168.0.0/16'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-17">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'RemoteIPTrustedProxy 169.254.0.0/16'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-18">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'RemoteIPTrustedProxy 127.0.0.0/8'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%7D-%3E-%2Fetc%2Fapa">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        } > /etc/apache2/conf-available/remoteip.conf; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-a2enconf-rem">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        a2enconf remoteip; \</span>`</div><div id="bkmrk-%23-https%3A%2F%2Fgithub.com-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># https://github.com/docker-library/wordpress/issues/383#issuecomment-507886512</span>`</div><div id="bkmrk-%23-%28replace-all-insta">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># (replace all instances of "%h" with "%a" in LogFormat)</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-find-%2Fetc%2Fap">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        find /etc/apache2 -type f -name '*.conf' -exec sed -ri 's/([[:space:]]*LogFormat[[:space:]]+"[^"]*)%h([^"]*")/\1%a\2/g' '{}' +</span>`</div><div id="bkmrk-%C2%A0-47">` `</div><div id="bkmrk-run-set--eux%3B-%5C-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN set -eux; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-version%3D%275.8">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        version='5.8.2'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-sha1%3D%27c3b1b5">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        sha1='c3b1b59553eafbf301c83b14c5eeae4cf1c86044'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%5C-5">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-curl--o-word">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        curl -o wordpress.tar.gz -fL "https://wordpress.org/wordpress-$version.tar.gz"; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-%22%24sha1-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        echo "$sha1 *wordpress.tar.gz" | sha1sum -c -; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%5C-6">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        \</span>`</div><div id="bkmrk-%23-upstream-tarballs-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-tar--xzf-wor">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        tar -xzf wordpress.tar.gz -C /usr/src/; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-rm-wordpress">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        rm wordpress.tar.gz; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%5C-7">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        \</span>`</div><div id="bkmrk-%23-https%3A%2F%2Fwordpress.-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># https://wordpress.org/support/article/htaccess/</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%5B-%21--e-%2Fusr%2F">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        [ ! -e /usr/src/wordpress/.htaccess ]; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%7B-%5C-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        { \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-19">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo '# BEGIN WordPress'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-20">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo ''; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-21">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'RewriteEngine On'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-23">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'RewriteBase /'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-24">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'RewriteRule ^index\.php$ - [L]'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-25">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'RewriteCond %{REQUEST_FILENAME} !-f'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-26">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'RewriteCond %{REQUEST_FILENAME} !-d'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-27">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo 'RewriteRule . /index.php [L]'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-28">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo ''; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-echo-29">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                echo '# END WordPress'; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%7D-%3E-%2Fusr%2Fsrc">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        } > /usr/src/wordpress/.htaccess; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%5C-8">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-chown--r-www">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        chown -R www-data:www-data /usr/src/wordpress; \</span>`</div><div id="bkmrk-%23-pre-create-wp-cont">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># pre-create wp-content (and single-level children) for folks who want to bind-mount themes, etc so permissions are pre-created properly instead of root:root</span>`</div><div id="bkmrk-%23-wp-content%2Fcache%3A-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># wp-content/cache: https://github.com/docker-library/wordpress/issues/534#issuecomment-705733507</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-mkdir-wp-con">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        mkdir wp-content; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-for-dir-in-%2F">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        for dir in /usr/src/wordpress/wp-content/*/ cache; do \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-dir%3D">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                dir="$(basename "${dir%/}")"; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-%C2%A0-mkdi">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">                mkdir "wp-content/$dir"; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-done%3B-%5C">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        done; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-chown--r-www-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        chown -R www-data:www-data wp-content; \</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-chmod--r-777">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        chmod -R 777 wp-content</span>`</div><div id="bkmrk-%C2%A0-48">` `</div><div id="bkmrk-volume-%2Fvar%2Fwww%2Fhtml">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">VOLUME /var/www/html</span>`</div><div id="bkmrk-%C2%A0-49">` `</div><div id="bkmrk-copy---chown%3Dwww-dat">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY --chown=www-data:www-data wp-config-docker.php /usr/src/wordpress/</span>`</div><div id="bkmrk-copy-docker-entrypoi">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY docker-entrypoint.sh /usr/local/bin/</span>`</div><div id="bkmrk-%C2%A0-50">` `</div><div id="bkmrk-entrypoint-%5B%22docker-">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">ENTRYPOINT ["docker-entrypoint.sh"]</span>`</div><div id="bkmrk-cmd-%5B%22apache2-foregr">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">CMD ["apache2-foreground"]</span>`</div><div id="bkmrk--95"></div><div id="bkmrk-https%3A%2F%2Fgithub.com%2Fm-5"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://github.com/macchiang/wordpress-demo","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://github.com/macchiang/wordpress-demo">[https://github.com/macchiang/wordpress-demo](https://github.com/macchiang/wordpress-demo)  
</span></span></div><div id="bkmrk-docker-compose.yaml-0"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose.yaml</span></div><div id="bkmrk-version%3A-%223.3%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">version: "3.3"</span>`</div><div id="bkmrk-services%3A-7">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">services:</span>`</div><div id="bkmrk-%C2%A0-db%3A-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  db:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-mysql-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: mysql</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-volumes%3A-4">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    volumes:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---db_data%3A%2Fvar">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - db_data:/var/lib/mysql</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-restart%3A-always-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    restart: always</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-environment%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    environment:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-mysql_root_pas-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      MYSQL_ROOT_PASSWORD: somewordpress</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-mysql_database">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      MYSQL_DATABASE: wordpress</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-mysql_user%3A-wo">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      MYSQL_USER: wordpress</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-mysql_password">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      MYSQL_PASSWORD: wordpress</span>`</div><div id="bkmrk-%C2%A0-wordpress%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  wordpress:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-depends_on%3A-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    depends_on:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---db">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - db</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-wordpress">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: wordpress</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-ports%3A-7">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    ports:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---%228000%3A80%22">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - "8000:80"</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-restart%3A-always-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    restart: always</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-environment%3A-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    environment:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-wordpress_db_h">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      WORDPRESS_DB_HOST: db:3306</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-wordpress_db_u">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      WORDPRESS_DB_USER: wordpress</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-wordpress_db_p">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      WORDPRESS_DB_PASSWORD: wordpress</span>`</div><div id="bkmrk-volumes%3A-3">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">volumes:</span>`</div><div id="bkmrk-%C2%A0-db_data%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  db_data:</span>`</div><div id="bkmrk-%C2%A0-51">` `</div># <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![ping pong](https://paper.dropboxstatic.com/static/img/ace/emoji/1f3d3.png?version=6.0.0 "ping pong")</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> Docker X Node.js實作：打造前後端具備的 To-Do List</span>

## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">建立Express + Nginx組合</span>

<div id="bkmrk-https%3A%2F%2Fgithub.com%2Fm-6"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://github.com/macchiang/express-nginx","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://github.com/macchiang/express-nginx">[https://github.com/macchiang/express-nginx](https://github.com/macchiang/express-nginx)  
</span></span></div><div id="bkmrk-nginx-config"><span class="ace-all-bold-hthree"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">**Nginx config**</span></span></div><div id="bkmrk-server-%7B">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">server {</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-listen-80-defaul">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    listen 80 default_server;</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-listen-%5B%3A%3A%5D%3A80-d">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    listen [::]:80 default_server;</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-server_tokens-of">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    server_tokens off;</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-client_max_body_">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    client_max_body_size 15M;</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-if-%28%24http_x_forw">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    if ($http_x_forwarded_proto = "http") {</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-return-301-h">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        return 301 https://$host$request_uri;</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%7D">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    }</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-location-%2F-%7B">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    location / {</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-proxy_set_he">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        proxy_set_header X-Real-IP $remote_addr;</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-proxy_set_he-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-proxy_set_he-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        proxy_set_header Host $http_host;</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-proxy_set_he-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        proxy_set_header X-NginX-Proxy true;</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-proxy_pass-h">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        </span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><strong>proxy_pass http://node:3000;</strong></span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-%C2%A0-proxy_redire">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">        proxy_redirect off;</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%7D-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    }</span>`</div><div id="bkmrk-%7D-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">}</span>`</div><div id="bkmrk--96"></div><div id="bkmrk-docker-compose.yml-1"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose.yml</span></div><div id="bkmrk-version%3A-%223%22-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">version: "3"</span>`</div><div id="bkmrk-services%3A-8">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">services:</span>`</div><div id="bkmrk-%C2%A0-nginx%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  nginx:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-nginx%3Aalp-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: nginx:alpine</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-volumes%3A-5">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    volumes:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---.%2Fnginx%3A%2Fetc">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - ./nginx:/etc/nginx/conf.d</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-links%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    links:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---node">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - node</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-ports%3A-8">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    ports:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---80%3A80-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - 80:80</span>`</div><div id="bkmrk-%C2%A0-node%3A">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  node:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-build%3A-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    build:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-context%3A-.-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      context: .</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-express-n">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: express-nginx:latest</span>`</div><div id="bkmrk-%C2%A0-52">` `</div>## <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">打造To-Do List</span>

<div id="bkmrk-https%3A%2F%2Fgithub.com%2Fm-7"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://github.com/macchiang/express-mongoDB-TodoList","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://github.com/macchiang/express-mongoDB-TodoList">[https://github.com/macchiang/express-mongoDB-TodoList](https://github.com/macchiang/express-mongoDB-TodoList)  
</span></span></div><div id="bkmrk--97"></div><div id="bkmrk-ddockerfile"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">Ddockerfile</span></div><div id="bkmrk-%23-base-image-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># Base image</span>`</div><div id="bkmrk-from-node%3A16-alpine-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">FROM node:16-alpine</span>`</div><div id="bkmrk-run-apk-upgrade---no-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN apk upgrade --no-cache</span>`</div><div id="bkmrk-%23-create-app-directo-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># Create app directory</span>`</div><div id="bkmrk-run-mkdir--p-%2Fapp-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN mkdir -p /app</span>`</div><div id="bkmrk-workdir-%2Fapp-3">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">WORKDIR /app</span>`</div><div id="bkmrk-%23-install-app-depend-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># Install app dependencies</span>`</div><div id="bkmrk-copy-package.json-pa-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY package.json package-lock.json ./</span>`</div><div id="bkmrk-run-npm-install-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">RUN npm install</span>`</div><div id="bkmrk-%23-copy-app-source-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># copy app source</span>`</div><div id="bkmrk-copy-.-%2Fapp-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">COPY . /app</span>`</div><div id="bkmrk-%23-service-port-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"># service port</span>`</div><div id="bkmrk-expose-3000-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">EXPOSE 3000</span>`</div><div id="bkmrk-cmd-%5B-%22node%22%2C-%22app.j">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">CMD [ "node", "app.js"]</span>`</div><div id="bkmrk--98"></div><div id="bkmrk-docker-compose.yml-2"><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">docker-compose.yml</span></div><div id="bkmrk-version%3A-%223%22-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">version: "3"</span>`</div><div id="bkmrk-services%3A-9">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">services:</span>`</div><div id="bkmrk-%C2%A0-nginx%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  nginx:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-nginx%3Aalp-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: nginx:alpine</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-volumes%3A-6">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    volumes:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---.%2Fnginx%3A%2Fetc-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - ./nginx:/etc/nginx/conf.d</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-links%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    links:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---node-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - node</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-ports%3A-9">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    ports:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---80%3A80-1">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - 80:80</span>`</div><div id="bkmrk-%C2%A0-node%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  node:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-build%3A-3">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    build:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0-context%3A-.-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      context: .</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-depends_on%3A-2">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    depends_on:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---mongo-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - mongo</span>`</div><div id="bkmrk-%C2%A0-mongo%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">  mongo:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-image%3A-mongo%3A5-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    image: mongo:5</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-ports%3A-10">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    ports:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---27017%3A27017-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">      - 27017:27017</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-volumes%3A-7">`    <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">volumes:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-%C2%A0---mongo_data%3A%2F">`      <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">- mongo_data:/data/db</span>`</div><div id="bkmrk-volumes%3A-4">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">volumes:</span>`</div><div id="bkmrk-%C2%A0-%C2%A0-mongo_data%3A-0">`<span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">    mongo_data:</span>`</div># <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">![open book](https://paper.dropboxstatic.com/static/img/ace/emoji/1f4d6.png?version=6.0.0 "open book")</span><span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"> 參考資料</span>

- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://blog.gtwang.org/linux/docker-commands-and-container-management-tutorial/](https://blog.gtwang.org/linux/docker-commands-and-container-management-tutorial/)</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://hub.docker.com/r/broadtech/alpine-apache2/dockerfile](https://hub.docker.com/r/broadtech/alpine-apache2/dockerfile)</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://ithelp.ithome.com.tw/articles/10251549](https://ithelp.ithome.com.tw/articles/10251549)</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://www.tpisoftware.com/tpu/articleDetails/1216](https://www.tpisoftware.com/tpu/articleDetails/1216)</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://yeasy.gitbook.io/docker\_practice](https://yeasy.gitbook.io/docker_practice)</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://blog.techbridge.cc/2018/09/07/docker-compose-tutorial-intro/](https://blog.techbridge.cc/2018/09/07/docker-compose-tutorial-intro/)</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://yeasy.gitbook.io/docker\_practice/compose/usage](https://yeasy.gitbook.io/docker_practice/compose/usage)</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://dev.to/truthseekers/setup-a-basic-local-php-development-environment-in-docker-kod](https://dev.to/truthseekers/setup-a-basic-local-php-development-environment-in-docker-kod)</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://dotblogs.com.tw/explooosion/2018/09/15/194754#2](https://dotblogs.com.tw/explooosion/2018/09/15/194754#2)</span>
- <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z url">[https://dca.gitbooks.io/nodejs-tw-wiki-book/content/book/todo\_list/todo\_list.html](https://dca.gitbooks.io/nodejs-tw-wiki-book/content/book/todo_list/todo_list.html)</span>

<div id="bkmrk--99"></div># <span class=" author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z">推薦學習</span>

<div id="bkmrk-https%3A%2F%2Fdev.to%2Fankit"><span class="gallery author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90za3ls0z82zz79zswnpuz79zedberz68za3xz84zz76zqmz83zmz84z1z75z"><span class="gallery-wrapper" data-ace-gallery-clipboard-json="{"items":[{"type":"unfurl","url":"https://dev.to/ankit01oss/7-github-projects-to-supercharge-your-docker-practices-2i80","serializedZonesForClipboard":{"captionZone":{"atext":{"text":"\n","attribs":"|1+1"},"pool":{"numToAttrib":{},"attribToNum":{},"nextNum":0,"dirty":false,"firstDirtyNum":null}}}}]}" data-ace-gallery-urls="https://dev.to/ankit01oss/7-github-projects-to-supercharge-your-docker-practices-2i80">[https://dev.to/ankit01oss/7-github-projects-to-supercharge-your-docker-practices-2i80](https://dev.to/ankit01oss/7-github-projects-to-supercharge-your-docker-practices-2i80)  
</span></span></div>

# 【上課筆記】【udemy】 Docker容器技术从入门到精通

### 上課講義

- [ https://www.docker.tips](https://www.docker.tips " https://www.docker.tips")

---

### 原始碼

- [Oh My Docker · GitHub](https://github.com/oh-my-docker)
- [GitHub - dockersamples/example-voting-app: Example Docker Compose app](https://github.com/dockersamples/example-voting-app)

# 【Demo】Python Flask + Redis 練習

### 準備一個python文件 app.py

```Python
from flask import Flask
from redis import Redis
import os
import socket

app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)


@app.route('/')
def hello():
    redis.incr('hits')
    return f"Hello Container World! I have been seen {redis.get('hits').decode('utf-8')} times and my hostname is {socket.gethostname()}.\n"
```

### 準備一個Dockerfile

```INI
FROM python:3.9.5-slim

RUN pip install flask redis && \
    groupadd -r flask && useradd -r -g flask flask && \
    mkdir /src && \
    chown -R flask:flask /src

USER flask

COPY app.py /src/app.py

WORKDIR /src

ENV FLASK_APP=app.py REDIS_HOST=redis

EXPOSE 5000

CMD ["flask", "run", "-h", "0.0.0.0"]
```

### 準備一個Redis image

###  

```shell
$ docker image pull redis
$ docker image build -t flask-demo .
$ docker image ls
REPOSITORY   TAG          IMAGE ID       CREATED              SIZE
flask-demo   latest       4778411a24c5   About a minute ago   126MB
python       3.9.5-slim   c71955050276   8 days ago           115MB
redis        latest       08502081bff6   2 weeks ago          105MB
```

### 建立一Bridage

```shell
$ docker network create -d bridge demo-network
8005f4348c44ffe3cdcbbda165beea2b0cb520179d3745b24e8f9e05a3e6456d
$ docker network ls
NETWORK ID     NAME           DRIVER    SCOPE
2a464c0b8ec7   bridge         bridge    local
8005f4348c44   demo-network   bridge    local
80b63f711a37   host           host      local
fae746a75be1   none           null      local
```

### 創建container

創建一個叫 `<span class="pre">redis-server</span>` 的container，連到 demo-network上

```shell
$ docker container run -d --name redis-server --network demo-network redis
002800c265020310231d689e6fd35bc084a0fa015e8b0a3174aa2c5e29824c0e
$ docker container ls
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS      NAMES
002800c26502   redis     "docker-entrypoint.s…"   4 seconds ago   Up 3 seconds   6379/tcp   redis-server

```

創建 flask container，連到 demo-network上

```shell
$ docker container run -d --network demo-network \
--name flask-demo \
--env REDIS_HOST=redis-server \
-p 5000:5000 flask-demo

```

打開瀏覽器訪問 [http://127.0.0.1:5000](http://127.0.0.1:5000/)

應該能看到類似下面的內容，每次刷新頁面，計數加1

Hello Container World! I have been seen 36 times and my hostname is 925ecb8d111a.

合併步驟成一腳本

```shell
# prepare image
docker image pull redis
docker image build -t flask-demo .

# create network
docker network create -d bridge demo-network

# create container
docker container run -d --name redis-server --network demo-network redis
docker container run -d --network demo-network --name flask-demo --env REDIS_HOST=redis-server -p 5000:5000 flask-demo

```

# 【Docker】【錯誤處理】無法停止服務

\*使用systemctl stop docker 無法停止服務

```shell
[root@localhost docker]# systemctl stop docker 
Warning: Stopping docker.service, but it can still be activated by:
  docker.socket

```

\*解決

```shell
#停止
[root@localhost docker]# systemctl stop docker.socket
[root@localhost docker]# systemctl stop docker.service

#啟動
[root@localhost docker]# systemctl daemon-reload
[root@localhost docker]# systemctl restart docker

```

\*\*如果還沒辦法解決

```shell
# 删除 docker socket 文件
cd /lib/systemd/system/  &&  rm -rf docker.socket
# 查看 docker 状态，已dead
sudo systemctl status docker.service
# 重新创建 docker.socket
cd /lib/systemd/system/  
vim docker.socket
# 添加如下内容
[Unit]
Description=Docker Socket for the API
PartOf=docker.service

[Socket]
ListenStream=/var/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker

[Install]
WantedBy=sockets.target
```

```shell
#啟動
[root@localhost docker]# systemctl daemon-reload
[root@localhost docker]# systemctl restart docker

```

# 【Webmin】相關

 查詢被Deny 需要從Zone default -&gt; Allow queries form ... -&gt; 【 Listed..】-&gt; 加入 any -&gt; 右上角 【 Apply 】

[![image-1681888539338.png](https://bookstack.treemanou.com/uploads/images/gallery/2023-04/scaled-1680-/ekv5h0IjPh5QuFza-image-1681888539338.png)](https://bookstack.treemanou.com/uploads/images/gallery/2023-04/ekv5h0IjPh5QuFza-image-1681888539338.png)

[![image-1681888508758.png](https://bookstack.treemanou.com/uploads/images/gallery/2023-04/scaled-1680-/3i1aqB3ElPohVONm-image-1681888508758.png)](https://bookstack.treemanou.com/uploads/images/gallery/2023-04/3i1aqB3ElPohVONm-image-1681888508758.png)

[![image-1681888698503.png](https://bookstack.treemanou.com/uploads/images/gallery/2023-04/scaled-1680-/wxlJrQurZrfPxJgj-image-1681888698503.png)](https://bookstack.treemanou.com/uploads/images/gallery/2023-04/wxlJrQurZrfPxJgj-image-1681888698503.png)

# Docker 各系統安裝

### 各系統安裝連結

- zabbix  
    [https://www.zabbix.com/documentation/4.4/zh/manual/installation/containers](https://www.zabbix.com/documentation/4.4/zh/manual/installation/containers)  
    [https://github.com/zabbix/zabbix-docker/tree/6.4/Dockerfiles/web-nginx-pgsql](https://github.com/zabbix/zabbix-docker/tree/6.4/Dockerfiles/web-nginx-pgsql)
- elk  
    <div><div>[https://github.com/deviantony/docker-elk](https://github.com/deviantony/docker-elk)  
    https://github.com/deviantony/docker-elk</div></div>
- smokeping  
    [https://cloud.tencent.com/developer/article/1703797](https://cloud.tencent.com/developer/article/1703797)
- jenkins  
    [https://hub.docker.com/\_/jenkins/](https://hub.docker.com/_/jenkins/)
- wekan  
    [https://github.com/wekan/wekan/wiki/Docker](https://github.com/wekan/wekan/wiki/Docker)  
    [https://wekan.github.io/wekan-doc/](https://wekan.github.io/wekan-doc/) (文件)
- postgresSQL  
    [https://hub.docker.com/\_/postgres](https://hub.docker.com/_/postgres)  
    [https://cde566.medium.com/docker-compose%E5%89%B5%E5%BB%BApostgresql-7f3f9519fa20](https://cde566.medium.com/docker-compose%E5%89%B5%E5%BB%BApostgresql-7f3f9519fa20)
- powerdns  
    [https://blog.csdn.net/sdhzdtwhm/article/details/135910057](https://blog.csdn.net/sdhzdtwhm/article/details/135910057)

---

###  

### Jenkins

[Jenkins - Official Image | Docker Hub](https://hub.docker.com/_/jenkins)

[jenkins/jenkins - Docker Image | Docker Hub](https://hub.docker.com/r/jenkins/jenkins)

```shell
docker run -d	\
	-p 8080:8080 -p 50000:50000 \
	-v ~/jenkins/home:/var/jenkins_home \
    --name jenkins \
    jenkins/jenkins:lts
```

ps. jenkins 抓取一定要帶版號不然會報錯

[jenkins Tags | Docker Hub](https://hub.docker.com/_/jenkins?tab=tags)

```
Using default tag: latest
Error response from daemon: manifest for jenkins:latest not found: manifest unknown: manifest unknown
```

```shell
docker pull jenkins/jenkins:lts
```

ps. 要安裝軟體需要使用root 登入

```shell
docker exec -u root -it jenkins sh
```

```
touch: cannot touch ‘/var/jenkins_home/copy_reference_file.log’: Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?
```

```shell
sudo chown -R 1000:1000 {mount jenkins home path}
```

ps.使用nginx revers proxy 現設定問題，需要設定 proxy\_set\_header

[Reverse proxy configuration (jenkins.io)](https://www.jenkins.io/doc/book/system-administration/reverse-proxy-configuration-with-jenkins/)

```
server {
    listen       80;
    server_name  tomcat.srou.com;

    location / {
         sendfile off;
        proxy_pass   http://192.168.100.4:10031/;
        proxy_redirect     default;
        proxy_http_version 1.1;

        # Required for Jenkins websocket agents
        proxy_set_header   Upgrade           $http_upgrade;

        proxy_set_header   Host              $host;
        proxy_set_header   X-Real-IP         $remote_addr;
        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_max_temp_file_size 0;

        #this is the maximum upload size
        client_max_body_size       10m;
        client_body_buffer_size    128k;

        proxy_connect_timeout      90;
        proxy_send_timeout         90;
        proxy_read_timeout         90;
        proxy_buffering            off;
        proxy_request_buffering    off; # Required for HTTP CLI commands
        proxy_set_header Connection ""; # Clear for keepalive
      
        
    }

}

```

---

### gitlab

```shell
docker run -d \
	--name gitlab \
	-p 8080:80 -p 443:443 -p 22:22 \
    --privileged \
    --restart always \
    -v ~/gitlab/config:/etc/gitlab \
    -v ~/gitlab/logs:/var/log/gitlab \
    -v ~/gitlab/data:/var/opt/gitlab  \
    gitlab/gitlab-ce
 
```

```
-d : 讓容器(Container)在背景執行
--name : 指定容器(Container)的名稱
-p : 指定主端(Host)對應客端(Quest)的連接埠
--privileged : 容器(Container)内的 root 拥有真正的 root 权限
-restart : 設定為 restart，則容器在異常停止後，會自動重新起動
-v : 將容器(Container)內需永續保存的目錄，連結至主端的目錄
```

 docker-compose.yml

```shell
docker-compose up -d
```

```YAML
version: "3.6"
services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    restart: always
    privileged: true
    ports:
      - '8080:80'
      - '443:443'
      - '22:22'
    volumes:
      - '~/gitlab/data:/var/opt/gitlab'
      - '~/gitlab/logs:/var/log/gitlab'
      - '~/gitlab/config:/etc/gitlab'
```

---

### Tomcat

[Docker部署tomcat出現404錯誤 - 台部落 (twblogs.net)](https://www.twblogs.net/a/5e90b821bd9eee34209011b0)

新版tomcat 不提供manager ，需手動複製，webapps.dist copy -&gt; webapps

---

### PostgresSQL

```YAML
version: "3.7"
services:
    db:
        image: postgres:13.2-alpine
        restart: always
        environment:
            POSTGRES_DB: postgres
            POSTGRES_USER: $USER_NAME #postgres
            POSTGRES_PASSWORD: $PASSWORD #1234
            PGDATA: /var/lib/postgresql/data
        volumes:
            - db-data:/var/lib/postgresql/data
        ports:
            - "5432:5432"
    pgadmin:
        image: dpage/pgadmin4:latest
        restart: always
        environment:
            PGADMIN_DEFAULT_EMAIL: $USER_EMAIL #xxx@gmail
            PGADMIN_DEFAULT_PASSWORD: $PASSWORD #abcd
            PGADMIN_LISTEN_PORT: 80
        ports:
            - "8080:80"
        volumes:
            - pgadmin-data:/var/lib/pgadmin
        links:
            - "db:pgsql-server"
volumes:
    db-data:
    pgadmin-data:
```

# Docker 安全性

[為何在 Docker 中執行特權容器不是個好主意? – 資安趨勢部落格 (trendmicro.com.tw)](https://blog.trendmicro.com.tw/?p=62986)

# Docker 相關連結

#### docker 測試環境(play with docker)

[Play with Docker (play-with-docker.com)](https://labs.play-with-docker.com/)

---

##### 【上課講義】【udemy】 Docker容器技术从入门到精通

- [https://www.docker.tips](https://www.docker.tips/)
- [Vagrant入门系列 - YouTube](https://www.youtube.com/playlist?list=PLfQqWeOCIH4B6YAEXMr6cx4AfnKNBLbZO)

##### 【上課講義】【hiskio】Docker 完全實作！結合 3 大語言掌握容器實務應用

[Docker 完全實作 – Dropbox Paper](https://paper.dropbox.com/doc/Docker--BaNWxS3HDfry~X6QJb7Ze4plAg-pcGbQoyLtmiPPoIlkkK2r)

##### 【鐵人賽】用30天來介紹和使用 Docker

[用30天來介紹和使用 Docker :: 2018 iT 邦幫忙鐵人賽 (ithome.com.tw)](https://ithelp.ithome.com.tw/users/20103456/ironman/1320?page=1)

##### Docker File 官方說明

[Dockerfile reference | Docker Documentation](https://docs.docker.com/engine/reference/builder/)

##### Spring Boot with Docker

[Getting Started | Spring Boot with Docker](https://spring.io/guides/gs/spring-boot-docker/)

##### Docker 從入門到實踐

[前言 - 《Docker —— 從入門到實踐­》正體中文版 (gitbook.io)](https://philipzheng.gitbook.io/docker_practice/)

##### Docker 與 JAVA開發實戰-程序员欣宸

[https://github.com/zq2599/blog\_demos](https://github.com/zq2599/blog_demos)

---

### 各系統安裝連結

- zabbix  
    [https://www.zabbix.com/documentation/4.4/zh/manual/installation/containers](https://www.zabbix.com/documentation/4.4/zh/manual/installation/containers)  
    [https://github.com/zabbix/zabbix-docker/tree/6.4/Dockerfiles/web-nginx-pgsql](https://github.com/zabbix/zabbix-docker/tree/6.4/Dockerfiles/web-nginx-pgsql)
- elk  
    <div><div>[https://github.com/deviantony/docker-elk](https://github.com/deviantony/docker-elk)</div></div>
- smokeping  
    [https://cloud.tencent.com/developer/article/1703797](https://cloud.tencent.com/developer/article/1703797)
- jenkins  
    [https://hub.docker.com/\_/jenkins/](https://hub.docker.com/_/jenkins/)

# Docker 部署IIS

- [\[Docker\] 容器初體驗 - 搞個 IIS Container 來部署網站 | 搞搞就懂 - 點部落 (dotblogs.com.tw)](https://dotblogs.com.tw/wasichris/2020/02/12/164746)
- [將 ASP.NET MVC 應用程式遷移到 Windows 容器 | Microsoft Learn](https://learn.microsoft.com/zh-tw/aspnet/mvc/overview/deployment/docker-aspnetmvc)
- [準備 Windows 作業系統容器 | Microsoft Learn](https://learn.microsoft.com/zh-tw/virtualization/windowscontainers/quick-start/set-up-environment?tabs=Windows-Server#prerequisites)

# Docker 監控相關

#### cadvisor 監控主機狀況

```shell
# 使用cadvisor
$ docker run -d --restart=always -v /var/run:/var/run:rw -p 8080:8080 --name=cadvisor google/cadvisor:latest
```

#### netdata 監控主機狀況

[Install Netdata with Docker | Learn Netdata](https://learn.netdata.cloud/docs/agent/packaging/docker)

```shell
docker run -d --name=netdata \
  -p 19999:19999 \
  -v netdataconfig:/etc/netdata \
  -v netdatalib:/var/lib/netdata \
  -v netdatacache:/var/cache/netdata \
  -v /etc/passwd:/host/etc/passwd:ro \
  -v /etc/group:/host/etc/group:ro \
  -v /proc:/host/proc:ro \
  -v /sys:/host/sys:ro \
  -v /etc/os-release:/host/etc/os-release:ro \
  --restart unless-stopped \
  --cap-add SYS_PTRACE \
  --security-opt apparmor=unconfined \
  netdata/netdata
```

# Docker 儲存

[![image-1675737589104.png](https://bookstack.treemanou.com/uploads/images/gallery/2023-02/scaled-1680-/bAEvwM8s8ZONGIss-image-1675737589104.png)](https://bookstack.treemanou.com/uploads/images/gallery/2023-02/bAEvwM8s8ZONGIss-image-1675737589104.png)

### **--mount 與 -v/ --volume**

當在使用 docker create 或是 docker run 的指令時，會有兩個選項可以使用，個別是 --mount 以及 -v (或是 --volume)。

<span class="s1">注意，千萬不要誤以為使用</span> -v <span class="s1">就是用</span> Volume <span class="s1">的方式或者是</span> --mount <span class="s1">就是使用</span> Bind Mount <span class="s1">的方式，不是這樣的！！我們先來看看這兩個在</span> docker create <span class="s1">與</span> docker run <span class="s1">中的說明是甚麼：</span>

```p2
-v, --volume list      Bind mount a volume
    --mount mount      Attach a filesystem mount to the container
```

但其實是可以用 --mount 或 -v 來綁定資料到 Volume，也可以用 --mount 或 -v 來綁定資料到 Filesystem。既然都可以，那為什麼要分兩種呢？

這是因為<span class="s1"> --mount </span>其實出現的比較早，但他設定綁定資料的方式比較完整卻麻煩，因此在後續又出現了<span class="s1"> -v </span>的選項來簡化綁定的設定過程。

---

### **Data Volume**

相關指令

```shell
# 建立volume 
# docker volume create [OPTIONS] [VOLUME]
$docker volume create my-vol

#使用 -v
$ docker run -d --name my-http -v my-vol:/usr/local/apache2 -p 8080:80 httpd
#使用 --mount
$ docker run -d --name my-http --mount source=my-vol,target=/usr/local/apache2 -p 8080:80 httpd
```

```shell
# 列出所有volume
[tomcat@docker]$ docker volume ls
DRIVER              VOLUME NAME
local               2db2d2b1a6ceb9f578d2149dc44625e1996dcc33de0639f8644ce2082182b9a8
local     			my-vol

# 查詢某volume細節
[tomcat@docke]$ docker volume inspect 2db2d2b1a6ceb9f578d2149dc44625e1996dcc33de0639f8644ce2082182b9a8
[
    {
        "CreatedAt": "2019-06-04T15:40:43+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/2db2d2b1a6ceb9f578d2149dc44625e1996dcc33de0639f8644ce2082182b9a8/_data",
        "Name": "2db2d2b1a6ceb9f578d2149dc44625e1996dcc33de0639f8644ce2082182b9a8",
        "Options": null,
        "Scope": "local"
    }
]

[tomcat@docke]$ docker volume inspect my-vol
[
    {
        "CreatedAt": "2023-02-07T02:11:18Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]


# 刪除所有不使用的volume
[tomcat@docker]$ docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
2db2d2b1a6ceb9f578d2149dc44625e1996dcc33de0639f8644ce2082182b9a8
44d6286d1a793ac8c788b0fd364fa8d9430ce3ec079731dbe894dd996cae9adb
925559f4c2399c0c989d8602ca77fb3243dfb83022fe029b09b130c9521e7f89
9484acbd73c53af47f29add893c5125b0cd7f0f96e521c54e643f1aeb8f97eeb
b47202da45060de8f67e48058966b32078d525cadd1c94671a0ffe33f3d5df4b
006d620ae77bf7530ea37abd48b9c20ac264956f4b9ef3397e2c5072f32677c2
15e0fd2e575c2c24a2a137ff420dbf30326f3859d483561efc45e568d294c802
98b5385b04a401e9e870c5a1e807d69c56a1764b2ec91baedd9c13994cb2c863
ffdae0e84d00966afdc0df55d664d06ee99c14d249ad7558848088c464d472ff

Total reclaimed space: 77.8MB

# 指定volume mount 至 /var/www/html
[tomcat@docker]$ docker run -d -v html_doc:/var/www/html httpd



```

---

### **Bind Mount to FileSystem**

```shell
# 直接mount 外部資料夾 至 /var/www/html
# 相對路徑
[tomcat@docker-qc html-doc]$ docker run -d -v ${PWD}/html-doc:/var/www/html httpd
# 絕對路徑
[tomcat@docker-qc html-doc]$ docker run -d -v /home/tomcat/docker/html-doc:/var/www/html httpd
```

### **Bind Mount to Memory**

Tmpfs，全名 Temporary File System，是在 Linux 暫存檔儲存空間的常見名稱，通常以掛載檔案系統方式實現。他可以將資料儲存在記憶體中而不是存在硬碟內，所以只要一重新開機，資料則會被抹除。

Tmpfs <span class="s1">如其名，如果使用</span> Tmpfs Mount <span class="s1">則資料會存在於記憶體上，在重啟</span> Container <span class="s1">的時候就會</span> Reset <span class="s1">資料。</span>

<span style="background-color: #ffff99;"><span class="s1">特別注意的是，使用</span> Tmpfs Mount <span class="s1">並不是使用</span> -v <span class="s1">的選項，而是使用</span> --tmpfs <span class="s1">，</span>--tmpfs <span class="s1">就如同</span> -v<span class="s1">一樣簡化了使用</span> --mount <span class="s1">時所需的設定。</span></span>

```p1
使用 --tmpfs
$ docker run -d --name my-http --tmpfs /usr/local/apache2/htdocs -p 8080:80 httpd
使用 --mount
$ docker run -d --name my-http --mount type=tmpfs,destination=/usr/local/apache2/htdocs -p 8080:80 httpd
```

---

[![image-1642495777057.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/ucGrtB4qipR1RYnh-image-1642495777057.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/ucGrtB4qipR1RYnh-image-1642495777057.png)

官方参考链接 [https://docs.docker.com/storage/volumes/#share-data-among-machines](https://docs.docker.com/storage/volumes/#share-data-among-machines)

---

### 常用volume mapping (log)

```shell
# nginx
docker run -p 80:80 -itd -v /tmp/log/nginx/docker-nginx-log:/var/log/nginx nginx

```

### **使用綁定的不同時機比較**

既然 Docker 提供了這麼多的方式讓我們儲存資料，那麼我們應該在甚麼情況下使用哪一種方式來儲存呢？

#### **- 使用 Volume 的時機**

- 想要在多個 Container 中共用資料的時候
- 在無法確保存放資料路徑或結構的時候
- 當 Docker 不在本機端而是在雲端或遠端的時候
- 當有需要資料的備份、還原、轉移的時候
- 當資料有大量 I/O 的情況，Docker 建議你可以把資料放在 Docker VM 內，會有更好的性能表現
- 當你的應用程式需要完整且原生的 File System 的時候

#### **- 使用 Bind Mount 的時機**

- 想要將 Config 設定檔同時分享給 Container 與本機端的時候
- 想要同時分享程式碼或其他來源文件給 Container 與本機端的時候
- 當非常確定所綁定的路徑底下，其資料夾與結構等等都非常確定且保持一致不會改變的時候

#### **- 使用 Tmpfs Mount 的時機**

- 不想讓資料被永久儲存的時候
- 需要每次重啟都有乾淨的環境時
- 當想要讀寫性能非常好時，因為它掛載的空間是在記憶體上

[Docker筆記 - 讓資料遠離Container，使用 Volume、Bind Mount 與 Tmpfs Mount](https://medium.com/alberthg-docker-notes/docker%E7%AD%86%E8%A8%98-%E8%AE%93%E8%B3%87%E6%96%99%E9%81%A0%E9%9B%A2container-%E4%BD%BF%E7%94%A8-volume-bind-mount-%E8%88%87-tmpfs-mount-6908da341d11 "Docker筆記 - 讓資料遠離Container，使用 Volume、Bind Mount 與 Tmpfs Mount")

# Docker Compose

### 安裝

[Install Docker Compose | Docker Documentation](https://docs.docker.com/compose/install/)

```shell
# linux
# 到這裡找版號 https://github.com/docker/compose/releases
# sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose
$ sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
docker-compose version 1.29.2, build 5becea4c

# 找不到命令的可以建立軟連結
$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
```

熟悉python的朋友，可以使用pip去安装docker-Compose

```
$ pip install docker-compose
```

---

### YML 語法結構

[compose-spec/spec.md at master · compose-spec/compose-spec · GitHub](https://github.com/compose-spec/compose-spec/blob/master/spec.md#volumes-top-level-element)

```YAML
version: "3.8"

services: # 容器
  servicename: # 服務名字，這個名字也是內部 bridge網絡可以使用的 DNS name
  	container_name: #自定義container 名稱，不使用會用 servicename
    # build: ./buildfolder
    build: # 加此參數會使用docker file 建立
    # 如果要指定 dockerfile 使用 context + dockerfile
    #build:
    #  context: ./buildfolder
    #  dockerfile: Dockerfile.dev
    image: # 鏡像的名字(如果使用build，此選項會變成image名稱，如果沒有build，會從網路拉取該名稱image)
    command: # 可選，如果設置，則會覆蓋默認鏡像裡的 CMD命令， ex: /bin/sh -c “while true;do sleep 3600 ;done”
    environment: # 可選，相當於 docker run裡的 --env
    volumes: # 可選，相當於docker run裡的 -v
    networks: # 可選，相當於 docker run裡的 --network
    ports: # 可選，相當於 docker run裡的 -p
    
  servicename2: #第二個服務

volumes: # 可選，相當於 docker volume create

networks: # 可選，相當於 docker network create
```

範例

```YAML
version: "3.8"

services:
  flask-demo:
    image: flask-demo:latest
    environment:
      - REDIS_HOST=redis-server
      - TZ=Asia/Taipei #設定時區
    networks:
      - demo-network
    ports:
      - 8080:5000
    volumes:
      - ./config/logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro,Z 
      - ./config/logstash/pipeline:/usr/share/logstash/pipeline:ro,Z #ro: read only, Z: 在SElinux 下唯讀(啟用SEliunx才有用)

  redis-server:
    image: redis:latest
    networks:
     - demo-network

networks:
  demo-network:
```

##### docker-compose 與 docker 版本對應，語法說明

##### [https://docs.docker.com/compose/compose-file/](https://docs.docker.com/compose/compose-file/)

##### docker run 轉換 docker-compose 語法工具

#### [https://www.composerize.com/](https://www.composerize.com/)

### 常用指令

```shell
# 前景執行
docker-compose up
# 背景執行
docker-compose up -d
# 使用自定義前贅字(預設是用資料夾名稱)
docker-compose -p my_project up -d

# 停止docker-compose
docker-compose stop

# 移除docker-compose
docker-compose down
# 移除docker-compose 同時移除volumn
docker-comopose down -v

# 列出container
docker-compose ps 

# 列出log
docker-compose log
docker-compose log -f

# 在webapp 內執行sh
docker-compose exec webapp sh

# 使用top監控
docker-compose top

# 抓取(build)image
docker-compose pull

```

### 更新服務

當程式有異動，想要重新build image

```shell
# 重新build image
docker-compose build
# 啟動時重新build
docker-compose up --build
# 如果有服務被移除，使用 --remove-orphans 移除相關資源
docker-composer up --remove-orphans
# 如果有變更掛載，需要重啟服務
docker-composer restart
```

### 網路配置

```INI
networks:
  mynetwork1:
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16
   mynetwork2:
     ipam:
      driver: default
      config:
        - subnet: 172.29.0.0/16
```

### 清除環境

```shell
docker-compose stop
docker-compose rm 
docker system prund -f
```

[![image-1642476741214.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/im4FodphkDPbjQJl-image-1642476741214.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/im4FodphkDPbjQJl-image-1642476741214.png)

docker-compose volume 寫法

[![image-1642476831997.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/0giARnkNtAdZy4q4-image-1642476831997.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/0giARnkNtAdZy4q4-image-1642476831997.png)

[![image-1642476893794.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/X7edUouET00rOpGG-image-1642476893794.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/X7edUouET00rOpGG-image-1642476893794.png)

docker compose yml 範例

```YAML
version: "3"
services:
  webapp:
    #指定image
    image: httpd:alpine
    ports:
        - "80:80"
    volumes:
        - "/data"
```

```YAML
version: "3"
services:
  webapp:
    #指定image
    build:
	context: .
        dockerfile: Dockerfile-alternate
	args:
		buildno:  1
```

---

###  相關連結

- [Docker 教學課程-第8部分：使用 Docker Compose | Microsoft Docs](https://docs.microsoft.com/zh-tw/visualstudio/docker/tutorials/use-docker-compose)
- [Compose file version 3 reference | Docker Documentation](https://docs.docker.com/compose/compose-file/compose-file-v3/)
- [Overview of docker-compose CLI | Docker Documentation](https://docs.docker.com/compose/reference/)
- [官網文件 https://docs.docker.com/compose/](https://docs.docker.com/compose/)

# Docker container 常用軟體安裝

更新 apt-get

```shell
#更新apt-update
apt-get update
```

#### vim

```shell
sudo apt-get install -y vim
```

#### ip

```shell
sudo apt-get install -y iproute2
```

#### ping

```shell
sudo apt-get install -y iputils-ping
```

#### ifconfig, netestat

```shell
sudo apt-get install -y net-tools
```

##### nc (netcat)

```shell
sudo apt-get install -y netcat
```

#### maven

```shell
FROM jenkins/jenkins:lts
RUN apt-get update && apt-get install -y maven
```

---

### apt-get 使用proxy

```shell

#apt_proxy.conf 設定 proxy
Acquire::http::proxy "http://127.0.0.1:8000/";
Acquire::ftp::proxy "ftp://127.0.0.1:8000/";
Acquire::https::proxy "https://127.0.0.1:8000/";

#可以用“-c”選項來指定使用配置檔案
sudo apt-get -c ~/apt_proxy.conf update
#apt-get也有一個“-o”選項，直接跟apt-get的設定變數，就不用指定配置檔案了，比如
sudo apt-get -o Acquire::http::proxy="http://127.0.0.1:8000/" update

```

# Docker File

### Docker File 官方說明

[Dockerfile reference | Docker Documentation](https://docs.docker.com/engine/reference/builder/)

官方各類型docker file 專案連結(可找到專案git repo)

[official-images/library at master · docker-library/official-images · GitHub](https://github.com/docker-library/official-images/tree/master/library)

[![image-1645294864450.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-02/scaled-1680-/xIH3UQ3k7ZQ3bYys-image-1645294864450.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-02/xIH3UQ3k7ZQ3bYys-image-1645294864450.png)

---

### Build Dockerfile

```shell
# docker image build -t {name}:{tag} {dokerfile 目錄}
docker image build -t hello_py:v1 .
```

### Docker File 結構

```INI
# 基礎鏡像檔
FROM ubuntu:21.04
# 環境變數
ENV VERSION=2.0.1
# 執行命令(可在執行容器的時候使用其他命覆蓋)
RUN apt-get update && \
    apt-get install -y wget && \
    wget https://github.com/ipinfo/cli/releases/download/ipinfo-${VERSION}/ipinfo_${VERSION}_linux_amd64.tar.gz && \
    tar zxf ipinfo_${VERSION}_linux_amd64.tar.gz && \
    mv ipinfo_${VERSION}_linux_amd64 /usr/bin/ipinfo && \
    rm -rf ipinfo_${VERSION}_linux_amd64.tar.gz
# 移動到當前目錄
WORKDIR /app
# 複製檔案
COPY hello.py /app/hello.py
# 複製檔案(如果是壓縮檔會自行解壓縮，一般來說還是用COPY)
ADD hello.tar.gz /app/
# 執行命令(無法覆蓋)
ENTRYPOINT ["echo", "hello docker"]
```

# Docker Image 相關

### 鏡像的獲取

- pull from `<span class="pre">registry</span>` (online) 從registry拉取
    
    
    - public（公有）
    - private（私有）
- build from `<span class="pre">Dockerfile</span>` (online) 從Dockerfile構建
- load from `<span class="pre">file</span>` (offline) 文件導入 （離線）

官方image:  
[https://hub.docker.com/search?type=image&amp;image\_filter=official](https://hub.docker.com/search?type=image&image_filter=official)

---

常用 public image server

- [Docker Hub Container Image Library | App Containerization](https://hub.docker.com/)
- [Quay Container Registry · Quay](https://quay.io/)

##### \*建立映像檔

```shell
# 於當前目錄，按Dockerfile.test中的指令，建立test:v1 ({name:tag})的映像檔
docker build . -f Dockrfile.test -t test:v1
```

##### \*拉取與推送映像檔

```shell
# 使用docker hub 下載image ({name:tag})
docker pull node:alpine
# 使用quay.io 下載image 
docker pull quay.io/bitnami/tomcat
# node:alpine 重新命名標籤 username/nodea:alpine
docker tag node:alpine username/nodea:alpine
# 推送至私人倉庫
docker push username/node:alpine
```

---

##### 使用私有registry

```shell
# 修改鏡像registry
sudo vim /etc/docker/daemon.json
#########################################################
#  可與許http鏡像　"insecure-registries" : ["10.60.78.79"],
#  鏡像站 "registry-mirrors": ["http://hub-mirror.c.163.com"]

{
  "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}
#########################################################
# 使文件生效
sudo systemctl daemon-reload
# 重啟docker
sudo service docker restart
```

##### 使用proxy 抓取鏡像檔

\*ubuntu

```shell
# 編輯設定檔
vim /etc/default/docker

##檔案內容
export http_proxy="http://192.168.33.10:3128/"
export https_proxy="http://192.168.33.10:3128/"
##

# proxy 如果有帳密驗證
export http_proxy="https://username:password@192.168.33.10:3128/"

# 重啟docker 
systemctl restart docker
```

\*centos

```shell
vim /etc/systemd/system/docker.service.d/http-proxy.conf 

###################################################################################
[Service]
Environment="HTTP_PROXY=http://192.168.1.1:3128/"
Environment="HTTPS_PROXY=http://192.168.1.1:3128/"
#如果要排除不走
Environment="NO_PROXY=localhost,127.0.0.0/8,docker-registry.somecorporation.com"

###################################################################################

#重讀設定
systemctl daemon-reload

#重啟docker
systemctl restart docker

```

---

##### 查看image

```shell
# 取得id
[root@localhost ~]# docker image ls

REPOSITORY   TAG            IMAGE ID       CREATED        SIZE
tomcat       latest         9f35737a8466   30 hours ago   680MB
busybox      latest         beae173ccac6   3 weeks ago    1.24MB
openjdk      8-jre-alpine   f7a292bbb70c   2 years ago    84.9MB
```

```shell
[root@localhost ~]# docker image inspect f7a292bbb70c
[
    {
        "Id": "sha256:f7a292bbb70c4ce57f7704cc03eb09e299de9da19013b084f138154421918cb4",
        "RepoTags": [
            "openjdk:8-jre-alpine"
        ],
        "RepoDigests": [
            "openjdk@sha256:f362b165b870ef129cbe730
.......

# 重要訊息
 "Id": "sha256:f7a292bbb70c4ce57f7704cc03eb09e299de9da19013b084f138154421918cb4",
        "RepoTags": [
            "openjdk:8-jre-alpine"
        ],


"Architecture": "amd64",
 "Os": "linux",

```

##### 刪除 image

```shell
# 查詢要刪除imge id
[root@localhost ~]# docker image ls
REPOSITORY   TAG            IMAGE ID       CREATED        SIZE
tomcat       latest         9f35737a8466   30 hours ago   680MB
busybox      latest         beae173ccac6   3 weeks ago    1.24MB
openjdk      8-jre-alpine   f7a292bbb70c   2 years ago    84.9MB
# 刪除 image
[root@localhost ~]# docker image rm beae173ccac6
Untagged: busybox:latest
Untagged: busybox@sha256:5acba83a746c7608ed544dc1533b87c737a0b0fb730301639a0179f9344b1678
Deleted: sha256:beae173ccac6ad749f76713cf4440fe3d21d1043fe616dfbe30775815d1d0f6a
Deleted: sha256:01fd6df81c8ec7dd24bbbd72342671f41813f992999a3471b9d9cbc44ad88374

# 刪除名字跟nginx 有關的imge (-f 強制)
[root@localhost ~]# docker images | grep nginx | awk '{print $3}' | xargs docker rmi
[root@localhost ~]# docker images | grep nginx | awk '{print $3}' | xargs docker rmi -f

# 刪除沒有名字的image (-f 強制)
[root@localhost ~]# docker images | grep "<none>" | awk '{print $3}' | xargs docker rmi
[root@localhost ~]# docker images | grep "<none>" | awk '{print $3}' | xargs docker rmi -f
```

##### image 匯入匯出

```shell
# 查看 image
[root@localhost ~]# docker image ls
REPOSITORY   TAG            IMAGE ID       CREATED        SIZE
tomcat       latest         9f35737a8466   30 hours ago   680MB
busybox      latest         beae173ccac6   3 weeks ago    1.24MB
openjdk      8-jre-alpine   f7a292bbb70c   2 years ago    84.9MB

# 匯出 image
# docker image save {name}:{tag} -o {匯出檔名}
[root@localhost ~]# docker image save openjdk:8-jre-alpine -o openjdk:8-jre-alpine.image
# 查看是否匯出
[root@localhost ~]# ls openjdk\:8-jre-alpine.image 
openjdk:8-jre-alpine.image

```

```shell
# image 匯入
# docker image load -i {image file}
[root@localhost ~]# docker image load -i ./openjdk\:8-jre-alpine.image 
f1b5933fe4b5: Loading layer [==================================================>]  5.796MB/5.796MB
9b9b7f3d56a0: Loading layer [==================================================>]  3.584kB/3.584kB
edd61588d126: Loading layer [==================================================>]  80.28MB/80.28MB
Loaded image: openjdk:8-jre-alpine

```

### push image to docker hub

```shell
# 建立上傳image
#docker image tag nginx {docker hub id}/{name}:{tag}
docker image tag nginx treemanou/my_nginx:v2
#docker image push {docker hub id}/{name}:{tag}
docker image push treemanou/my_nginx:v2
```

### commit 建立 image

```shell
# 找一個conatiner
$ docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS                      PORTS     NAMES
e09bb406dcef   busybox   "sh"      53 seconds ago   Exited (0) 18 seconds ago             hardcore_bartik
# 利用此container建立 image
# docker commit {container id} {name}:{tag}
$ docker commit e09 treemanou/my_busybox:v3
sha256:42bc77669110af56336ec10afdbd7f92fa371f02ecccbda1e0bbb1bbc00f3cf6
```

### Docker File

---

##### Docker File 官方說明

[Dockerfile reference | Docker Documentation](https://docs.docker.com/engine/reference/builder/)

---

\*ENV 環境變數

```
ENV ANT_HOME /opt/ant
```

\*ARG傳入參數

```
FROM　alpine
ARG NODE_ARG
ENV NODE_ENV="${NODE_ARG:-development}"
RUN echo "ARG=${NODE_ARG}, ENV=${NODE_ENV}"
CMD ehco "ARG=${NODE_ARG}, ENV=${NODE_ENV}"
```

```shell
# 傳入NODE_ARG
# DOCKER_BUILDKIT=0
DOCKER_BUILDKIT=0 docker build --build-arg NODE_ARG=staging　.
```

\*工作目錄 WORKDIR

```shell
# /  下
RUN echo "say hi" > hi.txt
WORKDIR /app
#  /app 下
RUN echo "hello" > world.txt
```

\*指定用戶USER (不指定舊識)

```shell
# 新增 group與user
RUN groupadd -r redis && useradd -r -g redis redis
# 指定當前user為redis
USER redis

# 以redis的身份執行reidis-server
RUN ["redis-server"]
```

\*Health Check

```shell
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
```

---

```shell
FROM registry.test.com.tw/test/centos:openjdk8_tomcat8.5

ENV CATALINA_HOME /opt/tomcat
ENV SERVICE_HOME /usr/AP/fubon
ENV ANT_HOME /opt/ant
ENV JAVA_HOME /usr/lib/jvm/java-1.8.0-openjdk
ENV PATH="${PATH}:${ANT_HOME}/bin:${CATALINA_HOME}/bin"
ENV AWS_HOME="/root/aws"

RUN wget https://archive.apache.org/dist/ant/binaries/apache-ant-1.10.7-bin.tar.gz \
  && tar -zxvf apache-ant-1.10.7-bin.tar.gz \
  && rm apache-ant-1.10.7-bin.tar.gz \
  && mv apache-ant* ${ANT_HOME} \
  && yum install -y python3 \
  && pip3 install awscli --upgrade --user \
  && ln -s  /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.252.b09-2.el7_8.x86_64/ /usr/lib/jvm/java-1.8.0-openjdk.x86_64 \
  && yum install -y httpd php php-gd 
  
COPY server.xml ${CATALINA_HOME}/conf/

COPY my_entrypoint.sh /my_entrypoint.sh
RUN chmod -v +x /my_entrypoint.sh

COPY --chown=user:group file* /app/

COPY server_builder.sh ${SERVICE_HOME}/

#Set Alias
RUN echo "alias cdcm='cd /usr/AP/test/cm'" >> ~/.bashrc \
 && echo "alias restartTomcat='cd /opt/tomcat/bin; ./shutdown.sh; /bin/sleep 3; ps -ef | grep '\''org.apache.catalina.startup.Bootstrap start'\'' | grep -v grep | awk '\''{print $2}'\'' | xargs kill; ./startup.sh'" >> ~/.bashrc \
 && echo "alias cmant='cd /usr/AP/test/cm/src; ant; restartTomcat'"  >> ~/.bashrc \
 
EXPOSE 8080

CMD ["-D","FOREGROUND"]

# 預設目錄
WORKDIR /usr/AP/test/ 

#  一定會執行
ENTRYPOINT ["/my_entrypoint.sh"]

```

\* 複寫CMD

```
docker run --rm apache:v1 -v
```

---

多階段建置

```shell
# 建置環境
FROM alpine as build
RUN echo "hello" > mytest

#  執行環境
FROM alpine
COPY --from=build /mytest .
RUN cat /mytest 
```

**Distroless Dock image** =&gt; 精簡image

---

### 常用image

#### busybox

- 提供輕量簡單的shell 的 linux 容器

##### containous/whoami

- 提供返回ip hostname 服務

```shell
vagrant@swarm-manager:~$ curl 192.168.200.10:8080
Hostname: fdf7c1354507
IP: 127.0.0.1
IP: 10.0.0.7
IP: 172.18.0.3
IP: 10.0.1.14
RemoteAddr: 10.0.0.2:36828
GET / HTTP/1.1
Host: 192.168.200.10:8080
User-Agent: curl/7.68.0
Accept: */*
```

# Docker Image Server DockerRegistry

[Day7：建立 private 的 Docker Registry - iT 邦幫忙::一起幫忙解決難題，拯救 IT 人的一天 (ithome.com.tw)](https://ithelp.ithome.com.tw/articles/10191213)

```shell
$ docker run -d -p 5000:5000 -v /home/user1/storage:/var/lib/registry --name registry registry:2

#
# -d：執行的 docker container 是 run 在背景的狀態，所以需要使用 docker logs 的指令才可以看到 log 狀態
# -p：主機的 5000 port mapping 到 container 的 5000 port
# -v：因為 push 到 docker registry 的資料是放在 container 裡面的，如果把 docker container 刪除掉 docker registry 的 Image 資料就會不見，因此需要使用 –v 參數將主機的檔案路徑 mapping 到 container 裡面的檔案路徑，這樣 docker container 被刪除 docker registry 的 Image 資料還會存在
# --name：設定 docker container 的名稱

```

##### clinet / server 都要加 daemon.json 

```shell
# vim /etc/docker daemon.json
# 允許192.168.1.1:5000 (port 一定要寫) 可不走https
{
"insecure-registries":["192.168.1.1:5000"]
}

```

### 上傳 image

```shell
# 假設本機ip 192.168.1.1 (registry server)
# 下載image
docker pull busybox

# 複製image 成 mybusybox
docker push tag busybox 192.168.1.1:5000/mybusybox
# 上傳image 
docker pull 192.168.1.1:5000/mybusybox
```

### 下載 image

```shell
# 假設本機ip 192.168.1.2 (docker client)
docker pull docker pull 192.168.1.1:5000/mybusybox

```

# Docker Image Server nexus

[sonatype/nexus3 - Docker Image | Docker Hub](https://hub.docker.com/r/sonatype/nexus3/)

1. *Use a docker volume*. Since docker volumes are persistent, a volume can be created specifically for this purpose. This is the recommended approach.
    
    ```
    $ docker volume create --name nexus-data
    $ docker run -d -p 8081:8081 --name nexus -v nexus-data:/nexus-data sonatype/nexus3
    ```
2. *Mount a host directory as the volume*. This is not portable, as it relies on the directory existing with correct permissions on the host. However it can be useful in certain situations where this volume needs to be assigned to certain specific underlying storage.
    
    ```
    $ mkdir /some/dir/nexus-data && chown -R 200 /some/dir/nexus-data
    $ docker run -d -p 8081:8081 --name nexus -v /some/dir/nexus-data:/nexus-data sonatype/nexus3
    ```

# Docker Network

[![image-1642500508897.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/3BWF5JGV4iFGcRUR-image-1642500508897.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/3BWF5JGV4iFGcRUR-image-1642500508897.png)

[![image-1642576871696.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/VnZuBqb1rvcf8IZh-image-1642576871696.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/VnZuBqb1rvcf8IZh-image-1642576871696.png)

建立兩容器

```shell
$ docker container run -d --rm --name box1 busybox /bin/sh -c "while true; do sleep 3600; done"
$ docker container run -d --rm --name box2 busybox /bin/sh -c "while true; do sleep 3600; done"
$ docker container ls
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS     NAMES
4f3303c84e53   busybox   "/bin/sh -c 'while t…"   49 minutes ago   Up 49 minutes             box2
03494b034694   busybox   "/bin/sh -c 'while t…"   49 minutes ago   Up 49 minutes             box1
```

### 容器間的通信-&gt;使用bridge

```shell
$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
1847e179a316   bridge    bridge    local
a647a4ad0b4f   host      host      local
fbd81b56c009   none      null      local
$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "1847e179a316ee5219c951c2c21cf2c787d431d1ffb3ef621b8f0d1edd197b24",
        "Created": "2021-07-01T15:28:09.265408946Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "03494b034694982fa085cc4052b6c7b8b9c046f9d5f85f30e3a9e716fad20741": {
                "Name": "box1",
                "EndpointID": "072160448becebb7c9c333dce9bbdf7601a92b1d3e7a5820b8b35976cf4fd6ff",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "4f3303c84e5391ea37db664fd08683b01decdadae636aaa1bfd7bb9669cbd8de": {
                "Name": "box2",
                "EndpointID": "4cf0f635d4273066acd3075ec775e6fa405034f94b88c1bcacdaae847612f2c5",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]
```

"IPAM": {  
 "Driver": "default",  
 "Options": null,  
 "Config": \[  
 {  
 "Subnet": "<span style="color: #ff0000;">172.17.0.0/16</span>",  
 "Gateway": "<span style="color: #ff0000;">172.17.0.1</span>"  
 }  
 \]  
},

"com.docker.network.bridge.name": "docker0",

```shell
# brctl 顯示bridge tool
$ brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.0242759468cf       no              veth8c9bb82
                                                        vethd8f9afb
```

### 容器對外通訊-&gt;iptables nat

```
$ ip route
default via 10.0.2.2 dev eth0 proto dhcp metric 100
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15 metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.200.0/24 dev eth1 proto kernel scope link src 192.168.200.10 metric 101
```

```
$ sudo iptables --list -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  anywhere            !loopback/8           ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16        anywhere

Chain DOCKER (2 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere
```

[![image-1642576581794.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/Bzvyu502k6v1ZIkl-image-1642576581794.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/Bzvyu502k6v1ZIkl-image-1642576581794.png)

docker network create --help

docker network create -d<span style="color: #ff0000;"> {driver}</span> --gateway <span style="color: #ff0000;">{gateway}</span> --subnet<span style="color: #ff0000;"> {subnet} {name}</span>  
docker network create -d bridge --gateway 127.200.0.1 -subnet 172.200.0.0/16 demo

```shell
[tomcat@docker-qc html-doc]$ docker network create -d bridge mybridge
65c5ba6cbea2fa677e8dd0623a510f3461e24ccac196b7374fc5e8d03803ec9e

[tomcat@docker-qc html-doc]$  docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
780162e5fe57        bridge              bridge              local
3c5b59c8a708        host                host                local
65c5ba6cbea2        mybridge            bridge              local

[tomcat@docker-qc html-doc]$ docker network inspect mybridge
[
    {
        "Name": "mybridge",
        "Id": "65c5ba6cbea2fa677e8dd0623a510f3461e24ccac196b7374fc5e8d03803ec9e",
        "Created": "2022-01-18T18:44:39.95740673+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

```

```shell
# 建立連接mybridge的container (--network 不設定會用預設的)
$ docker container run -d --rm --name box3 --network mybridge busybox /bin/sh -c "while true; do sleep 3600; done"
# 既有container 連接mybridge
$ docker network connect mybridge box1
# container 中斷 mybridge
$ docker network disconnect mybridge box1

```

---

### **Network type**

- bridge
- host
- none

**bridge**: 新增一網段，橋接本地網路  
**host**: 直接使用本地網路(無法看到port -&gt; 等於直接開在本機port 80，好處不用nat，壞處只能開一個)

```shell
#docker dontainer run -d --name {container name} --network {network type} {image}
docker dontainer run -d --name web --network host nginx
```

[![image-1642651291388.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/YfM2Dcw8nqoK2c7T-image-1642651291388.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/YfM2Dcw8nqoK2c7T-image-1642651291388.png)

只能開一個，多開會報錯

[![image-1642651575691.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/BW5D4QWEKWICxDLA-image-1642651575691.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/BW5D4QWEKWICxDLA-image-1642651575691.png)

**none**: 只有 lookback 127.0.0.1 沒有其他網路

---

### 網路命名空間

- ##### bridge tool : <span style="color: #ff0000;">brctl</span> 安裝

```shell
#Ubuntu
apt-get install bridge-utils 
#Centos
sudo yum install bridge-utils
```

[![image-1642659997529.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/jrMYPAmozUFUHgTx-image-1642659997529.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/jrMYPAmozUFUHgTx-image-1642659997529.png)

創建bridge

```shell
[vagrant@docker-host1 ~]$ sudo brctl addbr mydocker0
[vagrant@docker-host1 ~]$ brctl show
bridge name     bridge id               STP enabled     interfaces
mydocker0               8000.000000000000       no
[vagrant@docker-host1 ~]$

```

add-ns-to-br.sh

```shell
#!/bin/bash

bridge=$1
namespace=$2
addr=$3

vethA=veth-$namespace
vethB=eth00

sudo ip netns add $namespace
sudo ip link add $vethA type veth peer name $vethB

sudo ip link set $vethB netns $namespace
sudo ip netns exec $namespace ip addr add $addr dev $vethB
sudo ip netns exec $namespace ip link set $vethB up

sudo ip link set $vethA up

sudo brctl addif $bridge $vethA
```

```shell
#run shell
[vagrant@docker-host1 ~]$ sh add-ns-to-br.sh mydocker0 ns1 172.16.1.1/16
[vagrant@docker-host1 ~]$ sh add-ns-to-br.sh mydocker0 ns2 172.16.1.2/16

#up bridge
[vagrant@docker-host1 ~]$ sudo ip link set dev mydocker0 up
```

驗證

```shell
[vagrant@docker-host1 ~]$ sudo ip netns exec ns1 bash
[root@docker-host1 vagrant]# ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
5: eth00@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether f2:59:19:34:73:70 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.16.1.1/16 scope global eth00
    valid_lft forever preferred_lft forever
    inet6 fe80::f059:19ff:fe34:7370/64 scope link
    valid_lft forever preferred_lft forever
[root@docker-host1 vagrant]# ping 172.16.1.2
PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data.
64 bytes from 172.16.1.2: icmp_seq=1 ttl=64 time=0.029 ms
64 bytes from 172.16.1.2: icmp_seq=2 ttl=64 time=0.080 ms
^C
--- 172.16.1.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.029/0.054/0.080/0.026 ms
[root@docker-host1 vagrant]#
```

[![image-1642660373795.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/J47bjgngTUMyQynn-image-1642660373795.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/J47bjgngTUMyQynn-image-1642660373795.png)

[![image-1642660418946.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/96PF3Lseg7J1VaxD-image-1642660418946.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/96PF3Lseg7J1VaxD-image-1642660418946.png)

使用iptables 實現nat  
[NAT with Linux and iptables - Tutorial (Introduction) (karlrupp.net)](https://www.karlrupp.net/en/computer/nat_tutorial)

---

### 使用自定義網路練習

使用自定義網路，預設自帶dns，容器間可相互使用name ping 通

準備python 檔案 <span style="color: #ff0000;">**app.py**</span>

```Python
from flask import Flask
from redis import Redis
import os
import socket

app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)


@app.route('/')
def hello():
    redis.incr('hits')
    return f"Hello Container World! I have been seen {redis.get('hits').decode('utf-8')} times and my hostname is {socket.gethostname()}.\n"
```

準備一個 Dockerfile

```shell
FROM python:3.9.5-slim

RUN pip install flask redis && \
    groupadd -r flask && useradd -r -g flask flask && \
    mkdir /src && \
    chown -R flask:flask /src

USER flask

COPY app.py /src/app.py

WORKDIR /src

ENV FLASK_APP=app.py REDIS_HOST=redis

EXPOSE 5000

CMD ["flask", "run", "-h", "0.0.0.0"]
```

build image 並下載一個redis image

```shell
$ docker image pull redis
$ docker image build -t flask-demo .
$ docker image ls
REPOSITORY   TAG          IMAGE ID       CREATED              SIZE
flask-demo   latest       4778411a24c5   About a minute ago   126MB
python       3.9.5-slim   c71955050276   8 days ago           115MB
redis        latest       08502081bff6   2 weeks ago          105MB
```

建立一個bridge

```shell
$ docker network create -d bridge demo-network
8005f4348c44ffe3cdcbbda165beea2b0cb520179d3745b24e8f9e05a3e6456d
$ docker network ls
NETWORK ID     NAME           DRIVER    SCOPE
2a464c0b8ec7   bridge         bridge    local
8005f4348c44   demo-network   bridge    local
80b63f711a37   host           host      local
fae746a75be1   none           null      local

```

建立redis container 並連至 demo-network

```shell
$ docker container run -d --name redis-server --network demo-network redis
002800c265020310231d689e6fd35bc084a0fa015e8b0a3174aa2c5e29824c0e
$ docker container ls
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS      NAMES
002800c26502   redis     "docker-entrypoint.s…"   4 seconds ago   Up 3 seconds   6379/tcp   redis-server
```

建立 flask container

```shell
$ docker container run -d --network demo-network --name flask-demo --env REDIS_HOST=redis-server -p 5000:5000 flask-demo
```

打開瀏覽器 [http://127.0.0.1:5000](http://127.0.0.1:5000/)

可以看到以下內容，每次刷新次次就會+1  
Hello Container World! I have been seen <span style="color: #ff0000;">36</span> times and my hostname is 925ecb8d111a.

##### 整理後腳本

```shell
# prepare image
docker image pull redis
docker image build -t flask-demo .

# create network
docker network create -d bridge demo-network

# create container
docker container run -d --name redis-server --network demo-network redis
docker container run -d --network demo-network --name flask-demo --env REDIS_HOST=redis-server -p 5000:5000 flask-demo
```

# Docker Swarm

### 相關指令

```shell
# 查詢swarm狀態
docker info
# 未開啟
Swarm: inactive

# 初始化swarm
docker swarm init
##########################
Swarm initialized: current node (4szs3vf8x9pb79me4cxfsb9m2) is now a manager.

To add a worker to this swarm, run the following command:
	#加入叢集使用以下命令
    docker swarm join --token SWMTKN-1-3i2aq39bqqudp6p6y3o4ubw4ca1036z85z3huf9lyfijdfns88-33y43c8gw2ch85wbl2jdb4w0e 192.168.65.6:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
##########################

#查詢節點
docker node ls
ID                            HOSTNAME         STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
4szs3vf8x9pb79me4cxfsb9m2 *   docker-desktop   Ready     Active         Leader           20.10.6

# 開啟後查詢 docker info
Swarm: active
  NodeID: 4szs3vf8x9pb79me4cxfsb9m2
  Is Manager: true
  ClusterID: 83phccx66ca4rji17wk8p5kce
  Managers: 1
  Nodes: 1
  Default Address Pool: 10.0.0.0/8
  SubnetSize: 24
  Data Path Port: 4789
  Orchestration:
  
 # 離開docker swarm 叢集
 docker swrm leave -f
```

### docker swarm init 背後發生了什麼

主要是PKI和安全相關的自動化

- 創建swarm集群的根證書
- manager節點的證書
- 其它節點加入集群需要的tokens

創建Raft資料庫用於存儲證書，配置，密碼等數據

---

### 建立一個service(container)

```shell
# docker service create {image}:{tag}
docker service create --name web nginx:latest
```

```shell
# 取得servie id(不是container id)
docker service ls

ID             NAME           MODE         REPLICAS   IMAGE          PORTS
l5wvuxzw9l96   jolly_euclid   replicated   1/1        nginx:latest

# 查看container
docker service ps l5wvuxzw9l96
ID             NAME             IMAGE          NODE             DESIRED STATE   CURRENT STATE           ERROR     PORTS
vp8dkrsqslxw   jolly_euclid.1   nginx:latest   docker-desktop   Running         Running 3 minutes ago

# 建立3個副本(update)
docker service update l5wvuxzw9l96 --replicas 3
l5wvuxzw9l96
overall progress: 3 out of 3 tasks
1/3: running   [==================================================>]
2/3: running   [==================================================>]
3/3: running   [==================================================>]

# 建立4個副本(scale)
docker service scale l5wvuxzw9l96=4
web scaled to 4
overall progress: 4 out of 4 tasks 
1/4: running   [==================================================>] 
2/4: running   [==================================================>] 
3/4: running   [==================================================>] 
4/4: running   [==================================================>] 

#docker sercie ps
docker service ps l5wvuxzw9l96
ID             NAME             IMAGE          NODE             DESIRED STATE   CURRENT STATE            ERROR     PORTS
vp8dkrsqslxw   jolly_euclid.1   nginx:latest   docker-desktop   Running         Running 13 minutes ago
qavp0npxko3l   jolly_euclid.2   nginx:latest   docker-desktop   Running         Running 7 minutes ago
kqs6uvbkxmjh   jolly_euclid.3   nginx:latest   docker-desktop   Running         Running 7 minutes ago
```

### service 刪除

```shell
 docker service rm l5wvuxzw9l96
```

---

### docker swarm的網路：

- 第一是外部如何訪問部署運行在swarm集群內的服務，可以稱之為 `<span class="pre">入方向</span>` 流量，在swarm裡我們通過 `<span class="pre">ingress</span>` 來解決
- 第二是部署在swarm集群裡的服務，如何對外進行訪問，這部分又分為兩塊:
    
    
    - 第一，`<span class="pre">東西向流量</span>` ，也就是不同swarm節點上的容器之間如何通信，swarm通過 `<span class="pre">overlay</span>` 網絡來解決；
    - 第二，`<span class="pre">南北向流量</span>` ，也就是swarm集群裡的容器如何對外訪問，比如互聯網，這個是 `<span class="pre">Linux</span> <span class="pre">bridge</span> <span class="pre">+</span> <span class="pre">iptables</span> <span class="pre">NAT</span>` 來解決的

[![image-1644943091590.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-02/scaled-1680-/nxC5u1ibHLND7LXz-image-1644943091590.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-02/nxC5u1ibHLND7LXz-image-1644943091590.png)

# Docker如何固定IP設定的方法

[Docker如何固定IP設定的方法 - IT閱讀 (itread01.com)](https://www.itread01.com/article/1499743916.html)

經常用Docker模擬專案在生產環境中的部署，往往需要同時開好幾臺Docker容器，而且有時安裝的軟體需要繫結Docker區域網中的其他容器，如 MongoDB 副本集部署的時候，就需要繫結其他容器的內網IP。

但是，Docker 每次重啟後，容器的IP地址會變化，查詢了資料，Docker是支援設定固定IP的。

**Docker 預設網路**

Docker安裝後，預設會建立下面三種網路型別：

<div id="bkmrk-%24-docker-network-ls-">```
<span class="pln">$ docker network ls
NETWORK ID     NAME        DRIVER       SCOPE
</span><span class="lit">9781b1f585ae</span><span class="pln">    bridge       bridge       </span><span class="kwd">local</span>
<span class="lit">1252da701e55</span><span class="pln">    host        host        </span><span class="kwd">local</span>
<span class="lit">237ea3d5cfbf</span><span class="pln">    none        </span><span class="kwd">null</span>        <span class="kwd">local</span>
```

</div>啟動 Docker的時候，用 `--network `引數，可以指定網路型別，如：

<div id="bkmrk-%7E-docker-run--itd---">```
<span class="pun">~</span><span class="pln"> docker run </span><span class="pun">-</span><span class="pln">itd </span><span class="pun">--</span><span class="pln">name test1 </span><span class="pun">--</span><span class="pln">network bridge </span><span class="pun">--</span><span class="pln">ip </span><span class="lit">172.17</span><span class="pun">.</span><span class="lit">0.10</span><span class="pln"> centos</span><span class="pun">:</span><span class="pln">latest </span><span class="pun">/</span><span class="pln">bin</span><span class="pun">/</span><span class="pln">bash</span>
```

</div>**bridge：橋接網路**

預設情況下啟動的Docker容器，都是使用 bridge，Docker安裝時建立的橋接網路，每次Docker容器重啟時，會按照順序獲取對應的IP地址，這個就導致重啟下，Docker的IP地址就變了

**none：無指定網路**

使用 `--network=none `，docker 容器就不會分配區域網的IP

**host： 主機網路**

使用 `--network=host`，此時，Docker 容器的網路會附屬在主機上，兩者是互通的。

例如，在容器中執行一個Web服務，監聽8080埠，則主機的8080埠就會自動對映到容器中。

**建立自定義網路：（設定固定IP）**

啟動Docker容器的時候，使用預設的網路是不支援指派固定IP的，如下：

<div id="bkmrk-%7E-docker-run--itd----0">```
<span class="pun">~</span><span class="pln"> docker run </span><span class="pun">-</span><span class="pln">itd </span><span class="pun">--</span><span class="pln">net bridge </span><span class="pun">--</span><span class="pln">ip </span><span class="lit">172.17</span><span class="pun">.</span><span class="lit">0.10</span><span class="pln"> centos</span><span class="pun">:</span><span class="pln">latest </span><span class="pun">/</span><span class="pln">bin</span><span class="pun">/</span><span class="pln">bash
</span><span class="lit">6eb1f228cf308d1c60db30093c126acbfd0cb21d76cb448c678bab0f1a7c0df6</span><span class="pln">
docker</span><span class="pun">:</span> <span class="typ">Error</span><span class="pln"> response </span><span class="kwd">from</span><span class="pln"> daemon</span><span class="pun">:</span> <span class="typ">User</span><span class="pln"> specified IP address </span><span class="kwd">is</span><span class="pln"> supported on user </span><span class="kwd">defined</span><span class="pln"> networks only</span><span class="pun">.</span>
```

</div>因此，需要建立自定義網路，下面是具體的步驟：

**步驟1: 建立自定義網路**

建立自定義網路，並且指定網段：172.18.0.0/16

<div id="bkmrk-%E2%9E%9C-%7E-docker-network-c">```
<span class="pun">➜</span> <span class="pun">~</span><span class="pln"> docker network create </span><span class="pun">--</span><span class="pln">subnet</span><span class="pun">=</span><span class="lit">172.18</span><span class="pun">.</span><span class="lit">0.0</span><span class="pun">/</span><span class="lit">16</span><span class="pln"> mynetwork
</span><span class="pun">➜</span> <span class="pun">~</span><span class="pln"> docker network ls
NETWORK ID     NAME        DRIVER       SCOPE
</span><span class="lit">9781b1f585ae</span><span class="pln">    bridge       bridge       </span><span class="kwd">local</span>
<span class="lit">1252da701e55</span><span class="pln">    host        host        </span><span class="kwd">local</span>
<span class="lit">4f11ae9c85de</span><span class="pln">    mynetwork      bridge       </span><span class="kwd">local</span>
<span class="lit">237ea3d5cfbf</span><span class="pln">    none        </span><span class="kwd">null</span>        <span class="kwd">local</span>
```

</div>**步驟2: 建立Docker容器**

<u></u>程式碼如下:

➜ ~ docker run -itd --name networkTest1 --net mynetwork --ip 172.18.0.2 centos:latest /bin/bash

這個時候，建立的Docker容器就會持有 172.18.0.2 這個IP.

<div id="bkmrk-%5Broot%40ec8e31938fe7-%2F">```
<span class="pun">[</span><span class="pln">root@ec8e31938fe7</span> <span class="pun">/]#</span><span class="pln"> ifconfig
eth0   </span><span class="typ">Link</span><span class="pln"> encap</span><span class="pun">:</span><span class="typ">Ethernet</span> <span class="typ">HWaddr</span> <span class="lit">02</span><span class="pun">:</span><span class="lit">42</span><span class="pun">:</span><span class="pln">AC</span><span class="pun">:</span><span class="lit">12</span><span class="pun">:</span><span class="lit">00</span><span class="pun">:</span><span class="lit">02</span><span class="pln">
     inet addr</span><span class="pun">:</span><span class="lit">172.18</span><span class="pun">.</span><span class="lit">0.2</span> <span class="typ">Bcast</span><span class="pun">:</span><span class="lit">0.0</span><span class="pun">.</span><span class="lit">0.0</span> <span class="typ">Mask</span><span class="pun">:</span><span class="lit">255.255</span><span class="pun">.</span><span class="lit">0.0</span><span class="pln">
     inet6 addr</span><span class="pun">:</span><span class="pln"> fe80</span><span class="pun">::</span><span class="lit">42</span><span class="pun">:</span><span class="pln">acff</span><span class="pun">:</span><span class="pln">fe12</span><span class="pun">:</span><span class="lit">2</span><span class="pun">/</span><span class="lit">64</span> <span class="typ">Scope</span><span class="pun">:</span><span class="typ">Link</span><span class="pln">
     UP BROADCAST RUNNING MULTICAST MTU</span><span class="pun">:</span><span class="lit">1500</span> <span class="typ">Metric</span><span class="pun">:</span><span class="lit">1</span><span class="pln">
     RX packets</span><span class="pun">:</span><span class="lit">88</span><span class="pln"> errors</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> dropped</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> overruns</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> frame</span><span class="pun">:</span><span class="lit">0</span><span class="pln">
     TX packets</span><span class="pun">:</span><span class="lit">14</span><span class="pln"> errors</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> dropped</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> overruns</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> carrier</span><span class="pun">:</span><span class="lit">0</span><span class="pln">
     collisions</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> txqueuelen</span><span class="pun">:</span><span class="lit">0</span><span class="pln">
     RX bytes</span><span class="pun">:</span><span class="lit">4056</span> <span class="pun">(</span><span class="lit">3.9</span> <span class="typ">KiB</span><span class="pun">)</span><span class="pln"> TX bytes</span><span class="pun">:</span><span class="lit">1068</span> <span class="pun">(</span><span class="lit">1.0</span> <span class="typ">KiB</span><span class="pun">)</span><span class="pln">

lo    </span><span class="typ">Link</span><span class="pln"> encap</span><span class="pun">:</span><span class="typ">Local</span> <span class="typ">Loopback</span><span class="pln">
     inet addr</span><span class="pun">:</span><span class="lit">127.0</span><span class="pun">.</span><span class="lit">0.1</span> <span class="typ">Mask</span><span class="pun">:</span><span class="lit">255.0</span><span class="pun">.</span><span class="lit">0.0</span><span class="pln">
     inet6 addr</span><span class="pun">:</span> <span class="pun">::</span><span class="lit">1</span><span class="pun">/</span><span class="lit">128</span> <span class="typ">Scope</span><span class="pun">:</span><span class="typ">Host</span><span class="pln">
     UP LOOPBACK RUNNING MTU</span><span class="pun">:</span><span class="lit">65536</span> <span class="typ">Metric</span><span class="pun">:</span><span class="lit">1</span><span class="pln">
     RX packets</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> errors</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> dropped</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> overruns</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> frame</span><span class="pun">:</span><span class="lit">0</span><span class="pln">
     TX packets</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> errors</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> dropped</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> overruns</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> carrier</span><span class="pun">:</span><span class="lit">0</span><span class="pln">
     collisions</span><span class="pun">:</span><span class="lit">0</span><span class="pln"> txqueuelen</span><span class="pun">:</span><span class="lit">1</span><span class="pln">
     RX bytes</span><span class="pun">:</span><span class="lit">0</span> <span class="pun">(</span><span class="lit">0.0</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> TX bytes</span><span class="pun">:</span><span class="lit">0</span> <span class="pun">(</span><span class="lit">0.0</span><span class="pln"> b</span><span class="pun">)</span>
```

</div>

# Docker安裝

### Centos

[Docker Engine on CentOS | Docker Documentation](https://docs.docker.com/engine/install/centos/)

```highlight
 sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
```

```
 sudo yum install -y yum-utils
 sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
```

```
 sudo yum-config-manager --enable docker-ce-nightly
 
 sudo yum install docker-ce docker-ce-cli containerd.io
 
 sudo systemctl start docker
 sudo systemctl enable docker
```

~/.docker/config.json

```
{
 "proxies":
 {
   "default":
   {
     "httpProxy": "http://192.168.1.12:3128",
     "httpsProxy": "http://192.168.1.12:3128",
     "noProxy": "*.test.example.com,.example2.com,127.0.0.0/8"
   }
 }
}
```

/etc/docker/daemon.json

```
{
"registry-mirrors":["http://hub-mirror.c.163.com"],
}

```

```
registry-1.docker.io.	54	IN	A	34.197.211.151
registry-1.docker.io.	54	IN	A	34.192.145.113
registry-1.docker.io.	54	IN	A	18.214.230.110
registry-1.docker.io.	54	IN	A	52.55.168.20
registry-1.docker.io.	54	IN	A	3.229.227.53
registry-1.docker.io.	54	IN	A	3.209.182.229
registry-1.docker.io.	54	IN	A	3.213.204.48
registry-1.docker.io.	54	IN	A	54.161.109.204
```

```
mkdir /etc/systemd/system/docker.service.d
vim /etc/systemd/system/docker.service.d/http-proxy.conf
########################################################
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:80/"
Environment="NO_PROXY=localhost,127.0.0.0/8,docker-registry.somecorporation.com"

########################################################
sudo systemctl daemon-reload
sudo systemctl show --property Environment docker
sudo systemctl restart docker
```

---

### 使用get.docker.com 腳本

[https://get.docker.com](https://get.docker.com/)

```shell
 curl -L get.docker.com -o get-docker.sh
 sh get-docker.sh
```

```shell
#!/bin/sh
set -e
# Docker CE for Linux installation script
#
# See https://docs.docker.com/engine/install/ for the installation steps.
#
# This script is meant for quick & easy install via:
#   $ curl -fsSL https://get.docker.com -o get-docker.sh
#   $ sh get-docker.sh
#
# For test builds (ie. release candidates):
#   $ curl -fsSL https://test.docker.com -o test-docker.sh
#   $ sh test-docker.sh
#
# NOTE: Make sure to verify the contents of the script
#       you downloaded matches the contents of install.sh
#       located at https://github.com/docker/docker-install
#       before executing.
#
# Git commit from https://github.com/docker/docker-install when
# the script was uploaded (Should only be modified by upload job):
SCRIPT_COMMIT_SHA="93d2499759296ac1f9c510605fef85052a2c32be"

# strip "v" prefix if present
VERSION="${VERSION#v}"

# The channel to install from:
#   * nightly
#   * test
#   * stable
#   * edge (deprecated)
DEFAULT_CHANNEL_VALUE="stable"
if [ -z "$CHANNEL" ]; then
	CHANNEL=$DEFAULT_CHANNEL_VALUE
fi

DEFAULT_DOWNLOAD_URL="https://download.docker.com"
if [ -z "$DOWNLOAD_URL" ]; then
	DOWNLOAD_URL=$DEFAULT_DOWNLOAD_URL
fi

DEFAULT_REPO_FILE="docker-ce.repo"
if [ -z "$REPO_FILE" ]; then
	REPO_FILE="$DEFAULT_REPO_FILE"
fi

mirror=''
DRY_RUN=${DRY_RUN:-}
while [ $# -gt 0 ]; do
	case "$1" in
		--mirror)
			mirror="$2"
			shift
			;;
		--dry-run)
			DRY_RUN=1
			;;
		--*)
			echo "Illegal option $1"
			;;
	esac
	shift $(( $# > 0 ? 1 : 0 ))
done

case "$mirror" in
	Aliyun)
		DOWNLOAD_URL="https://mirrors.aliyun.com/docker-ce"
		;;
	AzureChinaCloud)
		DOWNLOAD_URL="https://mirror.azure.cn/docker-ce"
		;;
esac

command_exists() {
	command -v "$@" > /dev/null 2>&1
}

# version_gte checks if the version specified in $VERSION is at least
# the given CalVer (YY.MM) version. returns 0 (success) if $VERSION is either
# unset (=latest) or newer or equal than the specified version. Returns 1 (fail)
# otherwise.
#
# examples:
#
# VERSION=20.10
# version_gte 20.10 // 0 (success)
# version_gte 19.03 // 0 (success)
# version_gte 21.10 // 1 (fail)
version_gte() {
	if [ -z "$VERSION" ]; then
			return 0
	fi
	eval calver_compare "$VERSION" "$1"
}

# calver_compare compares two CalVer (YY.MM) version strings. returns 0 (success)
# if version A is newer or equal than version B, or 1 (fail) otherwise. Patch
# releases and pre-release (-alpha/-beta) are not taken into account
#
# examples:
#
# calver_compare 20.10 19.03 // 0 (success)
# calver_compare 20.10 20.10 // 0 (success)
# calver_compare 19.03 20.10 // 1 (fail)
calver_compare() (
	set +x

	yy_a="$(echo "$1" | cut -d'.' -f1)"
	yy_b="$(echo "$2" | cut -d'.' -f1)"
	if [ "$yy_a" -lt "$yy_b" ]; then
		return 1
	fi
	if [ "$yy_a" -gt "$yy_b" ]; then
		return 0
	fi
	mm_a="$(echo "$1" | cut -d'.' -f2)"
	mm_b="$(echo "$2" | cut -d'.' -f2)"
	if [ "${mm_a#0}" -lt "${mm_b#0}" ]; then
		return 1
	fi

	return 0
)

is_dry_run() {
	if [ -z "$DRY_RUN" ]; then
		return 1
	else
		return 0
	fi
}

is_wsl() {
	case "$(uname -r)" in
	*microsoft* ) true ;; # WSL 2
	*Microsoft* ) true ;; # WSL 1
	* ) false;;
	esac
}

is_darwin() {
	case "$(uname -s)" in
	*darwin* ) true ;;
	*Darwin* ) true ;;
	* ) false;;
	esac
}

deprecation_notice() {
	distro=$1
	distro_version=$2
	echo
	printf "\033[91;1mDEPRECATION WARNING\033[0m\n"
	printf "    This Linux distribution (\033[1m%s %s\033[0m) reached end-of-life and is no longer supported by this script.\n" "$distro" "$distro_version"
	echo   "    No updates or security fixes will be released for this distribution, and users are recommended"
	echo   "    to upgrade to a currently maintained version of $distro."
	echo
	printf   "Press \033[1mCtrl+C\033[0m now to abort this script, or wait for the installation to continue."
	echo
	sleep 10
}

get_distribution() {
	lsb_dist=""
	# Every system that we officially support has /etc/os-release
	if [ -r /etc/os-release ]; then
		lsb_dist="$(. /etc/os-release && echo "$ID")"
	fi
	# Returning an empty string here should be alright since the
	# case statements don't act unless you provide an actual value
	echo "$lsb_dist"
}

echo_docker_as_nonroot() {
	if is_dry_run; then
		return
	fi
	if command_exists docker && [ -e /var/run/docker.sock ]; then
		(
			set -x
			$sh_c 'docker version'
		) || true
	fi

	# intentionally mixed spaces and tabs here -- tabs are stripped by "<<-EOF", spaces are kept in the output
	echo
	echo "================================================================================"
	echo
	if version_gte "20.10"; then
		echo "To run Docker as a non-privileged user, consider setting up the"
		echo "Docker daemon in rootless mode for your user:"
		echo
		echo "    dockerd-rootless-setuptool.sh install"
		echo
		echo "Visit https://docs.docker.com/go/rootless/ to learn about rootless mode."
		echo
	fi
	echo
	echo "To run the Docker daemon as a fully privileged service, but granting non-root"
	echo "users access, refer to https://docs.docker.com/go/daemon-access/"
	echo
	echo "WARNING: Access to the remote API on a privileged Docker daemon is equivalent"
	echo "         to root access on the host. Refer to the 'Docker daemon attack surface'"
	echo "         documentation for details: https://docs.docker.com/go/attack-surface/"
	echo
	echo "================================================================================"
	echo
}

# Check if this is a forked Linux distro
check_forked() {

	# Check for lsb_release command existence, it usually exists in forked distros
	if command_exists lsb_release; then
		# Check if the `-u` option is supported
		set +e
		lsb_release -a -u > /dev/null 2>&1
		lsb_release_exit_code=$?
		set -e

		# Check if the command has exited successfully, it means we're in a forked distro
		if [ "$lsb_release_exit_code" = "0" ]; then
			# Print info about current distro
			cat <<-EOF
			You're using '$lsb_dist' version '$dist_version'.
			EOF

			# Get the upstream release info
			lsb_dist=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'id' | cut -d ':' -f 2 | tr -d '[:space:]')
			dist_version=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'codename' | cut -d ':' -f 2 | tr -d '[:space:]')

			# Print info about upstream distro
			cat <<-EOF
			Upstream release is '$lsb_dist' version '$dist_version'.
			EOF
		else
			if [ -r /etc/debian_version ] && [ "$lsb_dist" != "ubuntu" ] && [ "$lsb_dist" != "raspbian" ]; then
				if [ "$lsb_dist" = "osmc" ]; then
					# OSMC runs Raspbian
					lsb_dist=raspbian
				else
					# We're Debian and don't even know it!
					lsb_dist=debian
				fi
				dist_version="$(sed 's/\/.*//' /etc/debian_version | sed 's/\..*//')"
				case "$dist_version" in
					11)
						dist_version="bullseye"
					;;
					10)
						dist_version="buster"
					;;
					9)
						dist_version="stretch"
					;;
					8)
						dist_version="jessie"
					;;
				esac
			fi
		fi
	fi
}

do_install() {
	echo "# Executing docker install script, commit: $SCRIPT_COMMIT_SHA"

	if command_exists docker; then
		cat >&2 <<-'EOF'
			Warning: the "docker" command appears to already exist on this system.

			If you already have Docker installed, this script can cause trouble, which is
			why we're displaying this warning and provide the opportunity to cancel the
			installation.

			If you installed the current Docker package using this script and are using it
			again to update Docker, you can safely ignore this message.

			You may press Ctrl+C now to abort this script.
		EOF
		( set -x; sleep 20 )
	fi

	user="$(id -un 2>/dev/null || true)"

	sh_c='sh -c'
	if [ "$user" != 'root' ]; then
		if command_exists sudo; then
			sh_c='sudo -E sh -c'
		elif command_exists su; then
			sh_c='su -c'
		else
			cat >&2 <<-'EOF'
			Error: this installer needs the ability to run commands as root.
			We are unable to find either "sudo" or "su" available to make this happen.
			EOF
			exit 1
		fi
	fi

	if is_dry_run; then
		sh_c="echo"
	fi

	# perform some very rudimentary platform detection
	lsb_dist=$( get_distribution )
	lsb_dist="$(echo "$lsb_dist" | tr '[:upper:]' '[:lower:]')"

	if is_wsl; then
		echo
		echo "WSL DETECTED: We recommend using Docker Desktop for Windows."
		echo "Please get Docker Desktop from https://www.docker.com/products/docker-desktop"
		echo
		cat >&2 <<-'EOF'

			You may press Ctrl+C now to abort this script.
		EOF
		( set -x; sleep 20 )
	fi

	case "$lsb_dist" in

		ubuntu)
			if command_exists lsb_release; then
				dist_version="$(lsb_release --codename | cut -f2)"
			fi
			if [ -z "$dist_version" ] && [ -r /etc/lsb-release ]; then
				dist_version="$(. /etc/lsb-release && echo "$DISTRIB_CODENAME")"
			fi
		;;

		debian|raspbian)
			dist_version="$(sed 's/\/.*//' /etc/debian_version | sed 's/\..*//')"
			case "$dist_version" in
				11)
					dist_version="bullseye"
				;;
				10)
					dist_version="buster"
				;;
				9)
					dist_version="stretch"
				;;
				8)
					dist_version="jessie"
				;;
			esac
		;;

		centos|rhel|sles)
			if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then
				dist_version="$(. /etc/os-release && echo "$VERSION_ID")"
			fi
		;;

		*)
			if command_exists lsb_release; then
				dist_version="$(lsb_release --release | cut -f2)"
			fi
			if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then
				dist_version="$(. /etc/os-release && echo "$VERSION_ID")"
			fi
		;;

	esac

	# Check if this is a forked Linux distro
	check_forked

	# Print deprecation warnings for distro versions that recently reached EOL,
	# but may still be commonly used (especially LTS versions).
	case "$lsb_dist.$dist_version" in
		debian.stretch|debian.jessie)
			deprecation_notice "$lsb_dist" "$dist_version"
			;;
		raspbian.stretch|raspbian.jessie)
			deprecation_notice "$lsb_dist" "$dist_version"
			;;
		ubuntu.xenial|ubuntu.trusty)
			deprecation_notice "$lsb_dist" "$dist_version"
			;;
		fedora.*)
			if [ "$dist_version" -lt 33 ]; then
				deprecation_notice "$lsb_dist" "$dist_version"
			fi
			;;
	esac

	# Run setup for each distro accordingly
	case "$lsb_dist" in
		ubuntu|debian|raspbian)
			pre_reqs="apt-transport-https ca-certificates curl"
			if ! command -v gpg > /dev/null; then
				pre_reqs="$pre_reqs gnupg"
			fi
			apt_repo="deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] $DOWNLOAD_URL/linux/$lsb_dist $dist_version $CHANNEL"
			(
				if ! is_dry_run; then
					set -x
				fi
				$sh_c 'apt-get update -qq >/dev/null'
				$sh_c "DEBIAN_FRONTEND=noninteractive apt-get install -y -qq $pre_reqs >/dev/null"
				$sh_c "curl -fsSL \"$DOWNLOAD_URL/linux/$lsb_dist/gpg\" | gpg --dearmor --yes -o /usr/share/keyrings/docker-archive-keyring.gpg"
				$sh_c "echo \"$apt_repo\" > /etc/apt/sources.list.d/docker.list"
				$sh_c 'apt-get update -qq >/dev/null'
			)
			pkg_version=""
			if [ -n "$VERSION" ]; then
				if is_dry_run; then
					echo "# WARNING: VERSION pinning is not supported in DRY_RUN"
				else
					# Will work for incomplete versions IE (17.12), but may not actually grab the "latest" if in the test channel
					pkg_pattern="$(echo "$VERSION" | sed "s/-ce-/~ce~.*/g" | sed "s/-/.*/g").*-0~$lsb_dist"
					search_command="apt-cache madison 'docker-ce' | grep '$pkg_pattern' | head -1 | awk '{\$1=\$1};1' | cut -d' ' -f 3"
					pkg_version="$($sh_c "$search_command")"
					echo "INFO: Searching repository for VERSION '$VERSION'"
					echo "INFO: $search_command"
					if [ -z "$pkg_version" ]; then
						echo
						echo "ERROR: '$VERSION' not found amongst apt-cache madison results"
						echo
						exit 1
					fi
					if version_gte "18.09"; then
							search_command="apt-cache madison 'docker-ce-cli' | grep '$pkg_pattern' | head -1 | awk '{\$1=\$1};1' | cut -d' ' -f 3"
							echo "INFO: $search_command"
							cli_pkg_version="=$($sh_c "$search_command")"
					fi
					pkg_version="=$pkg_version"
				fi
			fi
			(
				pkgs=""
				if version_gte "18.09"; then
						# older versions don't support a cli package
						pkgs="$pkgs docker-ce-cli${cli_pkg_version%=}"
				fi
				if version_gte "20.10" && [ "$(uname -m)" = "x86_64" ]; then
						# also install the latest version of the "docker scan" cli-plugin (only supported on x86 currently)
						pkgs="$pkgs docker-scan-plugin"
				fi
				pkgs="$pkgs docker-ce${pkg_version%=}"
				if ! is_dry_run; then
					set -x
				fi
				$sh_c "DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends $pkgs >/dev/null"
				if version_gte "20.10"; then
					# Install docker-ce-rootless-extras without "--no-install-recommends", so as to install slirp4netns when available
					$sh_c "DEBIAN_FRONTEND=noninteractive apt-get install -y -qq docker-ce-rootless-extras${pkg_version%=} >/dev/null"
				fi
			)
			echo_docker_as_nonroot
			exit 0
			;;
		centos|fedora|rhel)
			if [ "$(uname -m)" != "s390x" ] && [ "$lsb_dist" = "rhel" ]; then
				echo "Packages for RHEL are currently only available for s390x."
				exit 1
			fi
			yum_repo="$DOWNLOAD_URL/linux/$lsb_dist/$REPO_FILE"
			if ! curl -Ifs "$yum_repo" > /dev/null; then
				echo "Error: Unable to curl repository file $yum_repo, is it valid?"
				exit 1
			fi
			if [ "$lsb_dist" = "fedora" ]; then
				pkg_manager="dnf"
				config_manager="dnf config-manager"
				enable_channel_flag="--set-enabled"
				disable_channel_flag="--set-disabled"
				pre_reqs="dnf-plugins-core"
				pkg_suffix="fc$dist_version"
			else
				pkg_manager="yum"
				config_manager="yum-config-manager"
				enable_channel_flag="--enable"
				disable_channel_flag="--disable"
				pre_reqs="yum-utils"
				pkg_suffix="el"
			fi
			(
				if ! is_dry_run; then
					set -x
				fi
				$sh_c "$pkg_manager install -y -q $pre_reqs"
				$sh_c "$config_manager --add-repo $yum_repo"

				if [ "$CHANNEL" != "stable" ]; then
					$sh_c "$config_manager $disable_channel_flag docker-ce-*"
					$sh_c "$config_manager $enable_channel_flag docker-ce-$CHANNEL"
				fi
				$sh_c "$pkg_manager makecache"
			)
			pkg_version=""
			if [ -n "$VERSION" ]; then
				if is_dry_run; then
					echo "# WARNING: VERSION pinning is not supported in DRY_RUN"
				else
					pkg_pattern="$(echo "$VERSION" | sed "s/-ce-/\\\\.ce.*/g" | sed "s/-/.*/g").*$pkg_suffix"
					search_command="$pkg_manager list --showduplicates 'docker-ce' | grep '$pkg_pattern' | tail -1 | awk '{print \$2}'"
					pkg_version="$($sh_c "$search_command")"
					echo "INFO: Searching repository for VERSION '$VERSION'"
					echo "INFO: $search_command"
					if [ -z "$pkg_version" ]; then
						echo
						echo "ERROR: '$VERSION' not found amongst $pkg_manager list results"
						echo
						exit 1
					fi
					if version_gte "18.09"; then
						# older versions don't support a cli package
						search_command="$pkg_manager list --showduplicates 'docker-ce-cli' | grep '$pkg_pattern' | tail -1 | awk '{print \$2}'"
						cli_pkg_version="$($sh_c "$search_command" | cut -d':' -f 2)"
					fi
					# Cut out the epoch and prefix with a '-'
					pkg_version="-$(echo "$pkg_version" | cut -d':' -f 2)"
				fi
			fi
			(
				if ! is_dry_run; then
					set -x
				fi
				# install the correct cli version first
				if [ -n "$cli_pkg_version" ]; then
					$sh_c "$pkg_manager install -y -q docker-ce-cli-$cli_pkg_version"
				fi
				$sh_c "$pkg_manager install -y -q docker-ce$pkg_version"
				if version_gte "20.10"; then
					$sh_c "$pkg_manager install -y -q docker-ce-rootless-extras$pkg_version"
				fi
			)
			echo_docker_as_nonroot
			exit 0
			;;
		sles)
			if [ "$(uname -m)" != "s390x" ]; then
				echo "Packages for SLES are currently only available for s390x"
				exit 1
			fi

			sles_version="${dist_version##*.}"
			sles_repo="$DOWNLOAD_URL/linux/$lsb_dist/$REPO_FILE"
			opensuse_repo="https://download.opensuse.org/repositories/security:SELinux/SLE_15_SP$sles_version/security:SELinux.repo"
			if ! curl -Ifs "$sles_repo" > /dev/null; then
				echo "Error: Unable to curl repository file $sles_repo, is it valid?"
				exit 1
			fi
			pre_reqs="ca-certificates curl libseccomp2 awk"
			(
				if ! is_dry_run; then
					set -x
				fi
				$sh_c "zypper install -y $pre_reqs"
				$sh_c "zypper addrepo $sles_repo"
				if ! is_dry_run; then
						cat >&2 <<-'EOF'
						WARNING!!
						openSUSE repository (https://download.opensuse.org/repositories/security:SELinux) will be enabled now.
						Do you wish to continue?
						You may press Ctrl+C now to abort this script.
						EOF
						( set -x; sleep 30 )
				fi
				$sh_c "zypper addrepo $opensuse_repo"
				$sh_c "zypper --gpg-auto-import-keys refresh"
				$sh_c "zypper lr -d"
			)
			pkg_version=""
			if [ -n "$VERSION" ]; then
				if is_dry_run; then
					echo "# WARNING: VERSION pinning is not supported in DRY_RUN"
				else
					pkg_pattern="$(echo "$VERSION" | sed "s/-ce-/\\\\.ce.*/g" | sed "s/-/.*/g")"
					search_command="zypper search -s --match-exact 'docker-ce' | grep '$pkg_pattern' | tail -1 | awk '{print \$6}'"
					pkg_version="$($sh_c "$search_command")"
					echo "INFO: Searching repository for VERSION '$VERSION'"
					echo "INFO: $search_command"
					if [ -z "$pkg_version" ]; then
						echo
						echo "ERROR: '$VERSION' not found amongst zypper list results"
						echo
						exit 1
					fi
					search_command="zypper search -s --match-exact 'docker-ce-cli' | grep '$pkg_pattern' | tail -1 | awk '{print \$6}'"
					# It's okay for cli_pkg_version to be blank, since older versions don't support a cli package
					cli_pkg_version="$($sh_c "$search_command")"
					pkg_version="-$pkg_version"

					search_command="zypper search -s --match-exact 'docker-ce-rootless-extras' | grep '$pkg_pattern' | tail -1 | awk '{print \$6}'"
					rootless_pkg_version="$($sh_c "$search_command")"
					rootless_pkg_version="-$rootless_pkg_version"
				fi
			fi
			(
				if ! is_dry_run; then
					set -x
				fi
				# install the correct cli version first
				if [ -n "$cli_pkg_version" ]; then
					$sh_c "zypper install -y  docker-ce-cli-$cli_pkg_version"
				fi
				$sh_c "zypper install -y docker-ce$pkg_version"
				if version_gte "20.10"; then
					$sh_c "zypper install -y docker-ce-rootless-extras$rootless_pkg_version"
				fi
			)
			echo_docker_as_nonroot
			exit 0
			;;
		*)
			if [ -z "$lsb_dist" ]; then
				if is_darwin; then
					echo
					echo "ERROR: Unsupported operating system 'macOS'"
					echo "Please get Docker Desktop from https://www.docker.com/products/docker-desktop"
					echo
					exit 1
				fi
			fi
			echo
			echo "ERROR: Unsupported distribution '$lsb_dist'"
			echo
			exit 1
			;;
	esac
	exit 1
}

# wrapped up in a function so that we have some protection against only getting
# half the file during "curl | sh"
do_install
```

# Docker架構

[![image-1644994790311.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-02/scaled-1680-/XEObQQ2Bh4FolaIj-image-1644994790311.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-02/XEObQQ2Bh4FolaIj-image-1644994790311.png)

[![image-1644994815207.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-02/scaled-1680-/5xLhezmrYbZpz2O4-image-1644994815207.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-02/5xLhezmrYbZpz2O4-image-1644994815207.png)

[![image-1644994935799.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-02/scaled-1680-/4KpqHL7bW0Xqz794-image-1644994935799.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-02/4KpqHL7bW0Xqz794-image-1644994935799.png)

# Docker常用指令

[![image-1641898072150.png](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/scaled-1680-/yQqsC2nE74AEf4ci-image-1641898072150.png)](https://bookstack.treemanou.com/uploads/images/gallery/2022-01/yQqsC2nE74AEf4ci-image-1641898072150.png)

\*container 運行

```shell
#run:
#-d 背景執行
#nginx 執行什麼服務
#ng 自訂的tagname
#-name 自訂名稱
# -e 設定環境變數, TZ=Asia/Taipei => 設定時區
docker container run -d nginx
docker container run -d -name ngx nginx
docker container run -d nginx:ng
docker container run -d -e "TZ=Asia/Taipei" nginx
```

\*查看運行container

```shell
docker container ls -a

[tomcat@docker-qc ~]$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
df6ab3df4b14        nginx               "nginx -g 'daemon of…"   9 seconds ago       Up 8 seconds        80/tcp              modest_cray
940d3d804bcd        nginx               "nginx -g 'daemon of…"   7 minutes ago       Up 7 minutes        80/tcp              elastic_raman

```

\*運行container 並進入shell

```shell
docker container run -it {container name} sh
```

[![image-1637142725643.png](https://bookstack.treemanou.com/uploads/images/gallery/2021-11/scaled-1680-/XbqLbfiUKtgdFbYz-image-1637142725643.png)](https://bookstack.treemanou.com/uploads/images/gallery/2021-11/XbqLbfiUKtgdFbYz-image-1637142725643.png)

\*進入已運行container

```shell
# 進入名為apache的容器執行sh
docker exec -it apache sh
```

\*複製檔案

```shell
# 建立一個hello.html
echo "hello" > hello.html
# 建立apache
docker run -d --name apache httpd:alpine
# 複製檔案至apache容器中
docker cp hello.html apache:/usr/local/apache2/htdocs/
# 複製容器中的檔案至本機
docker cp apache:/usr/local/apache2/htdocs/index.html ./index.html
```

\*掛載目錄

```shell
# 把hello.html掛成index.html
docker run -d --name apache2 -v $PWD/hello.html:/usr/local/apache2/htdocs/index.html httpd:alpine
```

\*建立外部連線

```shell
# -p port 對應 {本機}:{容器}
docker run -d -v $PWD.hell.html:/url/local/apache2/htdocs/index.html -p 80:80 httpd:alpine
```

---

\*刪除container

[![image-1637142432159.png](https://bookstack.treemanou.com/uploads/images/gallery/2021-11/scaled-1680-/qOCJd5dGCtA5ZwlU-image-1637142432159.png)](https://bookstack.treemanou.com/uploads/images/gallery/2021-11/qOCJd5dGCtA5ZwlU-image-1637142432159.png)

```shell
#-f 強制
docker rm -f {container id}

#刪除所有容器
docker rm -f $(docker ps -a -q)
#刪除所有名字有demo的容器
docker rm -f $(docker ps -a  -q -f name=demo)

# 停用所有container
docker stop $(docker ps -a -q)
# 刪除沒已使用的container 與 image
docker system prune
# 刪除所有映像檔
docker rmi $(docker images -a -q)
# 刪除所有name = <none> 的映像檔
docker rmi $(docker images -f "dangling=true" -q)
# 刪除所有名稱叫shopcar的映像檔
docker rmi $(docker images shopcar* -q)

# 清除volume
docker volume rm $(docker volume ls)

# 刪除所有沒有使用的container image volume
docker system prune -a -f --volumes

#起一個不會停止的centos
docker run -d --name centos7 centos:7 sleep infinity
```

---

#### 查看要效能

\*從主機查看container process

[![image-1637142044315.png](https://bookstack.treemanou.com/uploads/images/gallery/2021-11/scaled-1680-/VJEXMxCf0qyoGca5-image-1637142044315.png)](https://bookstack.treemanou.com/uploads/images/gallery/2021-11/VJEXMxCf0qyoGca5-image-1637142044315.png)

[![image-1637142037886.png](https://bookstack.treemanou.com/uploads/images/gallery/2021-11/scaled-1680-/aeI7SiLajqZ2uD20-image-1637142037886.png)](https://bookstack.treemanou.com/uploads/images/gallery/2021-11/aeI7SiLajqZ2uD20-image-1637142037886.png)

```shell
docker container top {container id}
```

\*查看狀態

```shell
# 容器狀態
docker stats {container id | name }
# cpu ram
docker top {container id | name }
# log
docker logs {container id | name }
docker logs -f {container id | name }
```

---

# Dockerfile 的 /etc/hosts 如何設定

來源：

[Dockerfile 的 /etc/hosts 如何設定 – Tsung's Blog (longwin.com.tw)](https://blog.longwin.com.tw/2018/09/docker-dockerfile-etc-hosts-dns-setup-2018/)

## Dockerfile 的 /etc/hosts 如何設定

於 [Dockerfile reference](https://docs.docker.com/engine/reference/builder/) 文件裡面，沒有看到 /etc/hosts 該怎麼改，後來發現 /etc/hosts 修改的方式還蠻黑暗的~

修改 /etc/hosts 的作法有兩種，先講比較正確的方法：

Docker 增加 hosts 可以參考 Docker run 的文件：[Docker run reference](https://docs.docker.com/engine/reference/run/)

於 Docker run 使用 --add-host=server-name:127.0.0.1，多個用空白隔開，繼續寫下去即可，範例如下：

- **docker run ... --add-host='server:0.0.0.0' ...**
- **docker run ... --add-host='server:127.0.0.1' --add-host='server2:127.0.0.2'...**

若有 /etc/hosts 有太多需要增加，可以使用下述 Shell script 產生 --add-host 參數

- /etc/hosts 若要 1 vs 1 的 ip host 對應 
    - **cat /etc/hosts | sed 's/^#.\*//g' | grep '\[0-9\]\[0-9\]' | tr "\\t" " " | awk '{print "--add-host="$2":"$1 }' | tr '\\n' ' '**
- /etc/hosts 若要 1 vs n(多) 的 ip host 對應 
    - **cat /etc/hosts | grep -v "^#" | awk '{for(i=2;i&lt;=NF;i++){print "--add-host "$i":"$1}}'**

再來看比較暴力的作法：(直接寫在 Dockerfile 裡面)

```
# 使用 /tmp/hosts 當 /etc/hosts COPY /etc/hosts /tmp/hosts.bak
RUN cp hosts /tmp/hosts # hosts 於外部 cp /etc/hosts .
#RUN cp /etc/hosts /tmp/hosts #路径长度最好保持一致
RUN mkdir -p -- /lib-override && cp /lib/x86_64-linux-gnu/libnss_files.so.2 /lib-override
RUN sed -i 's:/etc/hosts:/tmp/hosts:g' /lib-override/libnss_files.so.2
ENV LD_LIBRARY_PATH /lib-override
RUN cat /tmp/hosts.bak >> /tmp/hosts
```

Docker 內部讀取 /etc/hosts 的部份，修改成讀取 **/tmp/hosts** (參考自此篇：[Docker 修改 hosts](https://wongxingjun.github.io/2016/04/06/Docker%E4%BF%AE%E6%94%B9hosts/))

將下述寫入 Dockerfile，於 build 的時候，就會讀取 /tmp/hosts 來操作囉~

### 相關網頁

- - [docker 之 dockerFile (解決 hosts，hostname 問題)](https://blog.csdn.net/libo222/article/details/52669093)
    - [docker - Modify hosts file in dockerfile](https://serverfault.com/questions/777714/modify-hosts-file-in-dockerfil)

# Docker 使用私有repo (Nexus)

```p1
vim /etc/docker/daemon.json
```

```
{
    "insecure-registries": ["10.10.10.10:8083"],
    "registry-mirrors": ["http://10.10.10.10:8083"]
}
```

```
sudo systemctl restart docker
```

[![image-1733823888931.png](https://bookstack.treemanou.com/uploads/images/gallery/2024-12/scaled-1680-/Sun0E0r2v3qHI2mq-image-1733823888931.png)](https://bookstack.treemanou.com/uploads/images/gallery/2024-12/Sun0E0r2v3qHI2mq-image-1733823888931.png)

[![image-1733823909856.png](https://bookstack.treemanou.com/uploads/images/gallery/2024-12/scaled-1680-/OeE7TnZi2zpJNQfu-image-1733823909856.png)](https://bookstack.treemanou.com/uploads/images/gallery/2024-12/OeE7TnZi2zpJNQfu-image-1733823909856.png)

https://registry-1.docker.io

[![image-1733824478204.png](https://bookstack.treemanou.com/uploads/images/gallery/2024-12/scaled-1680-/k9GuHCfoM0j1FhJO-image-1733824478204.png)](https://bookstack.treemanou.com/uploads/images/gallery/2024-12/k9GuHCfoM0j1FhJO-image-1733824478204.png)

# Docker 內 container 如何使用Docker

在 Docker 容器內部直接執行宿主機上的 Docker 命令有一定的限制，因為 Docker 容器本身是與宿主機隔離的。以下是一些實現方法，根據不同需求選擇適合的解法：

---

### **方法 1：將 Docker socket 映射到容器**

將宿主機的 Docker socket (`/var/run/docker.sock`) 映射到容器內部，這樣容器內部的 Docker CLI 可以直接與宿主機的 Docker daemon 通訊。

#### **步驟**

1. **啟動容器時掛載 Docker socket：**
    
    ```bash
    docker run -it --rm \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v $(which docker):/usr/bin/docker \
      your-image
    
    ```
2. **在容器內使用 Docker 命令：** 容器內的 Docker CLI 可以直接操作宿主機的 Docker，執行例如 `docker ps`、`docker run` 等指令。
3. **注意安全性：** 授予容器訪問 Docker socket 的權限會帶來安全風險，因為容器內的進程可以完全控制宿主機的 Docker。僅在信任的環境下使用此方法。

---

### **方法 2：使用 Docker-in-Docker (DinD)**

如果希望在容器內運行獨立的 Docker daemon，可以使用 Docker 官方的 `docker:dind` 映像。

#### **步驟**

1. 啟動 DinD 容器：
    
    ```bash
    docker run --privileged --name dind-container -d docker:dind
    
    ```
2. 進入容器：
    
    ```bash
    docker exec -it dind-container sh
    
    ```
3. 在容器內執行 Docker 命令（這是獨立的 Docker daemon，不會影響宿主機的 Docker）。

---

### **方法 3：使用 Docker CLI 並通過 API 操作**

宿主機的 Docker daemon 提供 REST API，可以在容器內安裝 Docker CLI 並通過 API 操作。

#### **步驟**

1. 確保宿主機的 Docker daemon 開啟遠程 API，編輯 `/etc/docker/daemon.json`：
    
    ```json
    {
      "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
    }
    
    ```
    
    然後重啟 Docker：
    
    ```bash
    sudo systemctl restart docker
    
    ```
2. 啟動容器，並配置環境變數 `DOCKER_HOST` 指向宿主機 API：
    
    ```bash
    docker run -it --rm \
      -e DOCKER_HOST=tcp://<host-ip>:2375 \
      your-image
    
    ```
3. 在容器內執行 Docker 命令：
    
    ```bash
    docker ps
    
    ```

---

### **注意事項**

1. **安全風險：**
    
    
    - 授予容器訪問 Docker socket 或 Docker daemon 的權限可能導致安全漏洞。
    - 確保只在受信任的環境中使用，並採取必要的隔離措施（例如：限制網路訪問、使用 TLS 保護 API）。
2. **性能影響：**
    
    
    - 如果容器內需要頻繁操作宿主機的 Docker，可能會影響宿主機的性能。
3. **權限問題：**
    
    
    - 確保容器內的進程有足夠的權限訪問 `/var/run/docker.sock` 或 Docker API。

希望這些方法能幫助你解決問題！如果需要更詳細的操作指引，可以告訴我具體的需求或環境設定。

# 【Docker】上傳自己的 Docker image 到 Docker Hub

要上傳自己的 Docker image 到 Docker Hub，請按照以下步驟操作：

### 1. 登入 Docker Hub

確保你的電腦已經安裝了 Docker，然後使用以下命令登入 Docker Hub：

```sh
docker login

```

系統會要求輸入你的 Docker Hub 帳號和密碼。

### 2. 建立 Docker Image

如果你還沒有 Docker image，可以使用 `docker build` 指令來建立：

```sh
docker build -t <你的DockerHub帳號>/<image名稱>:<tag> .

```

例如：

```sh
docker build -t myusername/myapp:v1 .

```

這樣就會建立一個 `myusername/myapp` 的 image，標籤（tag）為 `v1`。

### 3. 標記 (Tag) Image

如果你已經有一個本地的 image，但還沒有加上 Docker Hub 的 repository 名稱，你需要先標記它：

```sh
docker tag <本地image ID或名稱> <你的DockerHub帳號>/<image名稱>:<tag>

```

例如：

```sh
docker tag myapp:latest myusername/myapp:v1

```

### 4. 推送 (Push) Image

將 image 推送到 Docker Hub：

```sh
docker push <你的DockerHub帳號>/<image名稱>:<tag>

```

例如：

```sh
docker push myusername/myapp:v1

```

### 5. 確認上傳成功

你可以到 [Docker Hub](https://hub.docker.com/) 查看你的 repository，或者在其他機器上使用以下命令來拉取（pull）該 image：

```sh
docker pull myusername/myapp:v1

```

### 常見問題

1. **登入失敗**：
    
    
    - 如果 `docker login` 失敗，可以先在 Docker Hub 上確認你的帳號密碼是否正確。
    - 如果你使用的是 Docker Hub 產生的 Access Token，請在密碼欄位輸入該 Token。
2. **推送失敗，沒有權限 (denied: requested access to the resource is denied)**：
    
    
    - 確保你的 image tag 是 `你的DockerHub帳號/你的image名稱`，而不是本地的名稱。
    - 使用 `docker login` 確保你已登入正確的帳號。

這樣你就能成功上傳自己的 Docker image 到 Docker Hub 了！ 🚀

# 【Docker】自動分配網路用盡

failed to create network pub-sub\_pubsub: Error response from daemon: could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network

👉 **這個錯誤的意思是**：

> Docker **沒有可用的 IP 網段** 來建立新的 network。

Docker 每次起新的 network，會自動從預設的 IP range (例如 172.18.0.0/16) 分配一段子網（subnet）來給你的 `docker-compose`。  
但因為你本機已經有太多 Docker network（或之前的 container network 沒清乾淨），導致 **IP address range 已經用光了**。

解法，詳細往下看

```YAML
# 查詢目前所有container網段
docker network inspect $(docker network ls -q) --format '{{.Name}}: {{(index .IPAM.Config 0).Subnet}}'


# 刪除無用network 
docker network prune

#解法，指定網段  
networks:
  ngtest:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24

```

---

# 🛠️ 解法 1：刪掉無用的 Docker Network

先看一下目前的 network：

```bash
docker network ls

```

會看到一堆像這樣：

<table id="bkmrk-network-id-name-driv"><thead><tr><th>NETWORK ID</th><th>NAME</th><th>DRIVER</th><th>SCOPE</th></tr></thead><tbody><tr><td>1a2b3c4d5e</td><td>bridge</td><td>bridge</td><td>local</td></tr><tr><td>6f7g8h9i0j</td><td>pub-sub\_pubsub</td><td>bridge</td><td>local</td></tr><tr><td>...</td><td>...</td><td>...</td><td>...</td></tr></tbody></table>

然後手動刪掉沒用的 network，例如：

```bash
docker network rm network_name

```

例如：

```bash
docker network rm pub-sub_pubsub

```

要一口氣刪很多：

```bash
docker network prune

```

（⚡小心！`prune` 會**把所有未使用的網路刪掉**。）

---

# 🛠️ 解法 2：docker-compose.yml 手動指定 IP 範圍

如果你想避免這個問題，以後可以**自己在 `docker-compose.yml` 裡面設定固定的子網段**，例如：

```yaml
networks:
  pubsub-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.30.0.0/16

```

然後每個 service 指定 network：

```yaml
services:
  pubsub-emulator:
    image: google/cloud-sdk:latest
    networks:
      - pubsub-net

```

這樣 Docker 就不會自己亂分配 IP，會用你指定的 `172.30.0.0/16`，可以大大降低出錯的機會。

---

# 🔥 最快速推薦操作

直接下這兩行，清除掉無用網路 ➔ 再重開 docker-compose：

```bash
docker network prune -f
docker-compose up

```

---

# 🛎️ 小提醒

<table id="bkmrk-%E5%95%8F%E9%A1%8C%E6%83%85%E5%A2%83-%E8%AA%AA%E6%98%8E-%E9%80%9A%E5%B8%B8%E5%87%BA%E7%8F%BE%E5%9C%A8-docker"><thead><tr><th align="left">問題情境</th><th align="left">說明</th></tr></thead><tbody><tr><td align="left">通常出現在 Docker Desktop 很久沒清</td><td align="left">每次起 network，Docker 自動分配，結果越堆越多</td></tr><tr><td align="left">`docker network ls` 看太多 bridge</td><td align="left">可以確認哪些是 zombie network</td></tr><tr><td align="left">`docker-compose down` 不一定會清 network</td><td align="left">要自己下 `prune` 或 `network rm`</td></tr></tbody></table>

---

好問題！  
你問的這個其實就是：

> **如何查目前 Docker 所有 network 的網段（subnet），確保自己新建的網段不會衝突？**

這個是專業級的 docker networking 操作了，我來直接教你最正確、完整又快速的方法 👨🏻‍💻

---

# ✅ 查詢目前所有 Docker network 網段的方法

直接打：

```bash
docker network inspect $(docker network ls -q) --format '{{.Name}}: {{(index .IPAM.Config 0).Subnet}}'

```

這條指令的意思是：

- `docker network ls -q`：列出所有 network 的 ID
- `docker network inspect`：逐個去查 network 詳細資訊
- `--format`：只輸出你要看的部分（名字 + 子網範圍）

👉 出來結果像這樣：

```
bridge: 172.17.0.0/16
host: 
none: 
myproject_default: 172.21.0.0/16
another-network: 172.22.0.0/16

```

如果某些 network 是空的（像 `host`、`none`），那是正常的，因為它們沒有自己管理 IP。

---

# 🛠️ 查完之後怎麼重新分配？

- 看到目前用掉哪些子網了（例如 172.17.0.0/16、172.21.0.0/16）
- 選一個**完全沒重疊**的新網段來建你的 network，例如：
    
    
    - `172.28.0.0/24`
    - `172.30.0.0/24`
    - `192.168.100.0/24`
    - `10.20.0.0/24`
- 然後在你的 `docker-compose.yml` 裡設定你自己的網段！

（一般建議用 172.x.x.x / 192.168.x.x / 10.x.x.x 這些 private 網段）

---

# 🔥 進階版（更詳細看）

如果你想要看得更細，例如看到每個 container 的 IP，可以打：

```bash
docker network inspect network-name

```

例：

```bash
docker network inspect bridge
docker network inspect pubsub-net

```

它會印出一個超大 JSON，裡面會列出：

- 網段 subnet
- gateway
- 已連接的 container 名稱和 IP 地址

---

# 🛎️ 小結論

<table id="bkmrk-%E4%BD%A0%E6%83%B3%E5%81%9A%E4%BB%80%E9%BA%BC-%E6%8C%87%E4%BB%A4-%E7%9C%8B%E6%89%80%E6%9C%89-network"><thead><tr><th align="left">你想做什麼</th><th align="left">指令</th></tr></thead><tbody><tr><td align="left">看所有 network 網段</td><td align="left">`docker network inspect $(docker network ls -q) --format '{{.Name}}: {{(index .IPAM.Config 0).Subnet}}'`</td></tr><tr><td align="left">詳細看某個 network</td><td align="left">`docker network inspect network-name`</td></tr></tbody></table>

---

# 【Docker】image tage 比較

當然可以！我們來一一比較你提到的這些 Docker image tag（以 Node.js 為例常見的 tag 形式），重點在於：

> ❗**它們的差異主要在底層作業系統的發行版與體積，會影響相容性、功能完整度、啟動速度與安全更新週期。**

---

## ✅ 比較總覽表

<table id="bkmrk-tag-%E5%BA%95%E5%B1%A4%E7%B3%BB%E7%B5%B1-%E9%AB%94%E7%A9%8D%EF%BC%88%E6%A6%82%E4%BC%B0%EF%BC%89-%E7%9B%B8%E5%AE%B9%E6%80%A7-"><thead><tr><th>Tag</th><th>底層系統</th><th>體積（概估）</th><th>相容性</th><th>套件完整度</th><th>適合場景</th></tr></thead><tbody><tr><td>`20.19.3`</td><td>Debian（預設）</td><td>🟠 中（~100MB）</td><td>✅ 高</td><td>✅ 完整</td><td>開發 / 安全穩定部署</td></tr><tr><td>`20.19.3-slim`</td><td>Debian（精簡）</td><td>🟡 較小（~30–50MB）</td><td>✅ 高</td><td>🟡 精簡套件</td><td>精簡部署，但仍需套件支援</td></tr><tr><td>`20.19.3-bullseye`</td><td>Debian 11 (Bullseye)</td><td>🟠 中</td><td>✅ 高</td><td>✅ 完整</td><td>LTS 開發與部署</td></tr><tr><td>`20.19.3-bullseye-slim`</td><td>Debian 11 (精簡)</td><td>🟡 較小</td><td>✅ 高</td><td>🟡 精簡</td><td>比 `slim` 更指定版本的精簡版</td></tr><tr><td>`20.19.3-bookworm`</td><td>Debian 12 (Bookworm)</td><td>🟠 中</td><td>✅ 高</td><td>✅ 完整</td><td>新版 Debian，未來趨勢</td></tr><tr><td>`20.19.3-bookworm-slim`</td><td>Debian 12 (精簡)</td><td>🟡 較小</td><td>✅ 高</td><td>🟡 精簡</td><td>更「新」的精簡版本</td></tr><tr><td>`20.19.3-alpine3.22`</td><td>Alpine Linux 3.22</td><td>🟢 超小（~5MB）</td><td>⚠️ 中</td><td>❌ 非常精簡</td><td>超小部署映像，需自行加套件</td></tr><tr><td>`20.19.3-alpine`</td><td>最新 Alpine 版本</td><td>🟢 超小</td><td>⚠️ 中</td><td>❌ 非常精簡</td><td>最新 alpine，可能有相容性風險</td></tr></tbody></table>

---

## 🧩 詳細說明與比較依據

### 1️⃣ **無尾碼版本：`20.19.3`**

- 預設會用 **Debian（目前是 Bookworm 或 Bullseye）**
- 最穩定、最多人支援的標準版本
- 套件支援完整，但 image 比 slim 大

---

### 2️⃣ **slim 系列（`slim`, `bullseye-slim`, `bookworm-slim`）**

- 相比完整版，移除了 **man pages、locale 資料、編譯工具**
- 仍然保留 Debian 的核心相容性
- 較小但仍易於除錯與擴充，比 alpine 安全穩

---

### 3️⃣ **alpine 系列（`alpine`, `alpine3.22`）**

- 超小型（~5MB），非常適合部署
- 缺點：需額外安裝 libc（有時需 glibc，不然會出現 `segmentation fault`）
- 有些 Node 原生模組會無法正常編譯
- 建議只在熟悉 Alpine Linux 的情況下使用

---

### 4️⃣ **bullseye vs. bookworm**

- `bullseye` = Debian 11（2021 發布）
- `bookworm` = Debian 12（2023 發布，目前最新版）

> 若你要做長期部署，**bookworm 更新、更長期支援**；但部分舊系統（如 AWS AMI、某些 lib）可能還用 bullseye。

---

## ✅ 實務建議

<table id="bkmrk-%E9%9C%80%E6%B1%82-%E5%BB%BA%E8%AD%B0%E4%BD%BF%E7%94%A8-%E8%A6%81%E6%9C%80%E7%A9%A9%E3%80%81%E9%96%8B%E7%99%BC%E8%88%87%E9%83%A8%E7%BD%B2%E5%85%BC%E9%A1%A7-"><thead><tr><th>需求</th><th>建議使用</th></tr></thead><tbody><tr><td>要最穩、開發與部署兼顧</td><td>`20.19.3` 或 `20.19.3-bookworm`</td></tr><tr><td>部署在 Docker，但想減少容量</td><td>`20.19.3-slim` 或 `20.19.3-bookworm-slim`</td></tr><tr><td>專案熟悉 Alpine、對大小敏感</td><td>`20.19.3-alpine`（但需額外測試）</td></tr><tr><td>你想明確指定環境版本以便重建一致性</td><td>`20.19.3-bullseye` / `bookworm` / `alpine3.22` 等有版本號的更佳</td></tr></tbody></table>

---

## 📌 附加提醒

- 有些 Node 原生模組（如 `bcrypt`, `sharp`, `canvas`）在 `alpine` 上常常會遇到編譯問題。
- `slim` 不代表最小，只是比完整版小；真正小的是 `alpine`。
- 不同 tag 最安全的選法是「**明確指定版本與 base image**」，可確保可重現性。

---