一、基本介紹
-
docker鏡像是容器啟動的基礎,鏡像里面包含容器啟動所需要的文件系統及其內容。docker鏡像采用分層構建的機制,這種分層大致分為兩部分,一部分是最底層的引導文件系統bootfs,類型有aufs,btffs或者overlay2等;另一部分真正讓用戶來構建用戶空間並運行進程的容器稱為rootfs。
-
bootfs:用於引導文件系統,包括BootLoader和kernel,容器啟動完成后會被卸載以節約內存資源。(這里說的卸載,是從內存中移除而不是刪除)
-
rootfs:位於bootfs之上,表現為docker的根文件系統,比如/dev、/bin之類。
- 傳統模式中,系統啟動時,內核掛載rootfs時會先將其掛在為”只讀“模式,自檢完成后將其重新掛載為讀寫模式。
- docker中,rootfs由內核掛載為”只讀“模式,而后通過”聯合掛載“技術額外掛載一個”可寫“層。(我們在docker container中的操作就是可寫層)
-
-
分層構建最底層的是基礎鏡像,位於上層的鏡像稱為父鏡像(系統層),每添加一個鏡像都是一個獨立的層次。最上層為“可寫層”。其它均為“只讀”層。刪除容器的時候,可寫層會一並被刪除

-
docker registry用於保存docker鏡像,包括鏡像的層次結構和元數據,用戶可以自建registry,也可以使用官方的docker hub。registry里面的鏡像通常由開發人員制作,而后推送至registry上保存,以供用戶使用。另外,為了安全起見,docker daemon要求docker registry必須是https的,如果不是就需要配置docker daemon。registry分類如下:
- Sponsor registry:第三方的Registry,供客戶和docker社區使用
- Mirror registry:第三方的Registry,只讓客戶使用
- Vendor registry:由發布docker鏡像的供應商提供的registry。如Redhat自己的registry
- private registry:通過設有防火牆和額外安全層的私有實體提供的registry。
-
repository是由某個特定docker鏡像的所有迭代版本所組成,一個registry可以存在多個repository。repository分為頂層倉庫和用戶倉庫。
- 頂層倉庫是直接由倉庫名命名的,一般用docker search搜索的第一個就是頂層倉庫
- 用戶倉庫名稱格式為:用戶名或者成為項目名/倉庫名。一般除了docker search搜索的第一個,其它的都是用戶倉庫。
-
鏡像的生成途徑
- 通過編寫dockerfile
- 基於容器制作:也就是把容器最上層的可寫層提交成一個新的鏡像。比如起了一個centos的容器,然后在上面搭建一個nginx,最后用docker container commit提交完就是一個nginx的鏡像了。
- docker hub automated builds:這個其實也是基於dockerfile構建的。首先在docker hub上面設置與GitHub的集成,然后本地寫完dockerfile后推到GitHub上面,docker hub檢測到GitHub的變化就會觸發build,生成新的鏡像。
二、鏡像制作
1. 基於dockerfile制作鏡像
2. 基於容器制作鏡像(第一種)
a) 就以busybox鏡像起一個容器,創建httpd啟動所需要的文件
[root@docker1 ~]# docker run --name busy01 -it busybox
/ # mkdir -p /data/html
/ # echo 'this is a test ' >/data/html/index.html
/ # ps
PID USER TIME COMMAND
1 root 0:00 sh
7 root 0:00 ps
/ # which httpd
/bin/httpd
b) 此時不要退出本窗口,另外開一個終端窗口進行鏡像制作。
上面使用ps命令可以看到,PID為1的進程是sh,容器中PID為1的進程就相當於我們宿主機的systemd進程,1進程是bash,它運行完就會結束的,PID為1的進程結束也就意味着容器就exit了。所以上面運行busybox容器的窗口是不可以關閉也不可以放在后台運行的。這里就順便再提一下應用程序的運行:如果想讓一個應用類的容器長久的運行下去,要么起一個類似busybox的容器,然后前台運行一個應用(比如httpd:httpd -f -h /data/html),這個窗口永遠不能關閉;要么在把容器的CMD設置為前台運行應用的命令(也就是設置應用的PID為1)。
c) 我們先看下busybox的CMD,可看到這個容器的CMD是sh。
[root@docker1 ~]# docker inspect busy01 | grep Cmd -A1
"Cmd": [
"sh"
d) 基於busybox鏡像重新commit一個CMD為httpd的鏡像。
[root@docker1 ~]# docker commit -c 'CMD ["/bin/httpd","-f","-h","/data/html"]' -p busy01 hamerle/httpd:v1
# -c:以列表的形式修改dockerfile的指令。此例只修改CMD指令,使新容器CMD指令為httpd(也就是PID為1的進程是httpd),之前是sh。
# -p:提交過程中暫停容器的運行,防止文件保存的不完整。
# -p的后面跟的要操作容器的名字,最后是提交后生成新鏡像的名字和tag。
[root@docker1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hamerle/httpd v1 099c89327481 2 minutes ago 1.2MB
busybox latest 64f5d945efcc 3 weeks ago 1.2MB
e) 以這個新鏡像創建一個httpd的容器,然后訪問httpd服務
[root@docker1 ~]# docker run --name httpd01 -d hamerle/httpd:v1
[root@docker1 ~]# docker inspect httpd01 | grep Cmd -A4
"Cmd": [
"/bin/httpd",
"-f",
"-h",
"/data/html"
[root@docker1 ~]# docker inspect httpd01 | grep IPAddress
"IPAddress": "172.17.0.3",
[root@docker1 ~]# curl 172.17.0.3
this is a test # 訪問成功
3. 基於容器制作鏡像(第二種)
在公司使用openjdk做基礎環境啟動的java程序莫名其妙的有問題,所以就萌生想法自己手動制作一個jdk環境。
a) 首先拉取centos鏡像並啟動容器
[root@docker1 ~]# docker pull centos:centos7.4.1708
[root@docker1 ~]# docker run --name jdk -itd centos:centos7.4.1708
b) 上傳jdk包到宿主機並解壓,然后拷貝到容器內部
[root@docker1 src]# pwd
/usr/local/src
[root@docker1 src]# tar xf jdk-8u201-linux-x64.tar.gz
[root@docker1 src]# docker cp -a /usr/local/src/jdk1.8.0_201/ jdk:/usr/local
c) 登入docker配置jdk
[root@docker1 src]# docker exec -it jdk /bin/bash
[root@cc8aaa0096bf /]# ln -s /usr/local/jdk1.8.0_201/bin/java /usr/bin/java
[root@cc8aaa0096bf /]# echo -e 'export JAVA_HOME=/usr/local/jdk\nexport CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar\nexport PATH=$JAVA_HOME/bin:$PATH' >>/etc/profile
[root@cc8aaa0096bf /]# source /etc/profile
d) 然后以現在的docker容器commit一個jdk基礎鏡像出來。新的名字以倉庫名的格式
[root@docker1 src]# docker commit -m 'install jdk' -a 'hamerle' jdk hamerle/centos7.4:jdk
[root@docker1 src]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hamerle/centos7.4 jdk 23a3a5d00138 About a minute ago 593MB
三、鏡像分享
-
鏡像分享至docker hub
- 注冊hub.docker.com的賬號
- 點擊"Repositories"菜單,然后點擊"Create Repository +"來創建一個倉庫,創建完成后瀏覽器的窗口不要關閉


* 首先注冊阿里雲的賬號
* 點擊"控制台"菜單,然后上面的搜索框搜索"容器鏡像服務 控制台",首次使用需要同意開通容器鏡像服務,然后點擊"創建鏡像倉庫",使用命名空間(也就是你的用戶名),創建過程還需要創建registry的密碼,創建完成后瀏覽器窗口不要關閉。



四、鏡像導入導出
# 這就以上面制作的hamerle/httpd:v1和v2為例,打包在一起導出供docker2使用
[root@docker1 ~]# docker save -o httpd_images.gz hamerle/httpd:v1 registry.cn-shanghai.aliyuncs.com/hamerle/httpd:v2
# -o:導出到某個文件。
[root@docker1 ~]# ll httpd_images.gz
-rw------- 1 root root 1432576 Jun 10 13:42 httpd_images.gz
# 將images拷貝到docker2上面,然后導入使用
[root@docker1 ~]# scp httpd_images.gz 10.0.0.12:/root
[root@docker2 ~]# ll httpd_images.gz
-rw------- 1 root root 1432576 Jun 10 13:52 httpd_images.gz
[root@docker2 ~]# docker load -i httpd_images.gz
# 從某個文件導入
[root@docker2 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hamerle/httpd v1 099c89327481 4 days ago 1.2MB
registry.cn-shanghai.aliyuncs.com/hamerle/httpd v2 099c89327481 4 days ago 1.2MB
寫作不易,轉載請注明出處,謝謝~~