文|Seraph
01 | 容器生態環境概覽
- 安裝(Ubuntu)
- 安裝docker依賴包:
apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
- 添加docker的官方GPG祕鑰:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
- 將docker源(穩定版本)添加到
/etc/apt/sources.llist
:add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
- 更新apt包引用:
apt-get update
- 安裝Docker Engine-Community 和 containerd :
apt-get install docker-ce docker-ce-cli containerd.io
-
由於Docker Hub在國外,下載鏡像會比較慢,DaoCloud提供國內鏡像服務。
註冊賬戶並登陸後,點擊右上角的小火箭打開加速器
拷貝下面的鏈接在相應的系統下執行即可。
然後使用systemctl restart docker.service
重啓Docker deamon。 -
基本docker命令
命令 | 含義 |
---|---|
docker run | 運行容器 |
docker pull | 拉取鏡像 |
docker images | 查看鏡像 |
docker commit | 提交容器更新至新的鏡像,添加--no-cache 參數表示不是用緩存。 |
docker build | 構建鏡像 |
docker history | 查看鏡像構建歷史 |
docker tag | 給鏡像打標籤 |
docker login | 登錄docker hub |
docker push | 上傳image至docker hub |
docker search | 搜索Docker Hub中的鏡像 |
docker rmi | 刪除Docker Host上的鏡像 |
docker rm | 刪除容器 |
docker ps | 查詢Docker Host上運行的容器,加上-a 查詢所有的容器(包含停止的) |
docker stop | 停止容器 |
docker attch | 直接進入容器啓動命令的終端,不會打開新的終端 |
docker exec | 在容器打開新的終端 |
docker logs | 查看容器輸出 |
docker start | 啓動容器 |
docker restart | 重啓容器 |
docker kill | 終止容器 |
docker pause | 暫停容器 |
docker uppause | 恢復暫停的容器 |
docker create | 創建容器 |
docker info | 查看docker相關信息 |
docker inspect | 查看容器信息 |
docker volume | 查看容器掛載信息 |
docker cp | 容器與host數據拷貝 |
docker top | 查詢容器內運行進程情況 |
docker stats | 監控容器資源使用情況 |
docker save/load | 導出/導入鏡像 |
docker export/import | 導出/導入容器 |
02 | 容器技術
- 容器由共享主機的內核系統,這個是與虛擬機最本質的區別。
容器一般由兩部分組成:應用程序本身、依賴(庫等)。
所以容器可以看成一個個相互隔離的進程。佔用的體積也小。 - 容器最關鍵的特性是:可移植性。解決了不同環境下部署難得問題。
- Docker核心組件
查詢docker運行狀態:systemctl status docker.service
- 修改遠程登陸功能(應用場景應該很低)
- 修改
/etc/systemd/system/multi-user.target.wants/docker.service
文件,在ExecStart
後面添加-H tcp://0.0.0.0
。 - 重啓Docker daemon
systemctl daemon-reload
systemctl restart docker.service
-
Docker鏡像
以Dockerfile構建而來,Dockerfile構建過程中,又是利用docker commit進行構建。 -
docker run命令 = docker pull + 啓動
03 | Docker鏡像
一、 Dockerfile
- 指令
指令 | 含義 |
---|---|
FROM | 指定基礎鏡像 |
MAINTAINER | 設置鏡像作者 |
CMD | 容器啓動時運行指定的命令,只有最有一個CMD會生效,同事CMD會被docker run 之後的參數替換 |
RUN | 運行指定指令 |
COPY | 從build context複製文件到容器中 |
ADD | 與COPY類似,但是src文件爲歸檔文件(tar\zip\tgz等),會被自動解壓 |
ENV | 設置環境變量,環境變量可被後面的指令使用 |
EXPOSE | 指定容器中的進程監聽某個端口 |
VOLUME | 將文件或目錄聲明爲volume |
WORKDIR | 設置工作目錄 |
ENTRYPOINT | 設置容器啓動時運行的命令,只有最後一個會生效,且CMD或docker run值後的運行參數會被當作參數傳遞給ENTRYPOINT |
-
兩種運行格式Shell和Exec格式:
Shell格式(默認調用/bin/sh -c):<instruction> <command>
Exec格式:<instruction> ["executable", "param1", "param2", ...]
-
由於每一層都會創建鏡像層,當有些由於不同時間執行可能受影響的指令,需要和其他執行搭配在一樣進行執行。
比如apt update
,不能單獨佔一行,否則會使用之前的鏡像層。 -
當CMD與ENTRYPOINT配合使用時,CMD提供參數,ENTRYPOINT必須使用Exec格式。
二、原理
- 容器維護的是rootfs(用戶空間),內核空間都是使用主機的Kernel,所以在容器內查詢Kernel,都和主機一樣。
所以當容器本身應用對內核版本有要求的時候,不建議使用容器,推薦使用虛擬機。
三、構建鏡像
-
一般能用官方或者別人創建穩定的鏡像,一定要先用。沒有才考慮自己構建容器。
推薦使用Dockerfile方式構建鏡像,不推薦使用docker commit
方式創建。
由於不能複用,再者使用者也不知道是創建出來的,無法對鏡像進行審計。 -
每執行一條指令,對容器修改後,都會使用類似
docker commit
操作,新建鏡像層。這樣的話,如果其中某個指令執行失敗,也能得到前一個指令執行後構建出來的鏡像。 -
鏡像是分層結構的,同時我們在容器中的修改只會保存在容器層。
Copy-on-Write
添加文件:在容器中創建文件,新文件被添加到容器層。
讀取文件:從容器層往下,再到鏡像層,查找文件。
修改文件:先如讀取文件時一樣查找文件,然後將文件複製到容器層進行修改。
刪除文件:先如讀取文件時一樣查找文件,在容器層中記錄此刪除操作。(實際上不刪除文件)
四、分發鏡像
-
每個repository可以有多個tag,所以當發新版本的時候,可以使用tag管理版本關係。
我們可以把tag看成linux下的鏈接,爲了我們用通用的名字使用特定的版本。
Image的ID是唯一,如果使用docker images查詢ID相同,說明是同一份鏡像,只不過tag不一樣而已。 -
搭建本地Registry
docker run -d -p 5000:5000 -v /myregistry:/var/lib/registry registry:2
repository的完整格式是:[registry-host]:[post]/[username]
,只不過Docker Hub可以省略。
私人庫其實就是在我們機器上啓動一個Registry容器,使用上僅是要加上repostitory完整格式指明是哪個私人庫,其它和訪問Docker Hub一樣。
04 | 容器
一、Run容器
- 當進程退出時(或OOM),Docker會根據
--restart
策略判斷是否要重啓容器。
- 當加
--restart=always
參數時,表示無論容器什麼原因退出,都會重啓容器。 - 當加
--restart==on-failure:3
參數時,表示容器退出非0時,則重啓容器。
- 內存限制
-m
:內存限制--memory-swap
:設置內存+swap的使用限制-vm
:啓動內存工作線程數-vm-bytes
:每個線程分配內存數
- CPU限制
-c
:CPU優先級,數字越大,佔比越高。--cpu
:CPU數量
- block IO帶寬限額
--blkio-weight
:block IO權重。--device-read-bps
:限制讀某個設備的bps--device-write-bps
:限制寫某個設備的bps--device-read-iops
:限制讀某個設備的iops--device-write-iops
:限制寫某個設備的iops
其中bps
表示每秒讀取多少byte。
iops
表示每秒IO的次數。
測試例子:
<1> 創建限制寫/dev/sda的速率30M/s:docker run -it --device-write-bps /dev/sda:30MB ubuntu
。
<2> 在容器中運行dd測試:time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct
。
progrium/stress
壓力測試鏡像。
二、刪除容器
- 刪除所有停止的容器
docker rm -v $(docker ps -qf status=exited)
。
三、實現容器的底層技術
-
cgroup實現資源限額。
cgroup的主目錄爲:/sys/fs/cgroup
。
按cpu、memory、blkio等區分的多個子目錄:
每個容器的限額會在相應的子目錄下的docker目錄下新建一個以容器ID爲名的目錄。其中保存着該容器的限額信息。 -
namespace實現資源隔離。
隔離的資源有:Mount、UTS(hostname)、IPC(共享內存和信號量)、PID、Network、User。
04 | Docker網絡
Docker容器安裝時會自動在host上新建三個網絡,用docker network ls
可以查詢到。
docker網絡run參數:--network
。
一、 none網絡
none網絡表示在這個網絡下的容器除了lo外,沒有其他任何網卡。適用於需要網絡隔離的場景
二、host 網絡
host網絡表示共享Docker host的網絡棧。
使用host網絡的有點是網絡性能最好。但因爲是和host共享網絡棧,所以需要避免端口衝突。
三、bridge網絡
Docker安裝時會創建一個命名爲docker0的linux bridge。我們新建的容器默認網絡模式爲bridge,所以會掛載到docker0上。不過虛擬網卡是成對的,一個在host上,與docker0連接;一個在容器內。
- 通過
docker network inspect bridge
命令可以查看網橋設置。 brctl show
查看網橋信息。
四、user-defined網絡
- 可以使用
docker network create
創建網絡
--driver
:網絡驅動,bridge、overlay和macvlan。--subnet
:指定子網。--gateway
:指定網關。--ip
:指定ip(前提已經使用–subnet指定了子網)
eg.docker network create --driver bridge --subnet 172.22.16.0/24 --gatway 172.22.16.1 my_net2
。
- 使用
docker network connect
可以給容器添加網絡。
建立在同一個網絡上的容器才能IP通信,所以當兩個容器需要IP通信時,可以讓其中一個容器添加另一個容器的網絡即可。
五、容器間通信
容器間可通過IP、Docker DNS Server或joined容器三種方式通信。
- 建立在同一個網絡上的容器即能IP通信。但是僅能通過靜態IP。
- Docker DNS Server通信,可以給容器主機命名,通過對方的主機名與在一個user-defined網絡(其它網絡不行)上進行通信。
- joined容器,我們可以通過joined容器的形式與容器共享網絡棧:
docker run -it --network=container:容器名
。
六、與外部網絡連接
- 我們默認以bridge模式建立的容器是能與外部網絡連接的。其主要是docker0通過NAT方式與外部連接。
- 外部網絡訪問容器,通常是根據容器映射到host上的端口。
每一個映射的端口,host都會啓動一個docker-proxy進程來處理。
06 | Docker 存儲
一、storage driver
- storage driver實現了多層數據的堆疊。docker支持多種storage driver實現,優先使用系統本身默認的storage driver,這個樣穩定性更好。
二、Data Volume
對於需要持久化的數據(即使容器刪除,數據也保留),需要使用Data Volume來處理。
有兩種方式:bind mount、docker managed volume。
- bind mount
- 使用方式:在docker run加入
-v <host path>:<container path>[:讀寫屬性]
即可。
其實就是目錄映射。 - Data Volume默認是可讀可寫,可以指定添加
:ro
只讀 - 缺點:需要指定目錄,移植後如發現host沒有指定目錄會出錯。
- docker managed volume
- 使用方式:在docker run加入
-v <container path>
即可。docker會爲容器自動生成host共享目錄。 - 當移植時,不會自動打包數據,只會生成相應的掛載目錄。
- 另一種數據共享方式:volume container
volume container的意識是專門爲其它容器提供volume,其容器只需被create就行,不用run。
- 新建volume容器示例:
docker create --name vc_data -v ~/htdocs:/usr/local/apache2/htdocs -v /other/useful/tools busybox
。 - 其它容器使用volume容器示例:
docker run --name web1 -d -p 80 --volumes-from vc_data httpd
。
- 在Dockerfile文件中使用VOLUME、ADD添加共享文件或volume。(自包含的)
- volume刪除
- 刪除容器是加上
-v
參數可以將容器使用到的volume也刪除,但前提是沒有其它容器也使用了。 - 可以使用
docker volume ls
查詢volume的情況。如果刪除容器時,沒有加-v
參數,docker volume ls
還是能查找volume存在的。
如要繼續刪除,可以使用docker volume rm
。 - 刪除所有孤兒volume指令:
docker volume rm $(docker volume ls -1)
。
07 | 多主機管理
docker machine,目前沒有實際環境,後面再試。
99 | 問題解決
- 在ubuntu下使用
--memory-swap
會彈出Your kernel does not support swap limit capabilities or the cgroup is not mounted. Memory limited without swap.
解決:嘗試在aliyun服務器改動過配置文件,然後服務器就起不來了。。。。