Docker如何安全地停止和刪除容器

 前言

上一篇文章講瞭容器的運行啟動:【Docker 那些事兒】如何安全地進入到容器內部

本篇文章將繼續承接上一篇,講講如何 停止、刪除容器對容器進行資源限制

1. 停止和刪除容器

🍑 停止容器

在工作中,有時會需要將容器暫停,例如,要為容器文件系統做一個快照時。使用 docker pausedocker unpause 命令可以對容器進行暫停與激活操作,並且暫停狀態的容器不會占用宿主機 CPU 資源。

當不再需要業務運行時,就要將容器關閉,這時可以使用 docker stop 命令。當遇到特殊情況而無法關閉容器時,還可以使用 docker kill 命令強制終止容器,

示例代碼如下:

以上示例使用 docker kill 命令強制終止瞭容器。

企業中通常有大量的容器需要操作,一個一個操作會浪費大量的人力及時間成本。在這種情況下,可以將 Docker 命令與正則表達式結合起來,實現對容器的批量操作。

首先查看運行狀態容器的 ID 號,示例代碼如下:

接著使用 正則表達式 根據運行狀態容器的 ID 號關閉正在運行的容器,示例代碼如下:

以上示例運用 docker stop 命令與正則表達式批量終止瞭運行中的容器,該命令還有另一種編寫方式,示例代碼如下:

另外,使用類似方法還可以對容器進行批量刪除、啟動等操作。

docker stop 與 docker kill 的區別如下👇

  • docker stop 執行時,首先給容器發送一個TERM信號,讓容器做一些退出前必須做的保護性、安全性操作,然後讓容器自動停止運行,如果在一段時間內容器沒有停止運行,再執行 kill -9 指令,強制終止容器。
  • docker kill 執行時,不論容器是什麼狀態,在運行什麼程序,直接執行 kill -9 指令,強制終止容器。

🍑 刪除容器

容器以其輕量級的特點受人歡迎,通常一些容器使用不久就會閑置,長期積累會導致不必要的資源浪費,所以要及時清理無用的容器。

docker rmi 命令不同,docker rm 命令用於刪除容器,下面將介紹刪除容器的幾種方法。

🍇 刪除容器方法一

首先,查看所有容器及其狀態,示例代碼如下:

從以上示例中可以看到,目前宿主機中有三個處於終止狀態的容器,以及一個處於運行狀態的容器。

然後,結合正則與 docker rm 命令列出處於終止狀態的容器並進行刪除,示例代碼如下:

以上示例使用 docker rm 命令結合正則表達式實現瞭批量刪除容器,並回顯刪除的容器 ID

最後,查看並確認容器已刪除,示例代碼如下:

從示例中可以看到,處於終止狀態的容器已經被刪除,運行狀態的容器並沒有被刪除。

🍇 刪除容器方法二

首先,查看所有容器及其狀態,示例代碼如下:

從以上示例中可以看到,宿主機中有三個處於終止狀態的容器,以及一個處於運行狀態的容器。

接著,使用 docker rm 命令結合正則表達式列出所有容器 ID 號並刪除容器,示例代碼如下:

從以上示例中可以看到,命令的執行時發生瞭報錯,提示無法刪除一個正在運行的容器,可以使用 -f 參數強制執行。

然後,查看當前容器狀態,示例代碼如下:

上述示例中可以看到,docker rm 命令結合正則表達式刪除瞭三個終止狀態的容器,運行中的容器沒有被刪除。
最後,根據報錯提示在命令中添加一個 -f 參數,表示強制刪除,示例代碼如下:

從以上示例中可以看到,處於運行狀態中的容器已經被刪除。

🍇 刪除容器方法三

首先,查看當前容器及其狀態,示例代碼如下:

接著,使用 docker rm 命令結合 docker ps -q -f status=exited 命名篩選出處於終止狀態的容器 ID 號,並刪除容器,

示例代碼如下:

上述示例中,命令已經執行成功。

最後,查看容器是否被刪除,示例代碼如下:

上述示例中可以看到,處於終止狀態的容器都已經被刪除。

🍇 刪除容器方法四

Docker1.13 版本開始,用戶可以使用 docker container prune 命令刪除處於終止狀態的容器。

首先,查看當前容器及其狀態,示例代碼如下:

接著,使用命令開始刪除所有處於終止狀態的容器,示例代碼如下:

從以上示例中可以看到,當 docker container prune 命令執行之後,系統會向用戶發出警告信息,並詢問是否要繼續。

docker container prune 會直接刪除所有處於終止狀態的容器,為瞭防止用戶的誤操作,將有用的容器刪除,命令執行時會有警告信息與詢問信息。

這時,如果確認要刪除,可輸入 “y” ,否則,輸入 “n” 即可阻止命令執行。示例刪除瞭所有處於終止狀態的容器,命令執行成功之後返回一個釋放內存的值。

最後,查看當前容器及其狀態,示例代碼如下:

從以上示例中可以看到,處於終止狀態的容器已經被刪除,而處於運行狀態的容器並沒有受到影響。

2. 容器資源限制

在默認情況下,Docker 沒有對容器進行硬件資源的限制。使用 Dcoker 運行容器時,一臺主機上可能會運行成百上千個容器,這些容器雖然相互隔離,但是在底層使用著相同的 CPU內存磁盤 等資源。

如果不對容器使用的資源進行限制,那麼容器對宿主機資源的消耗可能導致其他容器或進程不能夠正常運行,嚴重時可能導致服務完全不可用。

本節將介紹如何對容器配置 CPU內存Block IO 等資源的限制。

🍑 限制容器內存資源

Linux 服務器上,如果內核檢測到沒有足夠的內存(Memory)來執行重要的系統功能,內核會提示OOME(Out of Memory Error,內存溢出)並開始終止進程以釋放內存,這稱為 OOM 操作。

任何進程都有可能被終止,包括 Docker 和其他重要的應用程序。如果終止瞭系統關鍵進程,可能導致整個系統癱瘓。

設置限制內存上限雖然能保護主機,但是也可能會導致容器裡的服務運行不暢。如果為服務設置的內存上限太小,服務在正常工作時可能出現資源不足;

如果設置過大,則會因為調度器算法浪費內存。因此,合理的做法是遵循以下原則。

  • 為應用做內存壓力測試,瞭解正常業務需求下內存的使用情況,然後再進入生產環境。
  • 限制容器的內存使用上限。
  • 盡量保持主機的資源充足,一旦通過監控發現資源不足,就進行擴容或者對容器進行遷移。
  • 內存資源充足的情況下,盡量不要使用 Swap(交換分區),Swap 的使用會導致內存計算變得復雜,對調度器造成壓力。

下面介紹Docker啟動參數中的內存限制參數。

-m--memory

設置容器可使用的最大內存,最小值是4MB。

--memory-swap

設置容器可使用內存+Swap的最大值。

--memory-swapiness

默認情況下,用戶可以設置一個0~100的值,代表允許內存與交換分區置換的比例。

--memory-reservation

設置一個內存使用的 soft limit(非強制性限制),如果 Docker 發現主機內存不足,會執行 OOM 操作。這個值必須小於 –memory 設置的值。

--kernel-memory

容器能夠使用的內核內存的大小,最小值為 4MB

--oom-kill-disable

設置是否在運行 OOM 時候終止容器進程。
宿主機會在內存不足時,隨機關閉一些進程,而該參數會保護容器進程不被關閉。隻有通過設置 -memory 限制容器內存,才可以使用該參數,否則容器會耗盡主機內存,而且導致主機應用被終止。

註:--memory-swap 隻有在設置瞭 -memory 時才有意義。
 使用 Swap 允許容器在耗盡所有可用的內存時,將多餘的內存需求寫入磁盤。兩者的關系如表所示。

以上兩個參數默認值都為 -1,即對容器使用 內存Swap 沒有限制。

下面使用 progrium/stress 鏡像來介紹如何為容器分配內存,該容器可以模擬進行壓力測試。

示例代碼如下:

以上示例運行瞭一個容器,分配可用最大內存為 300MB,可用 Swap100MB

其中,–vm 1 參數表示啟動一個內存工作線程
–vm-bytes 280M 參數表示每個線程分配 280MB 內存。
可以看到系統不斷地給容器分配內存、釋放內存,一直循環。由於使用的內存 380MB,在最大使用量(400MB)之內,容器正常運行。

下面測試內存使用超出限額的情況,實例代碼如下:

從以上示例中可以看到,容器使用的內存超過瞭限額,容器裡的進程被終止掉瞭,其中,signal 9 就是終止進程信號,最後容器退出。

如果在創建容器時僅指定 -m 參數,不設置 -memory-swap 參數,那麼 -memory-swap 默認是 -m 的兩倍,

示例代碼如下:

在以上示例中,容器最多使用 100MB 內存和 100MB Swap

🍑 限制容器CPU資源

主機上的進程會通過時間分片機制使用 CPUCPU 用頻率來量化,也就是每秒執行的運算次數。為容器限制 CPU 資源並不是改變 CPU 的頻率,而是改變每個容器能使用的 CPU 時間片。

理想狀態下,CPU 應該一直處於運算狀態,並且進程的計算量不會超過 CPU 的處理能力。

Docker 允許用戶為每個容器設置一個數字,代表容器的 CPU share(共享),默認情況下每個容器的 share 值是 1000。這個 share 值是相對的,本身並不能代表任何確定的意義。當主機上有多個容器運行時,每個容器占用的 CPU 時間比例為它的 share 值在總額中的比例。

例如,主機上有兩個一直使用 CPU 的容器(為瞭方便理解,不考慮主機上運行的其他進程),其 CPU share 都為 1000,那麼兩個容器 CPU 使用率都是 50%

如果把其中一個容器的 share 值設置為 500,那麼兩者 CPU 的使用比為 2:1;如果刪除 share 值為 1000 的容器,剩下來容器的 CPU 使用率將會是 100%

Docker 為容器設置 CPU 資源限制的參數是 -c–cpu-shares,其值是一個整數。運行兩個容器 test01test02,並設置 CPU 權重,

示例代碼如下:

以上示例中分別為 test01test02 設置 CPU share10002000

接著,使用 docker stats 查看容器占用 CPU 情況,示例代碼如下:

從以上示例中可以看到,兩個容器 CPU 的使用占比約為 2:1,與先前設置的 share 值相吻合。

此時將 share 值為 2000 的 test02 容器暫停,再來查看 CPU 使用情況,示例代碼如下:

設置 CPU 資源限制還可以使用 –cpuset-cpus 參數,它能夠指定容器使用某一顆 CPU。這裡使用 CPU 測試鏡像 agileek/cpuset-test 進行測試,其功能是將 CPU 用滿,

示例代碼如下:

使用宿主機 top 命令查看 CPU 使用情況,可以看到 CPU1 已經被占滿,而 CPU0 沒有受到影響,如圖所示:

🍑 限制容器 Block IO

Block IO 表示磁盤的讀寫,Docker 可以用配置 bps(每秒讀寫的數據量)和 iops(每秒讀寫的次數)的方式限制容器對磁盤讀寫的帶寬。

下面介紹限制 bps 與 iops 的參數。

--device-read-bps

限制讀某個設備的bps。

--device-write-bps

限制寫某個設備的bps。

--device-read-iops

限制讀某個設備的iops。

--device-write-iops

限制寫某個設備的iops。

默認情況下,所有容器對磁盤讀寫的帶寬是相同的,通過配置 -blkio-weight 參數的值(10-1000)可以指定容器 Block IO 的優先級。–blkio-weight-cpu-shares 類似,默認值都是 500

下面運行的兩個容器 test01test02,其中,test01 讀寫磁盤的帶寬是 test02 的兩倍。

從以上示例中可以看到,容器 test01 的相對權重值是 800,而 test02 的相對權重值是 400,故 test01 讀寫磁盤的帶寬是 test02 的兩倍。

下面運行一個容器,限制其對 /dev/sda 寫入的速率不高於 20MB/s。因為容器文件系統在宿主機的 /dev/sda 上,在容器中寫文件相當於對宿主機的 /dev/sda 進行寫入操作。

示例代碼如下:

以上示例運行瞭一個 CentOS 容器,並限制其寫 /dev/sda 的速率為 20MB/s

下面通過命令查看該容器的寫入速率,示例代碼如下:

從以上示例中可以看到,設置瞭寫入限制的容器,寫入速率為 19.4MB/s,沒有超過寫入限制的 20MB/s

作為對比,下面運行一個不限制寫入速率的容器,示例代碼如下:

以上示例中,一個不限制讀寫速率的容器,寫入速率是 61.3MB/s

3. 總結

這兩篇文章,首先介紹瞭如何獲取 Docker 幫助手冊;然後通過大量的實驗講解瞭操作 Docker 容器的方法,包括進入、停止、刪除容器等,以及容器各種狀態之間如何轉換;
最後介紹瞭 Docker 容器的資源限制,包括 限制內存CPUBLOCK IO 三種方法。

到此這篇關於Docker如何安全地停止和刪除容器的文章就介紹到這瞭,更多相關Docker 停止刪除容器內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀:

    None Found