docker學習-docker容器運行

docker run是啓動容器的方法,可以用三種指定的方式指定容器啓動時執行的命令。
(1)CMD指令
(2)ENTRYPOINT指令
(3)在docker run中命令行中指定
但是docker run並不能長期保持running狀態,我們經常需要進入到容器中去做一些工作,比如查看日誌、調試、啓動其他進程等。有兩種進入容器的方式:attach和exec。

docker attach

首先啓動一個容器,保持後臺長期運行

docker run -d ubuntu /bin/bash -c "while true; do sleep 1; echo i_am_a_container;done

首先檢查容器的ID

docker ps -a

docker學習-docker容器運行

CONTAINER ID就是容器的編號,其實就是容器ID前12個字符,又叫短ID
IMAGE就是base IMAGE
NAMES是容器的名稱,在啓動容器的時候可以通過 --name參數顯式的爲容器命名。

通過docker attach可以attach到容器啓動命令的終端。

docker attach 1e5cc7e3b22b 

docker學習-docker容器運行
通過短ID attach到了容器的啓動命令終端,之後看到的是echo每秒輸出一次打印信息
可以通過ctl+p,然後ctl+q退出attach終端

docker exec

通過docker exec進入相同的容器

docker exec -it 1e5cc7e3b22b bash

docker學習-docker容器運行
說明
1、-it 以交互的形式打開終端,執行bash
2、可以像普通linux一樣執行命令,顯示了容器啓動的進程
3、退出容器

docker exec命令格式如下:

docker exec -it <container> bash |sh

attach vs exec

兩者的主要區別如下:
1、attch直接進入容器啓動命令的終端,不會啓動新的進程
2、exec則是在容器中打開新的終端,而且可以啓動新進程
3、如果想直接在終端中查看啓動命令的輸出,用attach,其他情況用exec

運行容器的最佳實踐

按用途容器大致可以分爲兩類:服務類容器和工具的容器
前者以daemon的形式運行,對外提供服務,比如Web Server、數據庫等。通過-d 以後臺的方式啓動這類容器是非常合適的,如果要排查問題,可以通過exec -it進入容器
後者容器通常能給我們提供一個臨時的工作環境,通常以run -it方式進行

工具類容器多使用基礎鏡像,例如busybox,debian,ubuntu等

總結如下:

(1)當CMD,Entypoint和docker run命令行指定的命令運行結束時,容器停止
(2)通過-d參數在後臺啓動容器
(3)通過exec -it可以進入容器並執行命令

容器生命週期

stop/start/restart容器

docker stop:停止運行中的容器,容器在docker host中其實就是一個進程,該命令本質上是像該進程發送一個SIGTERM信號,也可通過docker kill命令快速停止容器

docker start: 對於停止的容器。可以通過該命令進行啓動,會保留容器的第一次啓動時的參數

docker restart :重啓容器

pause/unpause容器

docker pause:讓容器暫停,如需要對容器的文件系統打快照
unpause:處於pause狀態的容器不會佔用CPU資源,直到通過dokcer unpause恢復運行

刪除容器

docker rm:使用docker一段時間後,host上可能會有大量已經退出的容器,這些容器依然會佔用host的文件系統資源,可以使用docker rm進行刪除
如果希望一次刪除多個容器,則可以使用如下命令

docker rm -v $(docker ps -aq -f status=exited)

容器的狀態機制

整個容器的生命週期狀態機制,如下所示:
docker學習-docker容器運行

資源限制

一個docker host上會運行若干容器,每個容器都需要cpu,內存和IO資源。Docker提供了類似的機制避免某個容器因佔用太多資源而影響到其他容器或者整個HOST的資源

內存限額

與操作系統類似,容器可使用的內存包括兩個部分:物理內存和swap。Docker通過下面的兩組參數來控制容器內存的使用量
(1)-m或 --memory:設置內存的使用限制
(2)--memory-swap:設置內存+swap的使用限制
例如:
docker run -m 200M --memory-swap=300M ubuntu
含義時允許該容器最多使用200M的內存和300MB的 swap。默認情況下,上面兩組參數爲-l,即對容器內存和swap的使用沒有限制

測試使用progrium/stress鏡像,該鏡像可以用於對容器執行壓力測試

docker run -it -m 200M --memory-swap=300M progrium/stress --vm 1 --vm-bytes 280M

說明:
1、--vm1:啓動1個內存工作線程
2、--vm-bytes 280M,每個線程分配280MB內存
docker學習-docker容器運行
過程:
1分配280M內存
2釋放280M內存
3再分配280M內存
4再釋放
5 一致持續循環

cpu限制

默認設置下,所有的容器可以平等的使用hostCPU資源,而且沒有限制
docker可以通過-c或者--cpu-shares設置容器使用cpu的權重,如果不指定,默認值1024
與內存限額不同,通過-c設置的cpu share並不是cpu資源的絕對數量,而是一個相對的權重值。某個容器最終能分配的到的CPU資源取決於它的cpu share總和和比例,換句話說通過cpu share可以設置容器使用CPU的優先級

docker run --name "container_A" -c 1024 ubuntu && docker run --name "container_B" -c 512 ubuntu

container_A的cpu share 1024,是containerB的兩倍,當兩個容器都需要CPU資源時,前者可以得到的cpu是後者的兩倍

需要特別注意的是,這種按權重分配CPU的只會發生在CPU資源緊張的情況下。如果containerA處於空閒狀態,這時爲了充分利用CPU資源,containrB也可以分配到全部可用的cpu

Block IO帶寬限制

Block IO是另一種可以限制容器資源,它是指磁盤的讀寫,docker可以通過設置權重,限制bsp和iops的方式控制容器讀寫磁盤的帶寬。

IO權重
默認情況下,所有的容器能平等的讀寫磁盤,可以通過設置 --blkio-weight 參數來改變容器的block IO的優先級
--blkio-weight與--cpu-share類似,設置的是相對權重,默認爲500

docker run -it --name container_A --blkio-weight 600 ubuntu && docker run --it --name container_B --blkio-weight 300 ubuntu

通過命令行設定,containerA的讀寫磁盤帶寬是containerB的兩倍

限制bps和iops

bsp是byte per second ,每秒讀寫的數據量
iops是ip per second,每秒IO的次數

可以通過以下參數控制容器的bsp和 iops
--device-read-bps,限制讀某個設備的 bps。
--device-write-bps,限制寫某個設備的 bps。
--device-read-iops,限制讀某個設備的 iops。
--device-write-iops,限制寫某個設備的 iops。

cgroup和namespace

cgropu和namespace是實現容器底層的最重要的兩種技術。cgroup實現資源限制,namespace實現資源的隔離

cgroup

cgroup 全稱 Control Group。Linux 操作系統通過 cgroup 可以設置進程使用 CPU、內存 和 IO 資源的限額。前面我們看到的--cpu-shares、-m、--device-write-bps 實際上就是在配置 cgroup。
可以在/sys/fs/cgroup中找到

docker run -it --cpu-shares 512 progrium/stress -c 1

記錄容器ID。在 /sys/fs/cgrouXXXpu/docker 目錄中,Linux 會爲每個容器創建一個 cgroup 目錄,以容器長ID 命名:
docker學習-docker容器運行
目錄中包含所有與 cpu 相關的 cgroup 配置,文件 cpu.shares 保存的就是 --cpu-shares 的配置,值爲 512。
同樣的,/sys/fs/cgroup/memory/docker 和 /sys/fs/cgroup/blkio/docker 中保存的是內存以及 Block IO 的 cgroup 配置

namespace

在每個容器中,我們都可以看到文件系統,網卡等資源,這些資源看上去是容器自己的。拿網卡來說,每個容器都會認爲自己有一塊獨立的網卡,即使 host 上只有一塊物理網卡。這種方式非常好,它使得容器更像一個獨立的計算機。

Linux 實現這種方式的技術是 namespace。namespace 管理着 host 中全局唯一的資源,並可以讓每個容器都覺得只有自己在使用它。換句話說,namespace 實現了容器間資源的隔離。
Linux 使用了六種 namespace,分別對應六種資源:Mount、UTS、I*、PID、Network 和 User。

Mount namespace
Mount namespace 讓容器看上去擁有整個文件系統。

容器有自己的 / 目錄,可以執行 mount 和 umount 命令。當然我們知道這些操作只在當前容器中生效,不會影響到 host 和其他容器。
UTS namespace
簡單的說,UTS namespace 讓容器有自己的 hostname。 默認情況下,容器的 hostname 是它的短ID,可以通過 -h 或 --hostname 參數設置。

I P C namespace
IPC namespace 讓容器擁有自己的共享內存和信號量(semaphore)來實現進程間通信,而不會與 host 和其他容器的 IPC 混在一起。

PID namespace
能夠使容器能夠擁有自己的PID
Network namespace
Network namespace 讓容器擁有自己獨立的網卡、IP、路由等資源。我們會在後面網絡章節詳細討論。

User namespace
User namespace 讓容器能夠管理自己的用戶,host 不能看到容器中創建的用戶。

常用命令

以下是容器的常用操作命令
create 創建容器
run 運行容器
pause 暫停容器
unpause 取消暫停繼續運行容器
stop 發送 SIGTERM 停止容器
kill 發送 SIGKILL 快速停止容器
start 啓動容器
restart 重啓容器
attach attach 到容器啓動進程的終端
exec 在容器中啓動新進程,通常使用 "-it" 參數
logs 顯示容器啓動進程的控制檯輸出,用 "-f" 持續打印
rm 從磁盤中刪除容器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章