1. 程式人生 > >Docker入門與實踐

Docker入門與實踐

  一、Docker介紹 docker官網:https://www.docker.com/ Docker hub地址: https://hub.docker.com/   1、基本概念 Docker 是一個開源的應用容器引擎,基於 Go 語言   並遵從Apache2.0協議開源。Docker 可以讓開發者打包他們的應用以及依賴包到一個輕量級、可移植的容器中,然後釋出到任何流行的 Linux 機器上,也可以實現虛擬化。容器是完全使用沙箱機制,相互之間不會有任何介面(類似 iPhone 的 app),更重要的是容器效能開銷極低。
  2、 docker的優勢 簡化程式: Docker 讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後釋出到任何流行的  Linux 機器上,便可以實現虛擬化。Docker改變了虛擬化的方式,使開發者可以直接將自己的成果放入Docker中進行管理。方便快捷已經是 Docker的最大優勢,過去需要用數天乃至數週的 任務,在Docker容器的處理下,只需要數秒就能完成。   節省開支: 一方面,雲端計算時代到來,使開發者不必為了追求效果而配置高額的硬體,Docker 改變了高效能必然高價格的思維定勢。Docker 與雲的結合,讓雲空間得到更充分的利用。不僅解決了硬體管理的問題,也改變了虛擬化的方式。
3、與傳統vm特性對比 作為一種輕量級的虛擬化方式,Docker在執行應用上跟傳統的虛擬機器方式相比具有顯著優勢: Docker容器很快,啟動和停止可以在秒級實現,這相比傳統的虛擬機器方式要快得多。 Docker容器對系統資源需求很少,一臺主機上可以同時執行數千個Docker容器。 Docker通過類似Git的操作來方便使用者獲取、分發和更新應用映象,指令簡明,學習成本較低。 Docker通過Dockerfile配置檔案來支援靈活的自動化建立和部署機制,提高工作效率。 Docker容器除了執行其中的應用之外,基本不消耗額外的系統資源,保證應用效能的同時,儘量減小系統開銷。
Docker利用Linux系統上的多種防護機制實現了嚴格可靠的隔離。從1.3版本開始,Docker引入了安全選項和映象簽名機制,極大地提高了使用Docker的安全性。  
特性 容器 虛擬機器
啟動速度 秒級 分鐘級
硬碟使用 一般為MB 一般為GB
效能 接近原生 弱於原生
系統支援量 單機支援上千個容器 一般幾十個
隔離性 安全隔離 完全隔離
   
  1. 基礎架構

 

5、docker的技術基礎   namespace,容器隔離的基礎,保證A容器看不到B容器. 6個名空間:User(使用者及使用者組)【核心3.8以上】,Mnt(檔案系統或掛載點),Network(網路IP、埠等),UTS(主機名和域名),IPC(進訊號量、訊息佇列和共享記憶體,程序通訊),Pid(程序號) cgroups,容器資源統計和隔離。主要用到的cgroups子系統:cpu,blkio(塊裝置IO),devices(裝置訪問),freezer(掛起或恢復任務),memory(記憶體使用量及報告),perf_event(對cgroup中的任務進行統一新年測試),net_cls(cgroup中的任務建立的資料報文的類別識別符號) unionfs,典型:aufs/overlayfs,分層映象實現的基礎   6、docker元件   docker Client客戶端————>向docker伺服器程序發起請求,如:建立、停止、銷燬容器等操作 docker Server伺服器程序—–>處理所有docker的請求,管理所有容器 docker Registry映象倉庫——>映象存放的中央倉庫,可看作是存放二進位制的scm(一般是dockerhub)   7、docker執行過程  

 

  二、 Docker安裝   環境: 1、64位cpu 2、Linux kernel 3.10以上(Centos7以後)  
#1、下載docker-ce的yum源
wget -O /etc/yum.repos.d/docker-ce.repo    https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
sed -i "s#download.docker.com#mirrors.tuna.tsinghua.edu.cn/docker-ce#g" /etc/yum.repos.d/docker-ce.repo
yum makecache
#2、yum下載docker-ce
yum install docker-ce -y 

#3、docker的配置檔案
/etc/docker/daemon.json

#4、啟動docker服務
systemctl  start docker

#5、    下載映象
docker pull busyboxf
#6、    登入docker hub
docker login -u  [賬號]
[[email protected] ~]# docker login  -u [賬號]
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

 

三、、Docker常用命令

-i                                  #以互動模式執行容器,通常與 -t 同時使用;
-t                                  #為容器重新分配一個偽輸入終端,通常與 -i 同時使用;
-d                                  #後臺執行容器,並返回容器ID;
--name="nginx-lb"                   #為容器指定一個名稱;
--dns 8.8.8.8                       #指定容器使用的DNS伺服器,預設和宿主一致;
--dns-search example.com            #指定容器DNS搜尋域名,預設和宿主一致;
-h "mars"                           #指定容器的hostname;
-e username="ritchie"               #設定環境變數;
--env-file=[]                       #從指定檔案讀入環境變數;
--cpuset="0-2" or --cpuset="0,1,2"  #繫結容器到指定CPU執行;
-m                                  #設定容器使用記憶體最大值;
--net="bridge"                      #指定容器的網路連線型別支援bridge/host/none/container:<name|id> 四種類型;
--link=[]                           #新增連結到另一個容器;
--expose=[]                         # 開放一個埠或一組埠
-p                                  #埠對映,格式為:主機(宿主)埠:容器埠
--config=~/.docker                  #客戶端配置檔案的位置
  -D, --debug=false                 #啟用Debug除錯模式
  -H, --host=[]                     #守護程序的套接字(Socket)連線
  -h, --help=false                  #列印使用
  -l, --log-level=info              #設定日誌級別
  -v, --version=false               #列印版本資訊並退出
build                               #通過Dockerfile定製映象
commit                              #提交當前容器為新的映象
cp                                  #從容器中拷貝指定檔案或者目錄到宿主機中或者從宿主機拷貝到容器
create                              #建立一個新的容器,同run 但不啟動容器
diff                                #檢視docker容器變化
events                              #從docker服務獲取容器實時事件
exec                                #在已存在的容器上執行命令
export                              #匯出容器的內容流作為一個tar歸檔檔案(對應import)
history                             #展示一個映象形成歷史
images                              #列出系統當前映象
import                              #從tar包中的內容建立一個新的檔案系統映像(對應export)
info                                #顯示系統相關資訊
inspect                             #檢視容器詳細資訊
kill                                #kill指定docker容器
load                                #從一個tar包中載入一個映象(對應save)
login                               #登陸docker Hub伺服器
logout                              #從當前Docker registry退出
logs                                #輸出當前容器日誌資訊[-f 是實時檢視]
pause                               #暫停容器
port                                #檢視對映埠對應的容器內部源埠
ps                                  #列出容器列表
pull                                #從docker映象源伺服器拉取指定映象或者庫映象
push                                #上傳指定映象或者庫映象至docker源伺服器
rename                              #重新命名容器
restart                             #重啟執行的容器
rm                                  #移除一個或者多個容器
rmi                                 #移除一個或多個映象(無容器使用該映象才可以刪除,否則需要刪除相關容器才可以繼續或者-f強制刪除)
run                                 #建立一個新的容器並執行一個命令
save                                #儲存一個映象為一個tar包(對應load)
search                              #在dockerhub中搜索映象
start                               #啟動容器
stats                               #統計容器使用資源
stop                                #停止容器
tag                                 #給源中映象打標籤
top                                 #檢視容器中執行的程序資訊
unpause                             #取消暫停容器
version                             #檢視容器版本號
wait                                #擷取容器停止時的退出狀態值

 

四、docker卷儲存(掛載目錄)

Docker的卷掛載有2種方式 1、資料卷:-v /data,-v src:dst 2、資料卷容器:--volumes-from  
1、    書卷 -v 的掛載方式
#將宿主機的/etc目錄掛載到容器的/mnt目錄

[[email protected] ~]# docker run -it -v /etc/:/mnt/  busybox


2、資料卷容器:--volumes-from
##資料卷容器:--volumes-from(複製其它容器的卷)
[[email protected] ~]# docker run -it --name v1 -v /mnt/:/mnt/   busybox
/ # ls /mnt/
logstash-6.2.3.rpm
/ # [[email protected] ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
70bb436cb5d8        busybox             "sh"                9 seconds ago       Up 8 seconds                            v1
[[email protected] ~]# docker run -it --name v2  --volumes-from  v1 busybox
/ # ls /mnt/
logstash-6.2.3.rpm

 

五、docker網路

docker run建立Docker容器時,可以用–net選項指定容器的網路模式,Docker有以下4種網路模式: bridge模式:使用–net =bridge指定,預設設定; host模式:使用–net =host指定; none模式:使用–net =none指定; container模式:使用–net =container:NAMEorID指定。     1、 bridge模式 bridge模式是Docker預設的網路設定,此模式會為每一個容器分配Network Namespace、設定IP等,並將並將一個主機上的Docker容器連線到一個虛擬網橋上。當Docker server啟動時,會在主機上建立一個名為docker0的虛擬網橋,此主機上啟動的Docker容器會連線到這個虛擬網橋上。虛擬網橋的工作方式和物理交換機類似,這樣主機上的所有容器就通過交換機連在了一個二層網路中。接下來就要為容器分配IP了,Docker會從RFC1918所定義的私有IP網段中,選擇一個和宿主機不同的IP地址和子網分配給docker0,連線到docker0的容器就從這個子網中選擇一個未佔用的IP使用。如一般Docker會使用172.17.0.0/16這個網段,並將172.17.42.1/16分配給docker0網橋(在主機上使用ifconfig命令是可以看到docker0的,可以認為它是網橋的管理埠,在宿主機上作為一塊虛擬網絡卡使用)。   2、host模式如果啟動容器的時候使用host模式,那麼這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個Network Namespace。容器將不會虛擬出自己的網絡卡,配置自己的IP等,而是使用宿主機的IP和埠。  使用host模式啟動容器後可以發現,使用ip addr檢視網路環境時,看到的都是宿主機上的資訊。這種方式創建出來的容器,可以看到host上的所有網路裝置。 容器中,對這些裝置有全部的訪問許可權。因此docker提示我們,這種方式是不安全的。如果在隔離良好的環境中(比如租戶的虛擬機器中)使用這種方式,問題不大。   3、none模式在none模式下,Docker容器擁有自己的Network Namespace,但是,並不為Docker容器進行任何網路配置。也就是說,這個Docker容器沒有網絡卡、IP、路由等資訊。需要我們自己為Docker容器新增網絡卡、配置IP等。    4、 container模式 這個模式指定新建立的容器和已經存在的一個容器共享一個Network Namespace,而不是和宿主機共享。新建立的容器不會建立自己的網絡卡,配置自己的IP,而是和一個指定的容器共享IP、埠範圍等。同樣,兩個容器除了網路方面,其他的如檔案系統、程序列表等還是隔離的。兩個容器的程序可以通過lo網絡卡裝置通訊。

 

#1、宿主機埠對映到容器

-P (大寫P)從宿主機的3萬多埠開始對映 (隨機)
docker run -it -P  nginx 
[[email protected]~]#docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
50bb17fcf9dd        nginx               "nginx -g 'daemon of…"   6 seconds ago       Up 5 seconds        0.0.0.0:32768->80/tcp   cranky_zhukovsky
#瀏覽器訪問 宿主機ip:32768


#2、指定對映埠 -p(小p)
docker run -it -p 【宿主機埠】:【容器埠】
docker run -itd -p 80:80 nginx 
[[email protected]~]#docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
ed6f6de58b09        nginx               "nginx -g 'daemon of…"   4 seconds ago       Up 3 seconds        0.0.0.0:80->80/tcp   unruffled_shirley
#瀏覽器訪問 宿主機ip

3、共享網路名稱空間
[[email protected] ~]# docker run -it --name n1 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
48: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ #

[[email protected] ~]# docker run -it --name n2 --network container:n1 busybox
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
48: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever



##測試
/ # hostname
854a346a1ae5
/ # echo 123 > /tmp/index.html
/ # httpd  -h /tmp/
/ # wget -O - -q 127.0.0.1
123

##另一臺
/ # hostname
854a346a1ae5
/ # wget -O - -q 127.0.0.1
123

#4、修改docker0的預設ip
修改配置檔案/etc/docker/daemon.json

例如
systemctl  stop docker

[[email protected] ~]# cat /etc/docker/daemon.json
{
"bip": "192.168.0.1/16"
}
[[email protected] ~]# systemctl  daemon-reload
[[email protected] ~]# systemctl  start docker
[[email protected] ~]# ip a s docker0
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
    link/ether 02:42:8c:10:a3:65 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.1/16 brd 192.168.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:8cff:fe10:a365/64 scope link
       valid_lft forever preferred_lft forever

 

六、構建docker容器的2種方式   1、基於容器建立新的映象
#1、啟動容器並在/tmp下建立index.html檔案,然後退出
[[email protected]~]#docker run -it --name im1 busybox sh
/ # echo 'lalal' >/tmp/index.html 
/ # exit
#2、    建立映象
[[email protected]~]docker commit -p  im1 im1
sha256:ac4415503e78b162e7f03f16f0f0b3aa058ed57237b4315691eb15b8a27a7c97

#3、更改docker建立容器後預設的執行命令 
docker commit -a [作者] -c "修改執行的命令"  執行的容器   生成的容器名
[[email protected]~]#docker commit -a "作者 <[email protected]>" -c "CMD /bin/ls /tmp/" im1 im2 
sha256:9b755a5afec2c92f077ad02c273de2ffaca541bce06ffed8d9e633853c07ed8d
#執行im2映象測試
[[email protected]~]#docker run -it im2
index.html

 

2、DockerFile(docker映象原始碼)

#dockefile檔案的首之母必須大寫 #.dockeringore目錄是忽略的檔案目錄   Dockerfile語法詳解: #代表註釋 FROM  必須是第一行(表明基於什麼映象製作) LABEL maintainer=”作者資訊" 作者資訊 ENV 設定環境變數 VOLUME  掛載目錄 RUN 代表需要執行的命令 WORKDIR  指定工作目錄 ADD 拷貝本地檔案到容器裡(相對路徑)支援url路徑(網路資源) COPY 拷貝資料夾到容器裡 ##必須是build下的目錄 EXPOSE 暴露埠 CMD [“nginx”] 它要啟動的命令是nginx (就算是nginx服務) ENTRYPOINT ENTRYPOINT的最佳用處是設定映象的主命令,允許將映象當成命令本身來執行(用CMD提供預設選項)。 ONBUILD ONBUILD 在dockerfile中構建一個觸發器(別人後面構建映象時執行的操作)   Dockerfile編寫例子
[[email protected]~]#mkdir /img
[[email protected]~]#cd /img/
[[email protected]]#vim nginx.sh
[[email protected]]#cat  nginx.sh
#!/bin/sh
cat>/etc/nginx/conf.d/www.conf<<EOF
server {
    server_name $HOSTNAME;
    listen  ${PORT:-0.0.0.0:80};
    root ${NGINX_ROOT:-/usr/local/nginx/html};
    charset utf-8;

}
EOF
exec "[email protected]"
[[email protected]]#chmod  +x nginx.sh 
[[email protected]]#vim Dockerfile
[[email protected]]#cat  Dockerfile
FROM nginx:1.15.4-alpine
LABEL maintainer="zhang [email protected]"

ENV NGINX_ROOT="/data/www/html/"
#定義NGINX_ROOT變數
ADD nginx.sh /bin/
#將nginx.sh指令碼新增到容器中的/bin/目錄下載

RUN  mkdir -p $NGINX_ROOT && \
     echo '9999' > ${NGINX_ROOT}index.html
#在容器中執行命令

EXPOSE 80/tcp
#開放80埠

HEALTHCHECK --start-period=3s CMD wget -O - -q http://${HOSTNAME}
#容器執行3s後開始檢測 30s檢查一次,超時時間30s,失敗次數3次 

ONBUILD ADD https://mirrors.aliyun.com/centos/RPM-GPG-KEY-beta /tmp/
#後面基於這個dockerfile製作好的容器為基礎映象,再次build時,將aliyun源上的檔案新增到/tmp目錄

CMD ["/usr/sbin/nginx","-g","daemon off;"]
#將這條命令檔次引數傳給ENTRYPOINT

ENTRYPOINT ["/bin/nginx.sh"]
#執行/bin/nginx.sh指令碼

 

#Docker build構建映象過程

[[email protected]]#docker build -t myimg:1.0 ./
Sending build context to Docker daemon  3.584kB
Step 1/10 : FROM nginx:1.15.4-alpine
1.15.4-alpine: Pulling from library/nginx
4fe2ade4980c: Already exists 
82359930187f: Pull complete 
dd73d113d335: Pull complete 
4b94bac1a7e3: Pull complete 
Digest: sha256:fd0361ff0882d63eec241705ba169d83c042bf27f8b568aedd131c2ab97246f0
Status: Downloaded newer image for nginx:1.15.4-alpine
 ---> 33c5c6e11024
Step 2/10 : LABEL maintainer="zhangbin [email protected]"
 ---> Running in f1c88d7cda87
Removing intermediate container f1c88d7cda87
 ---> 4cceaf0eaac2
Step 3/10 : ENV NGINX_ROOT="/data/www/html/"
 ---> Running in 5c1363aedd8e
Removing intermediate container 5c1363aedd8e
 ---> c437cfebc3d8
Step 4/10 : ADD nginx.sh /bin/
 ---> 80072bb635cf
Step 5/10 : RUN  mkdir -p $NGINX_ROOT &&      echo '9999' > ${NGINX_ROOT}index.html
 ---> Running in 8153863c1e3e
Removing intermediate container 8153863c1e3e
 ---> e3423f795002
Step 6/10 : EXPOSE 80/tcp
 ---> Running in 9c774aad02a6
Removing intermediate container 9c774aad02a6
 ---> 4768345031f8
Step 7/10 : HEALTHCHECK --start-period=3s CMD wget -O - -q http://${HOSTNAME}
 ---> Running in 0fc235d2a345
Removing intermediate container 0fc235d2a345
 ---> da36e9bce34a
Step 8/10 : ONBUILD ADD https://mirrors.aliyun.com/centos/RPM-GPG-KEY-beta /tmp/
 ---> Running in f19b6f1865f7
Removing intermediate container f19b6f1865f7
 ---> 6e22946b4229
Step 9/10 : CMD ["/usr/sbin/nginx","-g","daemon off;"]
 ---> Running in 1e0207770aeb
Removing intermediate container 1e0207770aeb
 ---> 91e82dc16090
Step 10/10 : ENTRYPOINT ["/bin/nginx.sh"]
 ---> Running in 6524c3388c5d
Removing intermediate container 6524c3388c5d
 ---> ddcd2449914d
Successfully built ddcd2449914d

#檢視映象
[[email protected]]#docker image ls|grep myimg
myimg                          1.0                 ddcd2449914d        14 minutes ago      17.7MB

#執行映象
[[email protected]]#docker run -it  --rm  -P  --name img01 myimg:1.0

#檢視映象
[[email protected]]#docker inspect img01|grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.3",
                    "IPAddress": "172.17.0.3",
[[email protected]]#docker ps  
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                        PORTS                    NAMES
e3b7af4d54e0        myimg:1.0           "/bin/nginx.sh /usr/…"   About a minute ago   Up About a minute (healthy)   0.0.0.0:32768->80/tcp    img01
##測試
[[email protected]]#echo 172.17.0.3  e3b7af4d54e0  >>/etc/hosts
[[email protected]]#curl  e3b7af4d54e0
9999

 

七、資源限制

Docker 基於 Linux 核心提供的 cgroups 功能,可以限制容器在執行時使用到的資源,比如記憶體、CPU、塊 I/O、網路等。 Docker資源限制詳解:https://github.com/shimachao/blog/blob/master/Docker/Docker%20%E5%AE%B9%E5%99%A8%20CPU%E3%80%81%E5%86%85%E5%AD%98%E8%B5%84%E6%BA%90%E9%99%90%E5%88%B6%E5%AE%9E%E9%AA%8C.md   測試
#下載測試映象
[[email protected] ~]# docker pull lorel/docker-stress-ng

#記憶體測試
[[email protected] ~]# docker run --name stress -it --rm -m 100M lorel/docker-stress-ng:latest strees --cpu 1 --vm 90M
stress-ng: info: [1] defaulting to a 86400 second run per stressor
stress-ng: info: [1] dispatching hogs: 1 cpu, 90 vm
stress-ng: error: [89] stress-ng-vm: fork failed: errno=12: (Out of me