title: Docker修煉之旅(二)
date: 2019-06-26 15:19:11
tags:
- Docker
categories:
- Study
- Docker
Docker鏡像和倉庫,寫寫Docker鏡像的一些相關(guān)命令,還有如何通過編寫Dockerfile文件構(gòu)建自己的鏡像
繼續(xù)Docker學(xué)習(xí),這一篇主要寫Docker鏡像
Docker鏡像是什么
Docker鏡像是由文件系統(tǒng)疊加而成烈疚。最底端是一個文件引導(dǎo)系統(tǒng)吏奸,即bootfs荆秦。Docker用戶不會與引導(dǎo)文件系統(tǒng)有直接的交互凹嘲。Docker鏡像的第二層是root文件系統(tǒng)rootfs,通常是一種或多種操作系統(tǒng)灌旧,例如ubuntu等。
在Docker中绰筛,文件系統(tǒng)永遠(yuǎn)都是只讀的枢泰,在每次修改時,都是進(jìn)行拷貝疊加從而形成最終的文件系統(tǒng)铝噩。Docker稱這樣的文件為鏡像衡蚂。一個鏡像可以迭代在另一個鏡像的頂部。位于下方的鏡像稱之為父鏡像,最底層的鏡像稱之為基礎(chǔ)鏡像毛甲。最后年叮,當(dāng)從一個鏡像啟動容器時,Docker會在最頂層加載一個讀寫文件系統(tǒng)作為容器玻募。
Docker文件系統(tǒng)層圖:
Docker鏡像一些相關(guān)命令
列出本地鏡像
我們可以用docker images
列出所有本地的鏡像只损,可以看到列出的鏡像有一個TAG
標(biāo)簽屬性,像圖中的Ubuntu鏡像七咧,就有三種標(biāo)簽14.04跃惫、18.04、latest
艾栋,分別代表Ubuntu的不同版本爆存,這種標(biāo)簽屬性機(jī)制使得在同一個倉庫里可以存儲多個鏡像』壤可以在拉取鏡像的時候通過冒號:
指定tag先较,如:docker run ubuntu:14.04或docker pull Ubuntu:14.04
本地的鏡像保存的位置在/var/lib/docker/
目錄下。每個鏡像都保存在Docker所采用的存儲驅(qū)動目錄下遥诉。本地容器都保存在/var/lib/docker/containers/
目錄下拇泣。
查找、拉取鏡像
可以用docker search <鏡像名>
命令在Docker Hub上面查找鏡像矮锈。
比如我們這里查找一下fedora
基礎(chǔ)鏡像霉翔,可以看到列出的Docker Hub上面的所以fedora鏡像,包括每個鏡像的描述苞笨、收藏量债朵、是否是官方鏡像等屬性,然后供我們自己選擇進(jìn)行拉取瀑凝。
我們這里就選擇fedora
官方鏡像進(jìn)行拉取序芦,使用docker pull
命令,如下圖粤咪。
拉取了鏡像后谚中,就可以用這個鏡像來構(gòu)造我們的容器,容器的操作具體見上一篇文章寥枝。
刪除鏡像
可以通過docker rmi
命令刪除鏡像宪塔,前提是這個鏡像沒有被容器使用(包括運(yùn)行或停止的容器)
如下圖示,我們嘗試刪除被運(yùn)行容器和已停止容器使用的鏡像囊拜,均失敗某筐。
只有把使用了該鏡像的容器刪除后,才能刪除鏡像冠跷。
構(gòu)建鏡像
一般來說南誊,我們不是真正的"創(chuàng)建"新鏡像身诺,而是基于一個已有的基礎(chǔ)鏡像,如Ubuntu或fedora等抄囚,構(gòu)建新鏡像而已霉赡。
構(gòu)建鏡像一般有兩種方法:
- 通過docker commit命令
- 使用docker build命令和Dockerfile文件
使用docker commit命令
先說第一種方法。docker commit
命令怠苔,可以把這種方法視為我們在往版本控制系統(tǒng)里提交變更同廉。
我們首先先用Ubuntu鏡像構(gòu)建一個容器,如下圖柑司,我們可以看到迫肖,創(chuàng)建的容器是沒有安裝vim
的,我們可以用apt-get install
命令安裝一下
可以看到攒驰,我們對最基礎(chǔ)的Ubuntu鏡像做了一些改變蟆湖,安裝了vim
軟件,不過這只是這個容器安裝了而已玻粪,再用Ubuntu鏡像創(chuàng)建另一個新容器隅津,還得再重新裝一遍vim
,這未免太過麻煩劲室。于是為了解決這個問題伦仍,我們可以把安裝了vim
的容器的狀態(tài)保存下來,生成一個新鏡像很洋,這樣就不必重新安裝vim
了充蓝。
為了完成這項工作,我們用到了docker commit
命令喉磁,首先先用exit
命令退出容器谓苟,然后獲取剛剛運(yùn)行的容器的ID(通過docker ps -l -q
命令獲取),然后用docker commit <容器ID> <新鏡像名>
命令創(chuàng)建新鏡像协怒。
我們這里使用docker commit
成功創(chuàng)建了一個新鏡像ubuntu:installed-vim
涝焙,可以通過docker images
查看是否創(chuàng)建成功。
這里關(guān)于docker commit命令在說兩句孕暇,這個命令應(yīng)該和git commit差不多仑撞,可以使用-m參數(shù)添加標(biāo)注,而且提交的部分只是創(chuàng)建容器的鏡像和容器的當(dāng)前狀態(tài)之間有差異的部分妖滔,這使得該更新十分輕量
使用Dockerfile文件
實際構(gòu)建鏡像中派草,docker commit命令方法用的較少,大多都是編寫Dockerfile文件铛楣,然后用docker build命令創(chuàng)建新鏡像。Dockerfile文件基于DSL語法
流程如下:
- 首先先創(chuàng)建一個目錄艺普,這個目錄就是我們的構(gòu)建環(huán)境簸州,要把Dockerfile放在該目錄下鉴竭,然后再在該目錄直接運(yùn)行
docker build
命令創(chuàng)建鏡像。 - 然后在該目錄下創(chuàng)建編寫Dockerfile文件
我們這里創(chuàng)建了一個Docker_study
文件夾岸浑,然后開始編寫Dockerfile文件搏存,文件具體代碼如下。
# version: 0.0.1
FROM ubuntu:14.04
MAINTAINER Miracle778 "Yiitao@163.com"
RUN apt-get update
RUN apt-get install -y nginx
RUN echo 'Hi, I am in Your Container'\
>/usr/share/nginx/html/index.html
EXPOSE 80
Dockerfile文件由一系列指令和參數(shù)組成矢洲。每天指令璧眠,如FROM,都必須是大寫字符读虏,且后邊要跟隨一個參數(shù)责静,如:FROM ubuntu:14.04
。Dockerfile文件中的指令會按順序從上到下執(zhí)行盖桥,所以要合理安排順序
每條指令都會創(chuàng)建一個新的鏡像層并對鏡像進(jìn)行提交灾螃,大致按照如下流程執(zhí)行。
- Docker從基礎(chǔ)鏡像運(yùn)行一個容器
- 執(zhí)行一條指令揩徊,對容器進(jìn)行修改
- 執(zhí)行類似于docker commit的指令腰鬼,提交一個新的鏡像層
- Docker基于新提交的鏡像運(yùn)行一個新容器
- 執(zhí)行Dockerfile中的下一條指令,重復(fù)上面2-4步過程塑荒,直至所有指令結(jié)束
從上面流程中可以看出熄赡,如果Dockerfile由于某一條指令執(zhí)行失敗了,那么你可以得到一個執(zhí)行完上一條指令后的可以使用的鏡像齿税,這對調(diào)試非常有用彼硫,可以利用這個鏡像運(yùn)行一個具備交互功能的容器,然后執(zhí)行你Dockerfile文件中失敗的指令偎窘,查看失敗原因乌助。
比如我們這里把上面Dockerfile文件中的第五行內(nèi)容改一下,把nginx
改為nignx
陌知,然后運(yùn)行下docker build
命令他托,關(guān)于docker build
命令我們等下在后面再講。這里先關(guān)注如何調(diào)試仆葡。
如上圖赏参,如我們所預(yù)期那樣,改變了Dockerfile文件的第五行的命令后沿盅,build過程果然報錯把篓,而且得到了上一條命令運(yùn)行完的容器ID,接下來我們運(yùn)用這個容器ID進(jìn)行調(diào)試腰涧。
我們使用docker run -i -t
命令以交互式模式進(jìn)入該容器韧掩,然后執(zhí)行下Dockerfile文件中報錯的指令,這里是apt-get install -y nignx
窖铡,然后觀察下結(jié)果疗锐。
如上圖示坊谁,確定了出錯原因,并且可以通過在容器中執(zhí)行改正指令達(dá)到調(diào)試效果滑臊,最終我們確定是
apt-get install -y nignx
命令的nginx
拼寫錯了口芍,于是可以在Dockerfile文件中修改過來。這就是調(diào)試過程雇卷。
下面我們用改正過后的正確的Dockerfile文件進(jìn)行鏡像創(chuàng)建鬓椭。執(zhí)行過程如下圖
我們來解釋解釋該步驟里的一些過程。
看到創(chuàng)建命令:docker build -t="miracle778/dockerfile_study" .
該命令執(zhí)行過程為先在本地目錄中尋找Dockerfile文件(也可以指定github地址上的Dockerfile文件)关划,找到后安裝Dockerfile命令一步步執(zhí)行小染。
-t 參數(shù)是指定鏡像名字,一般為:<倉庫名>/<鏡像名:標(biāo)簽>祭玉,這里名字不能有大寫字母
最后要注意的是氧映,命令后面那個點 .,不要忘記了
然后是Dockerfile文件里的指令解釋
代表注釋
FROM指令指定一個已經(jīng)存在的鏡像脱货,后續(xù)指令都將基于該鏡像進(jìn)行岛都,這個鏡像被稱為基礎(chǔ)鏡像
MAINTAINER 指令會告訴Docker該鏡像的作者是誰,以及作者的電子郵件地址
EXPOSE指令告訴Docker該容器內(nèi)的應(yīng)用程序?qū)褂萌萜鞯闹付ǘ丝?br> RUN 命令會在當(dāng)前鏡像中運(yùn)行指定的命令
默認(rèn)情況下振峻,RUN指令會在shell中使用命令包裝器/bin/sh -c來執(zhí)行臼疫。
如果是在一個不支持shell的平臺上運(yùn)行或者不希望在shell中運(yùn)行
也可以使用exec格式的RUN指令
RUN ["apt-get", "install" ,"-y" , "nginx"]
這種方式中,要使用一個數(shù)組來指定要運(yùn)行的命令和傳遞給該命令的參數(shù)
Dockerfile還有其他一些命令扣孟,后面的學(xué)習(xí)使用中會逐步用到烫堤,到時候再現(xiàn)學(xué)吧。
這里給個鏈接凤价,隨便百度Dockerfile命令大全得來的鸽斟,https://www.cnblogs.com/dazhoushuoceshi/p/7066041.html
然后再談?wù)凞ockerfile和構(gòu)建緩存
我們可以從上面的Dockerfile執(zhí)行流程和那個調(diào)試?yán)涌吹剑珼ocker鏡像構(gòu)建過程中利诺,每一步都會將結(jié)果提交為鏡像富蓄。換句話說,就是會把之前的鏡像層看做緩存慢逾。這樣會使得構(gòu)建鏡像節(jié)省很多時間立倍。
但有時候鏡像構(gòu)建過程中可能不需要使用緩存,這時就需要在docker build命令里加入--no-cache
標(biāo)志
講了這么多侣滩,快來使用下新鏡像吧
使用命令docker run --name Docker_study -d -p 80 miracle778/dockerfile_study nginx -g "daemon off;"
創(chuàng)建一個新容器口注,這句命令稍后再來解析,現(xiàn)在先看到命令執(zhí)行后的結(jié)果
可以看到君珠,容器創(chuàng)建好后寝志,成功運(yùn)行,建立了一個宿主機(jī)32772端口到docker容器80端口的映射,也就是說澈段,我們訪問本地的32772端口悠菜,就能訪問到容器的80端口,也就是這里的nginx服務(wù)器败富。
我們再回到Dockerfile文件中的最后一條RUN命令,是向/usr/share/nginx/html/index.html
文件里寫入了Hi, I am in Your Container
這句內(nèi)容摩窃。所以我們訪問docker容器80端口預(yù)期的結(jié)果應(yīng)該是返回Hi, I am in Your Container
我們通過curl命令測試一下兽叮,如下圖,結(jié)果符合預(yù)期猾愿。
現(xiàn)在我們再來看到使用新鏡像生成新容器的命令鹦聪,主要是看到-p
參數(shù),這個參數(shù)用來控制Docker在運(yùn)行時應(yīng)該公開哪些網(wǎng)絡(luò)端口給外部蒂秘,這個參數(shù)會覆蓋掉Dockerfile中EXPOSE
指定的端口泽本。而且有兩種分配方法,一種是Docker隨機(jī)分配一個比較大的端口號來映射到容器的80端口上姻僧,也就是我們圖中這里使用的方法;另一種方法是可以指定宿主機(jī)端口來映射到容器的指定端口规丽,如:-p 7777:80
就是把宿主機(jī)的7777端口映射給Docker容器的80端口。
然后我們在看到命令最后部分的nginx -g "daemon off;"
這里撇贺,這樣寫會以前臺運(yùn)行的方式啟動nginx赌莺,這里可能有點好奇為什么要這樣寫,如果不這么寫的話松嘶,可能會導(dǎo)致run
命令執(zhí)行完創(chuàng)建好容器后艘狭,容器自動退出的情況,這里我也查了查資料翠订,出現(xiàn)這種情況的原因見下巢音。
Docker 容器啟動時,默認(rèn)會把容器內(nèi)部第一個進(jìn)程尽超,也就是pid=1的程序官撼,作為docker容器是否正在運(yùn)行的依據(jù),如果 docker 容器pid=1的進(jìn)程掛了橙弱,那么docker容器便會直接退出歧寺。
Docker未執(zhí)行自定義的CMD之前,nginx的pid是1棘脐,執(zhí)行到CMD之后斜筐,nginx就在后臺運(yùn)行,bash或sh腳本的pid變成了1蛀缝。
所以一旦執(zhí)行完自定義CMD顷链,nginx容器也就退出了。
具體見:https://blog.csdn.net/youcijibi/article/details/88781014
總結(jié)
這篇文章主要是講些Docker鏡像相關(guān)的命令以及構(gòu)造自己的Docker鏡像的方法屈梁,重點是通過Dockerfile
文件加docker build
命令構(gòu)建自己的鏡像嗤练,其中Dockerfile
文件的編寫語法這里只講到一點榛了,其他的ADD | ENTRYPOINT | VOLUME | CMD
等命令這里都沒有提到,應(yīng)該會在后面的搭建具體應(yīng)用時用到煞抬,到時候再寫霜大。