文章目錄 Docker 服務器 Docker 鏡像 Docker 容器 本地 Registry RUN vs CMD vs ENTRYPOINT 限制容器對內存、CPU 和 IO 資源的使用 cgroup 和 namespace cgroup namespac Mount namespace UTS namespace IPC namespace PID namespace Network namespace User namespace
Docker 服務器
systemctl status docker.service:查看 Docker daemon 服務狀態 vim /etc/systemd/system/multi-user.target.wants/docker.service:修改 docker.service 配置 systemctl daemon-reload:重新加載 Docker daemon 配置 systemctl restart docker.service:重啟 Docker daemon 服務 docker -H 192.168.138.132 info:通過命令行與 Docker daemon 通信,查看 Docker 服務器的信息
Docker 鏡像
docker pull httpd:從 Registry 下載鏡像 docker inspect xxxxx:用于查看容器、鏡像、網絡或數據卷的詳細信息 dcoker run hello-world docker run -d -p 8080:80 httpd:先下載鏡像(如果本地沒有),然后再啟動容器。 docker run -it 鏡像名:以交互模式進入容器,并打開終端 docker images [centos][-a]:查看鏡像,-a 會顯示所有中間鏡像 Docker 容器的 ubuntu 鏡像配置 apt 國內源
sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
sed -i s@/security.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
apt-get clean
apt-get update
apt-get install -y vim:安裝 vim,并跳過安裝提示 docker commit wonderful_sa ubuntu_with_vi:將容器保存為鏡像 docker rmi [-f] 容器id:刪除鏡像(先停止容器才能刪除)。如果一個鏡像對應了多個 tag,只有當最后一個 tag 被刪除時,鏡像才被真正刪除。 touch Dockerfile:創建Dockerfile文件 docker build -t ubuntu-with-vi-dockerfile . :運行 docker build 命令,-t 將新鏡像命名為 ubuntu-with-vi-dockerfile,命令末尾的 . 指明 build context 為當前目錄。Docker 默認會從 build context 中查找 Dockerfile 文件,我們也可以通過 -f 參數指定 Dockerfile 的位置。 docker history ubuntu-with-vi-dockerfile:顯示鏡像的構建歷史 docker build -t --no-cache ubuntu-with-vi-dockerfile-2 . 根據當前目錄下的 dockerfile 構建鏡像,不使用緩存 docker tag aaa:latest bbb:1:修改鏡像的REPOSITORY和TAG docker search httpd:搜索 Docker Hub 中的鏡像。
Docker 容器
docker attach:進入容器的啟動命令終端,不會啟動新的進程。如果想直接在終端中查看啟動命令的輸出,用 attach;其他情況使用 exec。 docker exec -it container bash :在容器中打開新的終端,并且可以啟動新的進程。 docker logs -f container:如果只是為了查看啟動命令的輸出,可以使用 docker logs 命令。-f 的作用與 tail -f 類似,能夠持續打印輸出。 docker ps -a/ docker container ls -a:查看正在運行的容器,-a 會顯示所有狀態的容器。 ctrl + p + q :退出容器 docker run hello-world docker run -d -p 8080:80 httpd:先下載鏡像(如果本地沒有),然后再啟動容器。服務類容器通過 -d 以后臺方式啟動是非常合適的。 docker run -it 鏡像名:以交互模式進入容器,并打開終端。退出 Shell(輸入 exit 或 Ctrl+D):主進程(bash)終止 → 容器停止。若你不退出 Shell:容器會保持運行(因為主進程未終止)。工具類容器通常給能我們提供一個臨時的工作環境,通常以 run -it 方式運行。工具類容器多使用基礎鏡像,例如 busybox、debian、ubuntu 等。 docker run --name my_nginx_container nginx:–name 參數顯示地為容器命名,如果不指定,docker 會自動為容器分配名字。 docker run -d \ –name mysql-container \ -e MYSQL_ROOT_PASSWORD=my-secret-pw \ -p 3306:3306 \ -v /path/on/host:/var/lib/mysql \ mysql:latest docker run -d --restart=always httpd:無論容器因何種原因退出(包括正常退出),就立即重啟。 只有當容器的啟動進程退出時,–restart 才生效。 如果容器是因為執行 docker stop 或docker kill 退出,則不會自動重啟。 docker stop/kill 鏡像名:停止容器。kill 會快速停止容器。 docker create mysql-container:創建的容器處于 Created 狀態。docker run 命令實際上是 docker create 和 docker start 的組合。 docker start/restart mysql-container:重新啟動容器。 docker pause/unpause mysql-container:暫停容器/恢復運行容器。 docker rm container1 container2 container3:刪除容器。 docker rm -v $(docker ps -aq -f status=exited):批量刪除所有已經退出的容器。
本地 Registry
docker run -d -p 5000:5000 -v /myregistry:/var/lib/registry registry:2:-d 是后臺啟動容器。-p 將容器的 5000 端口映射到 Host 的 5000 端口。5000 是 registry 服務端口。-v 將容器 /var/lib/registry 目錄映射到 Host 的 /myregistry,用于存放鏡像數據。 docker tag hanfei/httpd:1 ubuntu:5000/hanfei/httpd:1:repository 的完整格式為:[registry-host]:[port]/[username]/xxx。只有 Docker Hub 上的鏡像可以省略 [registry-host]:[port] 。在 Docker 主機上,可以使用 hostname 命令查看主機的名稱。
RUN vs CMD vs ENTRYPOINT
RUN
RUN 指令通常用于安裝應用和軟件包,構建鏡像 。RUN 有兩種格式:
(1)Shell 格式:
RUN [ "apt-get" , "install" , "python3" ]
(2)Exec 格式:
RUN apt-get install python3
RUN apt-get update && apt-get install -y \ bzr \ cvs \ git \ mercurial \ subversion
CMD
CMD 指令通常用于設置容器啟動后默認執行的命令及其參數。 CMD 能夠被 docker run 后面跟的命令行參數替換。如果 Dockerfile 中有多個 CMD 指令,只有最后一個 CMD 有效。 推薦使用 Exec 格式,因為指令可讀性更強,更容易理解。
(1)Exec 格式:
CMD [ "executable" ,"param1" ,"param2" ]
(2)CMD [ "param1" ,"param2" ] 為 ENTRYPOINT 提供額外的參數,此時 ENTRYPOINT 必須使用 Exec 格式。
CMD [ "world" ]
(3)Shell 格式(不推薦)
ENTRYPOINT
ENTRYPOINT 配置容器啟動時運行的命令。讓容器以應用程序或者服務的形式運行。 ENTRYPOINT 看上去與 CMD 很像,它們都可以指定要執行的命令及其參數。不同的地方在于 ENTRYPOINT 不會被忽略,一定會被執行,即使運行 docker run 時指定了其他命令。 推薦使用 Exec 格式,因為指令可讀性更強,更容易理解。
(1)使用 Exec 格式的 ENTRYPOINT 指令。CMD 可為 ENTRYPOINT 提供額外的默認參數,同時可利用 docker run 命令行替換默認參數。
ENTRYPOINT [ "/bin/echo" , "Hello" ]
CMD [ "world" ]
(2)Shell 格式(不推薦)
ENTRYPOINT 的 Shell 格式會忽略任何 CMD 或 docker run 提供的參數。
限制容器對內存、CPU 和 IO 資源的使用
內存
docker run -m 200M --memory-swap= 300M ubuntu
docker run -it -m 200M --memory-swap= 300M progrium/stress --vm 1 --vm-bytes 280M
CPU
通過 -c 或 --cpu-shares 設置容器使用 CPU 的權重。如果不指定,默認值為 1024。 通過 -c 設置的 cpu share 并不是 CPU 資源的絕對數量,而是一個相對的權重值。某個容器最終能分配到的 CPU 資源取決于它的 cpu share 占所有容器 cpu share 總和的比例。換句話說:通過 cpu share 可以設置容器使用 CPU 的優先級。 權重分配 CPU 只會發生在 CPU 資源緊張的情況下。如果 container_A 處于空閑狀態,這時,為了充分利用 CPU 資源,container_B 也可以分配到全部可用的 CPU。
docker run --name "container_A" -c 1024 ubuntu
docker run --name "container_B" -c 512 ubuntu
Block IO
Block IO 指的是磁盤的讀寫,docker 可通過設置權重、限制 bps 和 iops 的方式控制容器讀寫磁盤的帶寬。目前 Block IO 限額只對 direct IO(不使用文件緩存)有效。
設置權重
默認情況下,所有容器能平等地讀寫磁盤,可以通過設置 --blkio-weight 參數來改變容器 block IO 的優先級,設置的是相對權重值,默認為 500。
docker run -it --name container_A --blkio-weight 600 ubuntu
docker run -it --name container_B --blkio-weight 300 ubuntu
bps 和 iops
bps 是 byte per second,每秒讀寫的數據量。 iops 是 io per second,每秒 IO 的次數。 –device-read-bps,限制讀某個設備的 bps。 –device-write-bps,限制寫某個設備的 bps。 –device-read-iops,限制讀某個設備的 iops。 –device-write-iops,限制寫某個設備的 iops。
docker run -it --device-write-bps /dev/sda:30MB ubuntu
time dd if = /dev/zero of = test.out bs = 1M count = 800 oflag = direct
cgroup 和 namespace
cgroup 實現資源限額, namespace 實現資源隔離。
cgroup
cgroup 全稱 Control Group。Linux 操作系統通過 cgroup 可以設置進程使用 CPU、內存 和 IO 資源的限額。–cpu-shares、-m、–device-write-bps 實際上就是在配置 cgroup。 /sys/fs/cgroup/cpu/docker/容器長ID:目錄中包含所有與 cpu 相關的 cgroup 配置。 /sys/fs/cgroup/memory/docker/容器長ID:目錄中包含所有與 memory 相關的 cgroup 配置。 /sys/fs/cgroup/blkio/docker/容器長ID:目錄中包含所有與 blkio 相關的 cgroup 配置。
namespac
在每個容器中,我們都可以看到文件系統,網卡等資源,這些資源看上去是容器自己的。拿網卡來說,每個容器都會認為自己有一塊獨立的網卡,即使 host 上只有一塊物理網卡。這種方式非常好,它使得容器更像一個獨立的計算機。Linux 實現這種方式的技術是 namespace。namespace 管理著 host 中全局唯一的資源,并可以讓每個容器都覺得只有自己在使用它。換句話說,namespace 實現了容器間資源的隔離。Linux 使用了六種 namespace,分別對應六種資源:Mount、UTS、IPC、PID、Network 和 User。
Mount namespace
容器有自己的 / 目錄,可以執行 mount 和 umount 命令。當然我們知道這些操作只在當前容器中生效,不會影響到 host 和其他容器。
1 .你插入了一個 U 盤,系統識別它為 /dev/sdb1。
2 .你執行命令:
mount /dev/sdb1 /mnt
3 .現在,你可以通過 /mnt 訪問 U 盤里的文件了:
ls /mnt
4 .當你用完 U 盤后,可以卸載它。這樣,U 盤就“關門”了,/mnt 目錄下不再顯示 U 盤的內容:
umount /mnt
UTS namespace
讓容器有自己的 hostname。 UTS namespace 為每個Docker容器設置了一個獨立的主機名和域名。這使得每個容器都能夠被視為網絡上的一個獨立節點,從而簡化了應用的訪問和管理,并增強了應用之間的隔離性和安全性。
docker run -h/--hostname myhost -it ubuntu
IPC namespace
IPC namespace 讓容器擁有自己的共享內存和信號量(semaphore)來實現進程間通信,而不會與 host 和其他容器的 IPC 混在一起。
PID namespace
容器在 host 中以進程的形式運行。 容器中進程的 PID 不同于 host 中對應進程的 PID,容器中 PID=1 的進程當然也不是 host 的 init 進程。也就是說:容器擁有自己獨立的一套 PID,這就是 PID namespace 提供的功能。
ps axf
docker exec -it container bash
Network namespace
User namespace
讓容器能夠管理自己的用戶,host 不能看到容器中創建的用戶。