Docker容器技術(shù)基礎(chǔ)

一、Docker簡介

[TOC]

1.1温鸽、什么是Docker

? Docker是在2013年由dotCloud發(fā)起的一個開源項目保屯,使用Go語言進行開發(fā),基于LInux內(nèi)核的cgroup涤垫、namespace等技術(shù)姑尺,對進程進行封裝隔離,屬于操作系統(tǒng)層面的虛擬化技術(shù)雹姊。

? Docker基于LXC的基礎(chǔ)上進一步封裝股缸,從文件系統(tǒng)衡楞、網(wǎng)絡(luò)互聯(lián)到進程隔離等等吱雏,極大簡化了容器的創(chuàng)建和維護,使Docker技術(shù)比虛擬機技術(shù)更為輕便瘾境、快捷歧杏。

docker1.png

1.2、為什么使用Docker

  • 更高效的系統(tǒng)資源利用率

    ? 由于容器不需要進行硬件虛擬化以及運行完整操作系統(tǒng)等額外開銷迷守,Docker對系統(tǒng)資源利用率更高犬绒。無論是應(yīng)用執(zhí)行速度、內(nèi)存損耗或者文件存儲速度兑凿,都要比傳統(tǒng)虛擬機技術(shù)更高效凯力。因此茵瘾,相比虛擬機技術(shù),一個相同配置的主機咐鹤,往往可以運行更多數(shù)量的應(yīng)用拗秘。

  • 更快速的啟動時間

    傳統(tǒng)虛擬機技術(shù)啟動應(yīng)用服務(wù)因需要啟動完整的操作系統(tǒng),往往需要數(shù)分鐘祈惶,而Docker容器應(yīng)用運行于宿主機內(nèi)核雕旨,無需啟動完整的操作系統(tǒng),因此可以做到秒級捧请、甚至毫秒級啟動凡涩。大大節(jié)約了開發(fā)、測試疹蛉、部署的時間活箕。

  • 環(huán)境一致性

    開發(fā)過程中一個常見的問題是環(huán)境一致性問題。由于開發(fā)可款、測試讹蘑、預(yù)發(fā)布、生產(chǎn)環(huán)境不一致筑舅,導(dǎo)致有些問題未及時發(fā)現(xiàn)座慰。而Docker的鏡像提供了除內(nèi)和外完整的運行時環(huán)境,確保了應(yīng)用運行環(huán)境一致性翠拣。

  • 更高效的持續(xù)交付和部署

    通過Docker可以定制應(yīng)用鏡像實現(xiàn)持續(xù)集成版仔、持續(xù)交付、持續(xù)部署误墓,可以很容器的部署或遷移到另一個平臺蛮粮,而不用擔(dān)心運行環(huán)境的變化導(dǎo)致應(yīng)用無法正常運行。

  • 更輕松的維護和擴展

    Docker使用分層存儲以及鏡像的技術(shù)谜慌,可以更容易的復(fù)用應(yīng)用重復(fù)部分然想,應(yīng)用的部署、運維也更加簡單欣范。

對比傳統(tǒng)虛擬機總結(jié):

特性 容器 虛擬機
啟動 秒級 分鐘級
硬盤使用 一般為MB 一般為GB
性能 接近原生 弱于原生
系統(tǒng)支持量 單機支持上千個容器 一般為幾十個

二变泄、基本概念

Docker包含了三大基本概念:

  • 鏡像(Image)

    Docker鏡像是一個特殊的文件系統(tǒng),除了提供容器運行時所需的程序恼琼、庫妨蛹、資源、配置等文件外晴竞,還包含了一些為運行時準備的一些配置參數(shù)(如環(huán)境變量蛙卤、用戶等)。鏡像不包含任何動態(tài)數(shù)據(jù),其內(nèi)容在構(gòu)建之后也不會被改變颤难,這個和容器的根本區(qū)別神年。

  • 容器(Container)

    鏡像和容器的關(guān)系,就像是面向?qū)ο蟪绦蛟O(shè)計中的實例一樣行嗤,鏡像是靜態(tài)的定義瘤袖,容器是鏡像運行時的實體。容器可以被創(chuàng)建昂验、啟動捂敌、停止、刪除既琴、暫停等占婉。容器運行時,以鏡像為基礎(chǔ)層(鏡像本身時只讀的)甫恩,在其上創(chuàng)建一個可寫層逆济,鏡像本身時保持不變的。

  • 倉庫(Repository)

    Docker倉庫類似于代碼倉庫磺箕,是Docker集中存放鏡像文件的地方奖慌。很多時候有人會將Docker倉庫和注冊服務(wù)器(registry)混為一談。實際上松靡,注冊服務(wù)器是存放倉庫的地方简僧,可以包含多個倉庫;每個倉庫可以包含多個標簽(tag)雕欺;每個標簽對應(yīng)一個鏡像岛马。

三、Docker安裝

3.1屠列、Ubuntu

安裝必要的一些系統(tǒng)工具

apt-get -y install apt-transport-https ca-certificates curl software-properties-common

安裝GPG證書

curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

添加軟件源

add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"

安裝Docker

apt-get -y update
apt-get -y install docker-ce

安裝指定版本:

查詢docker版本

apt-cache madison docker-ce

安裝指定版本(VERSION 例如18.06.1ce-0ubuntu-xenial)

apt-get -y install docker-ce-[VERSION]

3.2啦逆、CentOS7

安裝必要的一些系統(tǒng)工具

yum -y install yum-utils device-mapper-persistent-data lvm2

添加軟件源

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安裝Docker

yum makecache fast
yum -y install docker-ce

安裝指定版本:

查詢docker版本

yum list docker-ce --showduplicates | sort -r

安裝指定版本(VERSION 例如18.09.0.ce.1-1.el7.centos)

yum -y install docker-ce-[VERSION]

3.3、Docker配置文件

cat > /etc/docker/daemon.json <<EOF
{
 "registry-mirrors": ["https://registry.docker-cn.com"],
 "exec-opts": ["native.cgroupdriver=systemd"],
 "storage-driver": "overlay2",
 "storage-opts":["overlay2.override_kernel_check=true"],
 "graph": "/data/data/docker",
 "log-driver": "json-file",
 "log-opts": {
     "max-size": "100m",
     "max-file": "10"
 },
 "oom-score-adjust": -1000,
 "bip": "192.168.100.1/24"
}
EOF

注意:

  • registry-mirrors指定鏡像加速地址笛洛,這里指定官方在國內(nèi)的地址
  • insecure-registries指定私有docker倉庫地址
  • docker默認存放路徑在/var/lib/docker下夏志,graph可以自定義存放路徑。
  • bip可以指定docker運行的網(wǎng)段

四苛让、Docker常用操作

4.1沟蔑、操作容器

從鏡像創(chuàng)建并啟動容器(需要注意的是,容器運行在后臺模式下蝌诡,是不能使用--rm選項的溉贿。)

docker run -itd -p 8080:8080 -v /data:/data --name k8s registry.k8sre.com/library/alpine:3.9
docker container run -it --rm registry.k8sre.com/library/alpine:3.9

說明:

1枫吧、-t 選項讓Docker分配一個偽終端并綁定到容器的標準輸入上

2浦旱、-i 選項讓容器的標準輸入保持打開

3、-d選項讓容器可以后臺運行

4九杂、當操作者執(zhí)行docker run --privileged --privileged=true 時颁湖,Docker將擁有訪問主機所有設(shè)備的權(quán)限宣蠕,同時Docker也會在apparmor或者selinux做一些設(shè)置,使容器可以容易的訪問那些運行在容器外部的設(shè)備甥捺。

查看容器

docker ps           #列出當前正在運行的容器
docker ps -a        #列出所有的容器抢蚀,包括正在運行的和其他未運行的
docker ps -l        #列出最近一次啟動的容器
docker ps -a -q     #列出所有容器的CONTAINER_ID
docker container ls -a #列出所有容器

啟動/停止/重啟/刪除容器(新版本逐步使用docker container來管理容器)

docker start xxxx
docker stop xxxx
docker restart xxxx
docker rm -f xxxx
docker container prune #清理容器

進入容器

docker attach xxxx
docker exec -it xxxx

注意:使用docker attach從這個sedin中exit,會導(dǎo)致容器的停止镰禾,而docker exec并不會皿曲。所以推薦大家使用docker exec。

導(dǎo)出和導(dǎo)入容器

docker save alpine:3.9 -o xxx.tar 
docker load -i xxx.tar
docker export alpine:3.9 > alpine.tar
cat alpine.tar | docker import - registry.k8sre.com/library/alpine:3.9

注意:既可以使用docker load來導(dǎo)入鏡像文件到本地鏡像庫吴侦,也可以使用docker import來導(dǎo)入一個容器快照到本地鏡像庫屋休。這兩者的區(qū)別在于docker import導(dǎo)入容器快照文件將丟棄所有的歷史記錄和元數(shù)據(jù)信息(即僅保存容器當時的快照狀態(tài)),而docker load導(dǎo)入鏡像存儲文件將保存完整記錄备韧,體積也要大劫樟。此外容器快照文件導(dǎo)入時可以重新制定標簽等元數(shù)據(jù)信息。

宿主機與容器間傳文件

docker cp -r /root/tomcat.tar.gz CONTAINER_ID:/root #從宿主機復(fù)制到容器
docker cp -r CONTAINER_ID:/root/tomcat.tar.gz /root/    #從容器復(fù)制到宿主機

創(chuàng)建并使用存儲卷

docker run -v /data/downloads:/usr/downloads  --name dataVol ubuntu64 /bin/bash
docker run -it --volumes-from dataVol ubuntu64 /bin/bash

4.2织堂、操作鏡像

docker1.13+推薦使用docker image管理鏡像

從Dockerfile構(gòu)建鏡像

docker build -t registry.k8sre.com/libary/alpine:3.9 .

將運行的容器保存為鏡像

docker commit -a "作者名字" -m "說明文字" 容器ID 鏡像名:tag

搜索/獲取鏡像

docker search ubuntu
docker pull [選項] [Docker Registry地址]<倉庫名>:<標簽>
docker image pull ubunut:18.04      

查看鏡像

docker images -q
docker history IMAGE_ID     #查看鏡像內(nèi)的歷史記錄
docker image ls 
docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}" #自定義結(jié)構(gòu)查看鏡像

刪除鏡像

docker rmi $(docker images -q -f dangling=true)     #刪除所有虛懸鏡像
docker rmi IMAGE_ID/$(docker images -q)                 #刪除單個或所有鏡像

推送鏡像到倉庫

docker login -u k8sre registry.k8sre.com
docker tag IMAGE_ID registry.k8sre.com/libary/xxx:xxx
docker push registry.k8sre.com/libary/xxx:xxx

4.3叠艳、其他常用命令

docker system df            //顯示Docker磁盤使用狀態(tài)
docker system events        //顯示Docker服務(wù)實時事件信息
docker system info          //顯示系統(tǒng)信息
docker system prune         //刪除未使用的數(shù)據(jù)
docker trust inspect        //返回Key和簽名的低級別信息
docker trust key            //管理用于鏡像簽名的Key
docker trust revoke         //撤銷對鏡像的簽名
docker trust sign           //對鏡像進行簽名
docker trust signer         //管理可以對鏡像簽名的用戶
docker volume create       //創(chuàng)建一個卷
docker volume insoect      //顯示一或多個卷的詳細信息
docker volume ls           //列出卷
docker volume prune        //刪除所有未使用的卷
docker volume rm           //刪除一或多個卷
docker pause xxxx          //暫停一或多個容器內(nèi)所有進程
docker unpause xxxx        //取消暫停一或多個容器內(nèi)所有進程
docker port xxxx           //列出容器與主機的端口映射
docker rename xxx          //重命名容器名稱
docker diff                //查看容器文件系統(tǒng)內(nèi)有差異的文件
docker stats xxx           //實時輸出指定容器的資源使用狀態(tài)
docker top xxxx            //顯示指定容器運行中的進程信息
docker update              //更新一或多個容器配置,如資源配額、重啟策略等等
docker wait xxx            //捕捉一或多個容器的退出狀態(tài)

五易阳、Docker網(wǎng)絡(luò)實現(xiàn)和文件系統(tǒng)

5.1附较、Docker的網(wǎng)絡(luò)模式

? Docker的網(wǎng)絡(luò)實現(xiàn)利用了Linux上網(wǎng)絡(luò)命名空間和虛擬網(wǎng)絡(luò)設(shè)備(特別是veth pair)。熟悉這兩部分的基本概念潦俺,可以有助于理解Docker網(wǎng)絡(luò)的實現(xiàn)過程翅睛。

5.1.1、基本原理

? 要實現(xiàn)網(wǎng)絡(luò)通信黑竞,主機需要至少一個網(wǎng)絡(luò)接口(物理接口或虛擬接口)與外界相通捕发,并可以收發(fā)數(shù)據(jù)包;此外很魂,如果不同子網(wǎng)之間要進行通信扎酷,需要額外的路由機制。

? Docker中的網(wǎng)絡(luò)接口默認都是虛擬的接口遏匆。虛擬接口的最大優(yōu)勢就是轉(zhuǎn)發(fā)效率極高法挨。這是因為Linxu通過在內(nèi)核中進行數(shù)據(jù)復(fù)制來實現(xiàn)虛擬接口之間的數(shù)據(jù)轉(zhuǎn)發(fā),即發(fā)送接口的發(fā)送緩存中的數(shù)據(jù)包將被直接復(fù)制到接收接口的接收緩存中幅聘,而無需通過外部物理網(wǎng)絡(luò)設(shè)備進行交換凡纳。對于本地系統(tǒng)和容器內(nèi)系統(tǒng)來看,虛擬接口跟一個正常的以太網(wǎng)卡相比并無區(qū)別帝蒿,只是它速度要快得多荐糜。

? Docker容器網(wǎng)絡(luò)就很好的利用了Linux虛擬網(wǎng)絡(luò)技術(shù)。它在本地主機和容器內(nèi)分別建立一個虛擬接口,并讓它們彼此連通(這樣的一對接口叫做veth pair)暴氏。

docker2.png

5.1.2延塑、網(wǎng)絡(luò)創(chuàng)建過程

Docker創(chuàng)建一個容器的時候,會執(zhí)行以下操作:

? 1答渔、創(chuàng)建一對虛擬接口关带,分別放到本地主機和新容器的命名空間中。

? 2沼撕、本地主機一端的虛擬接口連接到默認的docker0網(wǎng)橋宋雏,并具有一個veth開頭的唯一名字。

? 3务豺、容器一端的虛擬接口將放到新創(chuàng)建容器中好芭,并修改名字作為eth0。這個接口只在容器的命名空間中可見冲呢。

? 4舍败、從網(wǎng)橋可用的地址段中獲取一個空閑地址分配給容器的eth0,并配置默認路由網(wǎng)關(guān)為docker0網(wǎng)卡的內(nèi)部接口docker0的IP地址敬拓。

? 5邻薯、此時,容器就可以使用它所能看到的eth0虛擬網(wǎng)卡來連接其他容器和訪問外部網(wǎng)絡(luò)了乘凸。

5.1.3厕诡、常見Docker網(wǎng)絡(luò)模型

  • bridge

    通過veth接口來連接容器,默認配置营勤。

  • host

    不將容器網(wǎng)絡(luò)放到隔離的命名空間中灵嫌,即不要容器化容器內(nèi)的網(wǎng)絡(luò)「鹱鳎可以使用本地主機的網(wǎng)絡(luò)寿羞,它擁有完全的本地主機接口訪問權(quán)限。容器進程可以跟主機其他root進程一樣打開低范圍端口赂蠢,可以訪問本地網(wǎng)絡(luò)服務(wù)(比如D-bus)绪穆,還可以讓容器做一些影響主機系統(tǒng)的事情,比如重啟主機等虱岂。因此使用這個選項的時候要謹慎玖院,如果進一步的使用--privileged=true參數(shù),容器甚至?xí)辉试S直接配置主機的網(wǎng)絡(luò)堆棧第岖。

  • container

    將新建的容器的進程放到一個已存在容器的網(wǎng)絡(luò)棧中难菌,新容器進程有自己的文件系統(tǒng)、進程列表蔑滓、資源限制郊酒,但會和已存在的容器共享IP地址和端口等網(wǎng)絡(luò)資源遇绞,兩者進程可以直接通過lo環(huán)回接口通信。

  • none

    將新建容器放到隔離的網(wǎng)絡(luò)棧中猎塞,但是不進行網(wǎng)絡(luò)配置试读。之后杠纵,用戶可以自己進行配置荠耽。

5.1.4、網(wǎng)絡(luò)配置

? 用戶使用--net=none后比藻,Docker將不對容器網(wǎng)絡(luò)進行配置铝量,可以使用以下方式進行配置:

啟用一個網(wǎng)絡(luò)為none的容器

docker run -it --net=none alpine /bin/bash

查找容器進程id

docker inspect -f '{{.State.Pid}}' container_id

查看docker0網(wǎng)絡(luò)信息

ip addr show docker0

創(chuàng)建一對”veth pair“接口A和B,綁定其中一個到docker0

ip link add A type veth peer name B
brctl addif docker0 A
ip link set A up

將B接口放到容器的網(wǎng)絡(luò)命名空間银亲,命名為eth0

ip link set B netns $PID
ip netns exec $PID ip link set dev B name eth0
ip netns exec $PID ip link set eth0 up

配置容器網(wǎng)絡(luò)和網(wǎng)關(guān)

ip netns exec $PID ip addr add 172.17.1.2/24 dev eth0
ip netns exec $PID ip route add default via 172.17.1.1

以上就是Docker網(wǎng)絡(luò)的配置過程慢叨。

當容器終止后,Docker會清空容器务蝠,容器內(nèi)的網(wǎng)絡(luò)接口會隨網(wǎng)絡(luò)命名空間一起被清除拍谐,A接口也被自動從docker0卸載并清除。

此外馏段,在刪除/var/run/netns/下的內(nèi)容之前轩拨,用戶可以使用ip netns exec 命令指定網(wǎng)絡(luò)命名中進行配置,從而影響容器內(nèi)的網(wǎng)絡(luò)院喜。

5.2亡蓉、Docker聯(lián)合文件系統(tǒng)

5.2.1、基本原理

? 聯(lián)合文件系統(tǒng)(UnionFS)是一種輕量級的高性能分層文件系統(tǒng)喷舀,它支持將文件系統(tǒng)中的修改信息作為一次提交砍濒,并層層疊加,同時可以將不同目錄掛載到同一個虛擬文件系統(tǒng)下硫麻。

聯(lián)合文件系統(tǒng)是實現(xiàn)Docker鏡像的技術(shù)基礎(chǔ)爸邢。鏡像可以通過分層來繼承。例如拿愧,用戶基于基礎(chǔ)鏡像(沒有父鏡像的鏡像成為基礎(chǔ)鏡像)來制作各種不同的應(yīng)用鏡像甲棍。這些鏡像共享同一個基礎(chǔ)鏡像曾,提高了存儲效率赶掖。此外感猛,當用戶改變一個Docker鏡像,則一個新的層(layer)會被創(chuàng)建奢赂。因此陪白,用戶不用替換整個原鏡像或者重新建立,只要添加新層即可用戶分發(fā)鏡像的時候膳灶,也只需要分發(fā)被改動的新層內(nèi)容(增量部分)咱士。這讓Docker的鏡像管理變得十分輕量級和快速险污。

docker3.jpg

5.2.2挑秉、Docker常見聯(lián)合文件系統(tǒng)

  • devicemapper

    1、建議不要在生產(chǎn)環(huán)境使用此存儲方案

    2、本地文件容易丟失加派,且不容易擴展空間

    3、從性能上而言开睡,本地文件掛接方式讓存儲結(jié)構(gòu)跟復(fù)雜且性能更低

    4莹菱、本地文件在集群和分布式存儲方式中讓系統(tǒng)架構(gòu)更加復(fù)雜

    5、不能很好的體現(xiàn)data數(shù)據(jù)和meta數(shù)據(jù)分離的優(yōu)越性

  • overlay

    1文捶、RHEL/CentOS 必須是 7.2 或以上版本

    2荷逞、Docker必須是最新版本,并且支持Overlay

    3粹排、底層文件系統(tǒng)必須是XFS

    4种远、SELinux在宿主機上必須打開設(shè)為enforcing模式,但docker服務(wù)啟動時不能打開支持selinux選項顽耳,不能設(shè)置"--selinux-enabled"坠敷。目前RHEL 7.2系統(tǒng)還不支持overlay下的selinux

    5、為了支持yum和rpm工具在以overlay為基礎(chǔ)的容器中正常運行射富,需要安裝yum-plugin-ovl軟件包膝迎。

  • overlay2

    1、overlay2 是 overlay 的升級辉浦,與overlay的結(jié)構(gòu)基本相同

    2弄抬、使用了從寫的函數(shù),在存儲上是不兼容的宪郊,因此從overlay升級的話需要刪除所有的鏡像和容器

    3掂恕、Overlay2解決了overlay inode損耗和提交(commit)性能問題,但是只在Docker 1.11之后的版本才能實現(xiàn)

    4弛槐、overlay2在docker 18之前的版本需要升級內(nèi)核版本才可以使用懊亡,目前最新版已經(jīng)不需要升級內(nèi)核即可使用

六、Dockerfile詳解

? 鏡像的定制實際上就是定制每一層所添加的配置文件乎串。如果我們可以把每一層修改店枣、安裝、構(gòu)建叹誉、操作的命令都寫入一個腳本鸯两,用這個腳本來定制、構(gòu)建鏡像长豁,那么無法重復(fù)钧唐、鏡像構(gòu)建透明性、鏡像體積的問題都會解決匠襟。這個腳本就是Dockerfile钝侠。

? Dockerfile是一個文本文件该园,其內(nèi)包含了一條條的指令,所有指令都是在開頭帅韧,并且必須為大寫字母里初,每一條指令構(gòu)建一層,因此每一條指令的內(nèi)容忽舟,就是描述該層當如何構(gòu)建双妨。Dockerfile的指令會按從上到下的順序執(zhí)行。

  • FROM:指定基礎(chǔ)鏡像

    所謂定制鏡像萧诫,那一定是以一個鏡像為基礎(chǔ)的斥难,在其上進行定制枝嘶,而FROM就是指定基礎(chǔ)鏡像帘饶,因此Dockerfile中FROM是必備的指令,并且必須是第一條指令群扶。

  • RUN:執(zhí)行命令

    RUN指令是用來執(zhí)行命令行命令的及刻,由于命令行的強大能力,RUN指令是在定制鏡像時最常用的指令之一竞阐。其格式有兩種:

    • shell格式:RUN <命令>缴饭,就像直接在命令行種輸入的命令一樣。
    • exec格式:RUN [“可執(zhí)行文件”,“參數(shù)1”,"參數(shù)2"]骆莹,這更像是函數(shù)調(diào)用種的格式颗搂。

    ? 因每一條指定構(gòu)建一層,當有多個shell格式的RUN指令時幕垦,盡量使用&&將各個命令串聯(lián)起來丢氢,簡化鏡像層。Dockerfile支持shell類的行尾添加\的命令換行方式先改,以及行首#進行注釋的格式疚察。良好的格式,比如換行仇奶、縮進貌嫡、注釋等,會讓維護该溯、排障更為容易岛抄,這是一個比較好的習(xí)慣。

    ? 此外狈茉,在指令結(jié)束時務(wù)必進行緩存清理夫椭,之前說過,鏡像時多層的论皆,每一層的東西并不會在下一層被刪除益楼,會一直跟隨著鏡像猾漫。因此鏡像構(gòu)建時,一定確保每一層只添加真正需要的東西感凤,任何無關(guān)的東西都應(yīng)該清理掉悯周。很多初學(xué)者制作令很臃腫的鏡像的原因之一,就是忘記了每一層構(gòu)建的最后一定要清理掉無關(guān)文件陪竿。

  • COPY:復(fù)制文件

    格式:

    • COPY <源路徑> …<目標路徑>
    • COPY ["<源路徑1>",..."<目標路徑>"]

    ? 和RUN指令一樣禽翼,也有兩種格式,一種類似命令行族跛,一種類似于函數(shù)調(diào)用闰挡。COPY指令將從構(gòu)建上下文目錄<源路徑>的文件/目錄復(fù)制到新的一層鏡像內(nèi)的<目標路徑>指定位置。

    ? <源路徑>可以是多個礁哄,甚至可以是通配符长酗,其通配符規(guī)則要滿足GO的規(guī)則。

    ? <目標路徑>可以是容器內(nèi)的絕對路徑桐绒,也可以是相對于工作目錄的相對路徑(工作目錄可以用WORKDIR指令來指定)夺脾。目標路徑不需要事先創(chuàng)建,如果目錄不存在會在復(fù)制文件前先行創(chuàng)建缺失目錄茉继。

    ? 此外咧叭,還需要注意一點,使用COPY指令烁竭,源文件的各種元數(shù)據(jù)都會保留菲茬。比如讀、寫派撕、執(zhí)行權(quán)限婉弹、文件變更時間等。這個特性對于鏡像定制很有用腥刹。

  • ADD:更高級的復(fù)制文件

    ? ADD指令和COPY的格式和性質(zhì)基本一致马胧。但是在COPY基礎(chǔ)上增加了一些功能。比如<源路徑>可以是一個URL衔峰,這種情況下佩脊,Docker引擎會試圖去下載這個鏈接的文件放到<目標路徑>去。下載后的文件權(quán)限自動設(shè)置為600垫卤,如果這并不是想要的權(quán)限威彰,那么還需要增加額外的一層RUN進行權(quán)限調(diào)整,另外穴肘,下載的是個壓縮包歇盼,需要使用額外一層RUN進行解壓縮。所以不如直接使用RUN指令评抚,然后wget豹缀、curl下載伯复,處理權(quán)限、解壓縮邢笙、然后清理無用文件更合理啸如。因此,這個功能其實并不實用氮惯,而且不推薦叮雳。

    ? 如果<源路徑>為一個tar壓縮文件的話,壓縮格式為gzip妇汗、bzip2帘不、xz的情況下,ADD指令將會自動解壓縮杨箭。

    ? 在Docker官方文檔中寞焙,ADD指令會令鏡像構(gòu)建緩存失效,從而可能會令鏡像變得比較緩慢告唆。因此棺弊,盡可能的使用COPY晶密,因為COPY語義很明確擒悬,就是復(fù)制文件而已,而ADD則包含了更復(fù)雜的功能稻艰,其行為也不一定很清晰懂牧。最適合使用ADD的場合,就是自動解壓縮的場合尊勿。

  • CMD:容器啟動命令

    CMD指令的格式和RUN相似僧凤,也是兩種格式:

    • shell格式:CMD <命令>
    • exec格式:CMD [“可執(zhí)行文件”,"參數(shù)1","參數(shù)2"...]
    • 參數(shù)列表格式:CMD ["參數(shù)1","參數(shù)2"…]。在指定了CNTRYPOINT指令后元扔,用CMD指定具體參數(shù)躯保。

    ? Docker不是虛擬機,容器就是進城澎语。既然是進程途事,那么在啟動容器的時候,需要指定所運行的程序及參數(shù)擅羞。CMD指令就是用于指定默認的容器主進程的啟動命令尸变。在運行時可以指定新的命令來替代鏡像設(shè)置中的這個默認命令。

    ? 在指令格式上减俏,一般推薦使用exec格式召烂,這類格式在解析時會被解析喂JSON數(shù)組,因此一定要使用雙引號娃承,而不是單引號奏夫。如果使用shell格式的話怕篷,實際的命令會被包裝為sh -c的參數(shù)的形式進行執(zhí)行。

    ? Docker不是虛擬機酗昼,容器中的應(yīng)用都應(yīng)該在前臺執(zhí)行匙头,而不是像虛擬機、物理機里面那樣仔雷,用upstart/systemd去啟動后臺服務(wù)蹂析,容器內(nèi)沒有后臺服務(wù)的概念。

    CMD ["nginx","-g","daemon off"]
    
  • ENTRYPOINT:接入點

    ? ENTRYPOINT的格式和RUN指令的格式一樣碟婆,分為exec格式和shell格式电抚。ENTRYPOINT的目的和CMD一樣,都是在指定容器啟動程序及參數(shù)竖共。ENTRYPOINT在運行時也可以替代蝙叛,需要通過--entrypoint來指定。

    ? 當指定來ENTRYPOINT后公给,CMD的含義就發(fā)生了改變借帘,不再是直接運行其命令,而是將CMD的內(nèi)容作為參數(shù)傳給ENTRYPOINT指令淌铐。

  • ENV:設(shè)置環(huán)境變量

    格式有兩種:

    • ENV <key> <value>
    • ENV <key1>=<value1> <key2>=<value2>

    ? 這個指令很簡單肺然,就是設(shè)置環(huán)境變量而已,無論是后面的其它指令腿准,如RUN际起,還是運行時的應(yīng)用,都可以直接使用這里定義的環(huán)境變量吐葱。

  • ARG:構(gòu)建參數(shù)

    格式:ARG <參數(shù)名> [=<默認值]

    ? 構(gòu)建參數(shù)和ENV的效果一樣街望,都是設(shè)置環(huán)境變量。不同的是弟跑,ARG所設(shè)置的構(gòu)建環(huán)境的環(huán)境變量灾前,在將來容器運行時是不會存在這些環(huán)境變量的。但是不要因此就使用ARG保存密碼之類的信息孟辑,因為docker history還是可以看到所有值的哎甲。

    ? Dockerfile中的ARG指令時定義參數(shù)名稱,以及定義其默認值扑浸。該默認值可以在構(gòu)建命令docker build中用--build-arg <參數(shù)名>=<值>來覆蓋。

    ? 在1.13之前的版本喝噪,要求--build-arg中的參數(shù)名础嫡,必須在Dockerfile中用ARG定義過了,換句話說,就是--build-arg指定的參數(shù)榴鼎,必須在Dockerfile中使用了伯诬。如果對應(yīng)參數(shù)沒有被使用,則會報錯退出構(gòu)建巫财。從1.13開始盗似,這種嚴格的限制被放開,不再報錯退出平项,而是現(xiàn)實警告信息赫舒,并繼續(xù)構(gòu)建。這對于使用CI系統(tǒng)闽瓢,用同樣的構(gòu)建流程構(gòu)建不同的Dockerfile的時候比較有幫助接癌,避免構(gòu)建命令必須根據(jù)每個Dockerfile的內(nèi)容修改。

  • VOLUME:定義存儲卷

    格式:

    • VOLUME ["<路徑1>","<路徑2>"...]
    • VOLUME <路徑>

    ? 之前我們說過扣讼,容器運行時應(yīng)該盡量避免容器存儲層不發(fā)生寫操作缺猛,對于數(shù)據(jù)庫類需要保存動態(tài)數(shù)據(jù)的應(yīng)用,其數(shù)據(jù)庫文件應(yīng)該保存于卷(volume)中椭符,在Dockerfile中荔燎,我們可以事先指定某些目錄掛載為匿名卷,這樣在運行時如果忘記指定掛載销钝,其應(yīng)用也可以這個正常運行有咨,不會向容器存儲層寫入大量數(shù)據(jù)。

  • EXPOSE:聲明端口

    格式: EXPOSE <端口1> [<端口2>…]曙搬。

    ? EXPOSE指令時聲明運行時容器提供服務(wù)端口摔吏,這只是一個聲明,在運行時并不會因為這個聲明應(yīng)用就會開啟這個端口的服務(wù)纵装。

  • WORKDIR:指定工作目錄

    格式: WORKDIR <工作目錄路徑>。

    ? 使用WORKDIR指令可以來指定工作目錄(或者稱為當前目錄)据某,以后各層的當前目錄就被改為指定的目錄橡娄,如該目錄不存在,WORKDIR會幫你創(chuàng)建目錄癣籽。

  • USER:指定當前用戶

    格式:USER <用戶名>

    ? USER指定和WORKDIR相似挽唉,都是改變環(huán)境狀態(tài)并影響以后層。WORKDIR是改變工作目錄筷狼,USER則是改變之后層的執(zhí)行RUN瓶籽、CMD以及ENTRYPOINT這類命令的身份。

    ? USER只是幫助你切換到指定用戶而已埂材,這個用戶必須是事先創(chuàng)建好的塑顺,否則無法切換。

  • HEALTHCHECK:健康檢查

    格式:

    • HEALTHCHECK [選項] CMD <命令> :設(shè)置檢查容器健康狀況的命令
    • HEALTHCHECK NONE :如果基礎(chǔ)鏡像有健康檢查指令,使用這行可以屏蔽掉其健康檢查指令

    ? HEALTHCHECK指令是Docker應(yīng)該如何進行判斷容器的狀態(tài)是否正常严拒,這是Docker1.12引入的新指令扬绪。通過該指令指定一行命令,用這行命令來判斷容器主進程的服務(wù)狀態(tài)是否正常裤唠,從而比較真實的反應(yīng)容器實際狀態(tài)挤牛。

    ? 當一個鏡像指定了HEALTHCHECK指令后,用其啟動容器种蘸,初始狀態(tài)會為starting墓赴,在HEALTHCHECK指令檢查成功后變?yōu)閔ealthy,如果連續(xù)一定次數(shù)失敗航瞭,則會變?yōu)閡nhealthy竣蹦。

    HEALTHCHECK支持下列選項:

    • --interval=<間隔> :兩次健康檢查的間隔,默認為30秒沧奴。
    • --timeout=<時長> :健康檢查命令運行超時時間痘括,如果超過這個時間,本次健康檢查就被視為失敗滔吠,默認30秒纲菌。
    • --retries=<次數(shù)> :當連續(xù)失敗指定次數(shù)后,則將容器狀態(tài)視為unhealth疮绷,默認3次翰舌。

    ? 和CMD、ENTRYPOINT一樣冬骚,HEALTHCHECK只可以出現(xiàn)一次椅贱,如果寫了多個,只有最后一個生效只冻。在HEALTHCHECK [選項] CMD 后面的命令庇麦,格式和ENTRYPOINT一樣,分為shell格式和exec格式喜德。命令的返回值決定了該次健康檢查的成功與否:0:成功山橄;1:失敗舍悯;2:保留航棱。不要使用這個值。

  • ONBUILD:為他人做嫁衣

    格式:ONBUILD <其他指令>萌衬。

    ? ONBUILD是一個特殊的指令饮醇,它后面跟的是其它指令,比如RUN秕豫、COPY等朴艰,而這些指令,在當前鏡像構(gòu)建時并不會被執(zhí)行。只有當以當前鏡像為基礎(chǔ)鏡像呵晚,去構(gòu)建下一級鏡像的時候才會被執(zhí)行蜘腌。Dockerfile中的其它指令都是為了定制當前鏡像而準備的,唯有ONBUILD是為了幫助別人定制自己而準備的饵隙。

七撮珠、Docker核心技術(shù)

? Docker采用了標準的C/S架構(gòu),包括客戶端和服務(wù)端兩大部分金矛。

? 客戶端可以和服務(wù)端機可以運行在一個機器芯急,也可以通過socket或者RESTful API來進行通信。

7.1驶俊、服務(wù)端

? Docker daemon一般在宿主機后臺運行娶耍,作為服務(wù)端接受來自客戶的請求,并處理這些請求(創(chuàng)建饼酿、運行榕酒、分發(fā)容器)。在設(shè)計上故俐,Docker daemon是一個非常松耦合的架構(gòu)想鹰,通過專門的ENgine模塊來分發(fā)管理各個來自客戶端的任務(wù)。

? Docker服務(wù)端默認監(jiān)聽本地的unux:///var/run/docker.sock套接字药版,只允許本地的root用戶訪問辑舷。可以通過-H選項修改監(jiān)聽方式槽片。

docker -H 0.0.0.0:666 -d &

此外何缓,Docker還支持通過HTPPS認證方式來驗證訪問。

7.2还栓、客戶端

? Docker客戶端為用戶提供了一系列可執(zhí)行命令碌廓,用戶通過這些命令實現(xiàn)與Docker daemon的交互。

? 用戶使用的Docker可執(zhí)行命令即為客戶端程序蝙云。與Docker daemon不同的是氓皱,客戶端發(fā)送命令后,等待服務(wù)端返回勃刨,一旦收到返回后,客戶端立刻執(zhí)行結(jié)束并退出股淡。用戶執(zhí)行新的命令身隐,需要再次調(diào)用客戶端命令。

? 同樣唯灵,客戶端默認通過本地的unux:///var/run/docker.sock套接字向服務(wù)端發(fā)送命令贾铝。如果服務(wù)端沒有監(jiān)聽到默認套接字,則需要客戶端在執(zhí)行命令的時候顯式指定。

docker -H tcp://127.0.0.1:666 version

7.3垢揩、命令空間

? 命令空間(Namespace)是Linux內(nèi)核針對實現(xiàn)容器虛擬化而引入的一個強大特性玖绿。

? 每個容器都可以擁有自己單獨的命名空間,運行在其中的應(yīng)用都像是在獨立的操作系統(tǒng)中運行一樣叁巨。命名空間保證了容器之間互不影響斑匪。

? 眾所周知,在操作系統(tǒng)中锋勺,包括內(nèi)核蚀瘸、文件系統(tǒng)、網(wǎng)絡(luò)庶橱、PID贮勃、UID、IPC苏章、內(nèi)存寂嘉、硬盤、CPU等資源枫绅,所有的資源都是應(yīng)用進程直接共享的泉孩。要想實現(xiàn)虛擬化,除了要實現(xiàn)對內(nèi)存撑瞧、CPU棵譬、網(wǎng)絡(luò)IO、硬盤IO预伺、存儲空間等的限制外订咸,還要實現(xiàn)文件系統(tǒng)、網(wǎng)絡(luò)酬诀、PID脏嚷、UID、IPC等等的相互隔離瞒御。前者相對實現(xiàn)容易實現(xiàn)一些父叙,后者則需要宿主機系統(tǒng)的深入支持。

? 隨著Linux系統(tǒng)的逐步完善肴裙,已經(jīng)實現(xiàn)讓某些進程在彼此隔離的命名空間中運行趾唱,這些進程都共用一個內(nèi)核和某些運行時環(huán)境(runtime),但是彼此是不可見的-它們各自認為是自己獨占系統(tǒng)的蜻懦。

7.3.1甜癞、進程命名空間

? Linux通過命名空間管理進程號,對于同一個進程(同一個task_struct)宛乃,在不同的命名空間中悠咱,看到的進程號不相同蒸辆,每個進程命名空間有一套自己的進程號股那里方法。進程命名空間是一個父子關(guān)系的結(jié)構(gòu)析既,子空間中的進程對于父空間是可見的躬贡。新fork出的進程在父命名空間個子命名空間將分別由一個進程號來對應(yīng)。

7.3.2眼坏、網(wǎng)絡(luò)命名空間

? 如果有了PID命名空間拂玻,那么每個名字空間中的進程就可以相互隔離,但是網(wǎng)絡(luò)端口還是共享本地系統(tǒng)的端口空骚,

? 通過網(wǎng)絡(luò)命名空間纺讲,可以實現(xiàn)網(wǎng)絡(luò)隔離。一個網(wǎng)絡(luò)命名空間為進程提供了一個完全獨立的網(wǎng)絡(luò)協(xié)議棧的視圖囤屹。包括網(wǎng)絡(luò)設(shè)備接口熬甚、IPv4和IPv6協(xié)議棧、IP路由表】防火墻規(guī)則肋坚,Sockets等等乡括。這樣每個容器的網(wǎng)絡(luò)就能隔離。Docker采用虛擬網(wǎng)絡(luò)設(shè)備(Virtual Network Device)的方式智厌,將不同命名空間的網(wǎng)絡(luò)設(shè)備連接到一起诲泌。默認情況下,容器中的虛擬網(wǎng)卡將同本地主機上的docker0網(wǎng)橋連接在一起铣鹏。

查看橋街道宿主機docker0網(wǎng)橋的虛擬網(wǎng)口:

brctl show

7.3.3敷扫、IPC命名空間

? 容器中進程交互還是采用了LInux常見的進程間交互方法(Interprocess Communication IPC),包括信號量诚卸、消息隊列和共享內(nèi)存等葵第。PID命名空間和IPC命名空間可以組合起來一起使用,同一個IPC名字空間內(nèi)的進程可以彼此可見合溺,允許進行交互卒密;不同名字空間的進程則無法交互。

7.3.4棠赛、掛載命名空間

? 類似chroot哮奇,將一個進程放到一個特定的目錄執(zhí)行。掛載命名空間運行不同命名空間的進程看到的文件結(jié)構(gòu)不同睛约,這樣每個命名空間中的進程所看到的文件目錄彼此隔離鼎俘。

7.3.5、UTS命名空間

? UTS(UNIX Time-sharing System)命名空間允許每個容器擁有獨立的主機名和域名辩涝,從而可以虛擬出一個獨立主機名和網(wǎng)絡(luò)空間的環(huán)境而芥,就跟網(wǎng)絡(luò)上一臺獨立的主機一樣。

7.3.6膀值、用戶命名空間

? 每個容器可以有不同的用戶和組ID棍丐,也就是說可以在容器內(nèi)使用特定的內(nèi)部用戶執(zhí)行程序,而非本地系統(tǒng)上存在的用戶沧踏。

? 每個容器內(nèi)部都可以由root用戶歌逢,跟宿主機不在同一個命名空間。

7.4翘狱、控制組

? 控制組(CGroups)是Linux內(nèi)核的一個特性秘案,主要用來對共享資源進行隔離、限制潦匈、審計等阱高。只有能控制分配到容器的資源,Docker才能避免多個容器同時運行時的系統(tǒng)資源競爭茬缩。

? 控制組可以提供對容器的內(nèi)存赤惊、CPU、磁盤IO等資源進行限制和計費管理凰锡∥粗郏控制組的設(shè)計目標是為不同的應(yīng)用情況提供統(tǒng)一的接口,從控制單一進程(比如nice工具)到系統(tǒng)級虛擬化(包括OpenVZ掂为、Linux-VServer裕膀、LXC等)。

控制組提供以下功能:

  • 資源限制(Resource Limiting):可以設(shè)置為不超過設(shè)定的內(nèi)存限制勇哗。比如內(nèi)存子系統(tǒng)可以為進程組設(shè)定一個內(nèi)存使用上限昼扛,一旦進程組使用的內(nèi)存達到限額再申請內(nèi)存,就會觸發(fā)Out of Memory欲诺。
  • 優(yōu)先級(Prioritization):通過優(yōu)先級讓一些組優(yōu)先得到更多的CPU抄谐、MEM等資源
  • 資源審計(Accounting):用來統(tǒng)計系統(tǒng)實際上把多少資源用到適合的目的上,可以使用cpuacct子系統(tǒng)記錄某個進程組使用的CPU時間
  • 隔離(Isolation):為組隔離名字空間瞧栗,這樣一個組不會看到另一個組的進程斯稳、網(wǎng)絡(luò)連接、文件系統(tǒng)
  • 控制(Control):掛起迹恐、恢復(fù)和重啟動等操作
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末挣惰,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子殴边,更是在濱河造成了極大的恐慌憎茂,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锤岸,死亡現(xiàn)場離奇詭異竖幔,居然都是意外死亡,警方通過查閱死者的電腦和手機是偷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門拳氢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來募逞,“玉大人,你說我怎么就攤上這事馋评》沤樱” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵留特,是天一觀的道長纠脾。 經(jīng)常有香客問我,道長蜕青,這世上最難降的妖魔是什么苟蹈? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮右核,結(jié)果婚禮上慧脱,老公的妹妹穿的比我還像新娘。我一直安慰自己蒙兰,他們只是感情好磷瘤,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著搜变,像睡著了一般采缚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上挠他,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天扳抽,我揣著相機與錄音,去河邊找鬼殖侵。 笑死贸呢,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的拢军。 我是一名探鬼主播楞陷,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼茉唉!你這毒婦竟也來了固蛾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤度陆,失蹤者是張志新(化名)和其女友劉穎艾凯,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懂傀,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡趾诗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蹬蚁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恃泪。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡郑兴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出悟泵,到底是詐尸還是另有隱情杈笔,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布糕非,位于F島的核電站淋昭,受9級特大地震影響舆瘪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜尽楔,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一持钉、第九天 我趴在偏房一處隱蔽的房頂上張望衡招。 院中可真熱鬧,春花似錦每强、人聲如沸始腾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽浪箭。三九已至,卻和暖如春辨绊,著一層夾襖步出監(jiān)牢的瞬間奶栖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工门坷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宣鄙,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓默蚌,卻偏偏與公主長得像冻晤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子绸吸,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容