Docker鏡像
一個host可以啓動多個容器,基於鏡像可在容器中啓動不同的應用。如果本地無此鏡像,docker可自動連接到docker registry上下載鏡像,存儲到本地文件系統(如overlay2)中。由於鏡像的格式是分層的,因此存儲鏡像的文件系統必須支持這種特殊的格式,也就是所謂的二層文件系統。
Docker是碼頭工人的意思,而鏡像可形象理解爲應用程序的集裝箱,碼頭工人docker負責裝卸集裝箱(image/application)。
Docker鏡像結構
Docker鏡像含有啓動容器所需的文件系統及其內容,因此,可用於創建並啓動docker容器。
-
鏡像採用分層構建機制,最底層爲bootfs,其上爲rootfs
-
bootfs:用於系統引導的文件系統,包括bootloader和kernel。容器啓動完成後,會被卸載以節約內存資源。
-
rootfs:位於bootfs之上,表現爲docker容器的根文件系統
-
傳統模式中,系統啓動之時,內核掛載rootfs時首先將其掛載爲只讀模式,完整性自檢完成後將其重新掛載爲讀寫模式
-
docker中,rootfs由內核掛載爲只讀模式,而後通過聯合掛載技術額外掛載一個可寫層。
-
-
-
Docker Image Layer
位於下層的鏡像稱爲父鏡像,最底層的稱爲基礎鏡像(base image)
最上層爲可寫層,其下的均爲“只讀”層
舉個例子:
在底層純淨的發行版如Debian之上,添加一個emacs層,這是一個獨立的應用層,如果需要額外的工具則需要在上面執行安裝操作比如安裝vim,安裝後可理解爲附加了一層vim的層級,該層級僅僅包含了vim。然後可再添加一個獨立的層級如apache。當啓動apache時,從下往上掛載疊加,並且三層都是隻讀的。如果需要讀寫操作,則在最上層容器的自有層次(container)進行,而其他層次是共享的。
一旦啓動完成,最底下的層(kernel)也將被移除。如果刪除容器,則容器自有的可寫層也被刪除。
鏡像的分層構建和聯合掛載,依賴專有的文件系統支撐。
Docker鏡像的文件系統
早期,使用的專有文件系統爲AUFS。而aufs的前身爲unionFS,其代碼很爛,因此當它申請到內核代碼樹時被拒絕。因此如果需要使用aufs,則自行打補丁。
而對於以穩定著稱的redhat/CentOS而言是不允許使用aufs的。Ubuntu是允許將aufs打包到內核中去,並且它也已經直接提供打好補丁的內核。故而早期如果要使用docker,只能使用ubuntu/debian系。
而overlayfs,也可以通過打補丁或者裝載內核模塊的方式,讓CentOS使用。
Docker還支持dm,不過它性能和穩定性很差,因此不再使用。早期CentOS7使用的是devicemapper,而新版的Docker中,CentOS7裝的是overlay2。
在實際使用過程中,爲了更大發揮docker的性能和支持更多的內核特性,建議使用ubuntu作爲容器的底層基礎設施。
Docker registry
Docker註冊庫,是鏡像的統一存儲位置。構建鏡像時,需要一個統一存儲的位置。當啓動鏡像時,docker daemon先嚐試從本地獲取鏡像,如果本地不存在鏡像則到registry中下載鏡像並保存到本地。如果沒有指定鏡像地址,則到docker hub中獲取。
一般而言,需要二次定製鏡像以符合自身業務需求。
Registry的組成部分:repository(一大堆倉庫) index(一個索引)
Repository
由某些特定的docker鏡像的所有迭代版本組成的鏡像倉庫。一個Registry這種可以存在多個Reopsitory
- Repository分爲“頂層倉庫”和“用戶倉庫”
- 用戶層庫名稱格式爲“用戶名/倉庫名”
- 每個層庫可以包含多個Tag,每個標籤對應一個鏡像
Index
- 維護用戶賬戶、鏡像的校驗以及公共命名空間的信息
- 相當於爲Registry提供了一個完成用戶認證等功能的檢索接口
一般的流程是,開發人員從公共registry中獲取鏡像,並定製打包成images並push到私有registry中。一旦push成功,便觸發相應的hook,自動deploy到響應的環境中。
雲原生 Cloud Native
傳統意義上,程序員的程序是針對某個開發環境而寫的,針對系統庫和編程接口來生成自己的代碼,稱爲系統原生。
如果面向雲環境開發的程序,調用雲環境提供的接口,爲了在雲環境上而運行的程序,稱爲雲原生。
容器或者雲,是封裝好的。它們不方便修改裏面的文件,因此可以通過環境變量賦值的方式來向容器傳遞信息。
而且是當配置文件啓動時,從環境變量自動加載並注入到容器中生成的。因此,可以通過環境變量來配置容器的啓動。
Docker Hub
鏡像的製作一般基於基礎鏡像(base image)來做的,而base image一般是docker hub官方手動製作的。
默認情況下,docker daemon是從docker hub上pull鏡像的,並且能存放用戶的第三方鏡像。
docker hub 作爲鏡像倉庫而存在。它支持以下功能:
-
auto builds:使用命令基於docker file來製作鏡像,定義好file之後通過docker build生成或者放置到自動構建的位置來製作,或者基於容器docker commit來手動製作
自動構建是通過聯動的方式來做的。Docker file可以放置到github的project的倉庫中,該倉庫和docker hub倉庫可建立關聯關係。Docker hub倉庫持續監控着github倉庫,如果github倉庫新加了docker file,則docker hub自動拖去並添加到倉庫中
-
Webhooks:自動構建功能的特性,觸發自動構建的動作
第三方鏡像倉庫:https://quay.io/
Docker鏡像製作
鏡像生成途徑:
- Dockerfile
- 基於容器製作
- Docker Hub automated builds
基於容器製作鏡像
方法:啓動一個容器,在容器之上做好自己需要的配置,然後通過docker commit製作鏡像。
Usage:docker commit [options] CONTAINER [REPOSITORY[:TAG]]
Name,shorthand | Default | Description |
---|---|---|
–author, -a | Author | |
–change, -c | Apply Dockerfile instruction to the created image | |
–message, -m | Commit message | |
–pause, -p | true | Pause container during commit |
例子:將busybox 加上html目錄和index.html,將此結果做成鏡像。日後每次啓動有會存在此文件。
-
啓動容器,提供文件後保存
root@eto:~# docker run --name b1 -it busybox / # mkdir -p /data/html / # echo "busybox http server" >> /data/html/index.html root@eto:~# docker commit -p b1 sha256:0f8cd6de017004598851b75b96fca52fe9bbbcf457701e28455e934edc475315
此時即可看到一個新鏡像,可以爲之打上標籤:
root@eto:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 0f8cd6de0170 About a minute ago 1.22MB
root@eto:~# docker tag 0f8cd6de0170 jaywin/httpd:v0.1-1
root@eto:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jaywin/httpd v0.1-1 0f8cd6de0170 3 minutes ago 1.22MB
可以爲一個鏡像打上多個標籤:
root@eto:~# docker tag 0f8cd6de0170 jaywin/httpd:latest
root@eto:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jaywin/httpd latest 0f8cd6de0170 3 minutes ago 1.22MB
jaywin/httpd v0.1-1 0f8cd6de0170 3 minutes ago 1.22MB
刪除一個鏡像,僅刪除了指定標籤的鏡像
root@eto:~# docker image rm jaywin/httpd:latest
Untagged: jaywin/httpd:latest
查看鏡像在啓動時,默認執行的命令,比如
root@eto:~# docker inspect busybox | grep Cmd -A3
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
--
"Cmd": [
"sh"
],
在創建鏡像時,改變原來鏡像默認運行的命令。可修改原有鏡像的基礎命令,修改其中的cmd指令
root@eto:~# docker commit -a "jaywin.com" -c 'CMD ["/bin/httpd","-f","-h","/data/html"]' -p b1 jaywin/httpd:v0.2
sha256:f5a014fe42903e6c527249a7a9208d5cb137772a4bdbaed68eca9bc1a9cf0089
運行:
root@eto:~# docker run --name t2 jaywin/httpd:v0.2
root@eto:~# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7389ad8062ea jaywin/httpd:v0.2 "/bin/httpd -f -h /d…" About a minute ago Up About a minute
root@eto:~# curl 172.17.0.2
busybox http server
基於dockerfile製作鏡像
鏡像推送
可以將本地製作好的鏡像,推送到registry中保存。常用的公有registry有docker hub官方和阿里雲提供的registry
docker hub
登錄到服務器上,不指定地址,則登錄到docker hub
root@eto:~# docker login -u jaywinz
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 hub中保持一致
root@eto:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jaywin/httpd v0.2 f5a014fe4290 17 minutes ago 1.22MB
root@eto:~# docker tag f5a014fe4290 jaywinz/httpd:v0.2-2
root@eto:~# docker push jaywinz/httpd:v0.2-2
The push refers to repository [docker.io/jaywinz/httpd]
bcefc70bb04a: Pushed
5b0d2d635df8: Mounted from library/busybox
v0.2-2: digest: sha256:b12533340a43375ca74fb21d80229d706981b73012095a331e55f1403b5b8d8a size: 734
由於網站在國外,速度較慢。
阿里雲
國內訪問比較快的鏡像地址,是阿里雲
可以登錄自己的阿里雲賬號,即可獲得專用的加速地址。將此地址寫到docker的配置文件中即可。
root@eto:~# cat /etc/docker/daemon.json
{
"exec-opts": ["native.cgrounpdriver=systemd"],
"registry-mirrors": ["https://e2615hzs.mirror.aliyuncs.com"]
}
root@eto:~# systemctl daemon-realod
root@eto:~# systemctl restart docker
可以根據操作指南,將鏡像託管到阿里雲
root@eto:~# docker login --username=15088132158 registry.cn-hangzhou.aliyuncs.com
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
root@eto:~# docker tag f5a014fe4290 registry.cn-hangzhou.aliyuncs.com/jaywinz/httpd:v0.2-2
root@eto:~# docker push registry.cn-hangzhou.aliyuncs.com/jaywinz/httpd:v0.2-2
The push refers to repository [registry.cn-hangzhou.aliyuncs.com/jaywinz/httpd]
bcefc70bb04a: Pushed
5b0d2d635df8: Pushed
v0.2-2: digest: sha256:b12533340a43375ca74fb21d80229d706981b73012095a331e55f1403b5b8d8a size: 734
推送鏡像時,如果不是推送到docker hub,則必須加上服務器地址,名稱空間和標籤。
鏡像的導入和導出
除了可通過docker registry進行鏡像分發,也能通過導入導出的方式進行鏡像分發。使用兩個命令
- docker save
- docker load
因此可以在已有鏡像的基礎上,打包鏡像。然後在另外的主機上解壓直接使用。
打包兩個鏡像:
root@eto:~# docker save -o myimages.gz jaywin/httpd:v0.1-1 jaywinz/httpd:v0.2-1
root@eto:~# ls
myimages.gz
傳送到另外的主機, 並導入:
root@eto2:~# docker load -i myimages.gz
5b0d2d635df8: Loading layer [==================================================>] 1.437MB/1.437MB
bcefc70bb04a: Loading layer [==================================================>] 5.12kB/5.12kB
Loaded image: jaywin/httpd:v0.1-1
Loaded image: jaywinz/httpd:v0.2-1
root@eto2:~# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jaywinz/httpd v0.2-1 f5a014fe4290 48 minutes ago 1.22MB
jaywin/httpd v0.1-1 0f8cd6de0170 6 days ago 1.22MB