GitHub: https://github.com/QingyaFan
制作鏡像
初學(xué)docker總是有點(diǎn)疑惑菊卷,鏡像是什么?容器又是什么宝剖?它們之間有什么區(qū)別洁闰,它們之間有什么聯(lián)系?怎么制作鏡像万细,怎么運(yùn)行容器扑眉?在這篇文章里就來總結(jié)一下。
一赖钞、什么是鏡像腰素,什么是容器
鏡像(docker image)就是一個(gè)打包好的安裝文件,鏡像中不僅包含你的應(yīng)用雪营,還包含應(yīng)用運(yùn)行需要的所有依賴和環(huán)境弓千,上至一些library,下至操作系統(tǒng)献起。而容器(docker container)就是我們?cè)赿ocker Engine環(huán)境中啟動(dòng)的鏡像實(shí)例洋访,容器和操作系統(tǒng)中其它進(jìn)程沒有區(qū)別,只不過擁有自己的網(wǎng)絡(luò)和存儲(chǔ)谴餐,與系統(tǒng)中其它的進(jìn)程實(shí)現(xiàn)隔離姻政,同時(shí)也與其它容器隔離。
鏡像名稱的格式是url/directory/name:tag
岂嗓,例如sample.com/busybox:v3.2
汁展,當(dāng)我們拉取該鏡像時(shí),docker engine會(huì)嘗試從sample.com
拉取該鏡像厌殉,如果鏡像名字中沒有指定url善镰,會(huì)從docker engine配置中的鏡像倉庫拉取,默認(rèn)docker hub年枕;名字中的tag并不是必須的炫欺,如果不指定,默認(rèn)為"latest"熏兄。
已經(jīng)有很多人制作了很多應(yīng)用的鏡像品洛,共享在了DockerHub或者其他公共鏡像倉庫(例如國內(nèi)的阿里云鏡像倉庫)树姨,我們沒有必要重復(fù)造輪子,DockerHub就像GitHub一樣桥状,我們可以從中拉取已有鏡像來使用帽揪,如果現(xiàn)有鏡像不能滿足需求,就需要自己制作鏡像辅斟,那么下面我們來說說制作鏡像的方法转晰。
二、制作鏡像
docker制作鏡像有兩種方法:
- 利用dockerfile士飒,將構(gòu)建流程寫入dockerfile文件查邢,然后執(zhí)行,
docker build -f docker_file_name
酵幕; - 現(xiàn)有容器基礎(chǔ)上構(gòu)建扰藕,
docker commit container_name/container_id new_image_name
。
2.1 dockerfile
dockerfile是一個(gè)配置文件芳撒,它告訴docker如何構(gòu)建鏡像邓深,docker會(huì)根據(jù)dockerfile中的指令,一步一步的完成鏡像笔刹。一個(gè)典型的nodejs后端API項(xiàng)目dockerfile如下:
FROM base_image
WORKDIR /var/apps/app_name
# 安裝項(xiàng)目依賴包
COPY ./package.json ./
RUN cnpm install --production
# 拷貝項(xiàng)目文件
COPY ./ ./
EXPOSE 3000
CMD [ "node", "app.js" ]
FROM
關(guān)鍵字確定了基礎(chǔ)鏡像芥备,很多時(shí)候,我們不需要自己從頭開始制作舌菜,我們可以基于已有的輪子來做门躯,基礎(chǔ)鏡像可以是操作系統(tǒng),也可以是安裝了一些依賴的操作系統(tǒng)酷师,后面的命令都是基于這個(gè)基礎(chǔ)讶凉,在這個(gè)基礎(chǔ)鏡像提供的環(huán)境中執(zhí)行命令,進(jìn)行操作山孔。例如WORKDIR
是在鏡像中指定了一個(gè)項(xiàng)目目錄懂讯,如果目錄不存在,會(huì)自動(dòng)創(chuàng)建台颠;COPY
是將文件拷貝到鏡像內(nèi)褐望,這些文件時(shí)docker開始構(gòu)建鏡像時(shí)讀取的,docker開始構(gòu)建鏡像時(shí)會(huì)讀取dockerfile所在目錄的所有文件至docker engine中串前,不過有一個(gè).dockerignore
文件可以配置docker忽略讀取的文件瘫里,類似于.gitignore
,./
當(dāng)前路徑即表示dockerfile所在的文件夾荡碾;RUN
表示在鏡像中執(zhí)行shell命令谨读,cnpm install --production
則表示安裝nodejs項(xiàng)目的依賴;接下來又有一個(gè)copy坛吁,拷貝所有項(xiàng)目文件劳殖;EXPOSE
則是暴露項(xiàng)目的監(jiān)聽端口铐尚;最后CMD
表示鏡像啟動(dòng)時(shí)執(zhí)行的命令壁晒,這個(gè)命令必須是不被掛起的穷吮,不能以Service的形式,否則容器啟動(dòng)就會(huì)馬上退出封断。
這里大家可能會(huì)有疑問矛缨,為什么copy分為兩部分爹脾,不在一個(gè)copy命令中一次性拷貝完成呢?這是因?yàn)閐ocker鏡像是分層構(gòu)建的箕昭,每個(gè)命令都對(duì)應(yīng)著鏡像的一層灵妨,而在兩次構(gòu)建中某一層沒有改變時(shí),則不會(huì)重新構(gòu)建這一層盟广,nodejs項(xiàng)目的依賴包很少變動(dòng),所以選擇放在鏡像的下一層瓮钥,其它代碼文件頻繁變動(dòng)筋量,所以選擇和package.json的拷貝分開。
2.2 docker commit
在一個(gè)運(yùn)行的容器中碉熄,有時(shí)候你需要添加一些依賴桨武,或者修改某些文件,想下次啟動(dòng)容器時(shí)依然保留改動(dòng)锈津,不想從頭構(gòu)建呀酸,那可以使用docker commit
基于容器生成一個(gè)鏡像。
docker commit [OPTIONS] container_id_or_name image:tag
下次啟動(dòng)容器直接從image:tag
這個(gè)鏡像啟動(dòng)即可琼梆。
注:在容器中做了修改性誉,需要重新啟動(dòng)容器,然后執(zhí)行
docker commit
才能生效茎杂。
三错览、管理鏡像
鏡像作為一種資源,docker提供了方便的管理方法煌往,具體說來倾哺,假設(shè)我們機(jī)器上有一個(gè)名為busybox:test
的鏡像,我們可以使用下面的方法對(duì)其進(jìn)行增刪改查:
- 查刽脖,使用
docker images
或docker image ls
查看所有鏡像的列表羞海; - 使用
docker tag busybox:test yet_another_name:new_tag
取一個(gè)別名,這時(shí)再docker images
會(huì)發(fā)現(xiàn)多了一個(gè)鏡像曲管,不要被表象迷惑却邓,該操作并不會(huì)重新創(chuàng)建鏡像,而是添加了一個(gè)引用院水,就像劉備和劉皇叔都是劉備一樣申尤; - 使用
docker rmi busybox:test
刪除鏡像癌幕; - 使用
docker pull busybox:test
拉取鏡像; - 使用
docker push busybox:test
推送鏡像到鏡像倉庫昧穿。
四勺远、總結(jié)
兩種鏡像制作方法,建議經(jīng)常使用第一種时鸵。制作完鏡像胶逢,就可以啟動(dòng)容器了,啟動(dòng)容器也有很多選項(xiàng)饰潜,很多時(shí)候啟動(dòng)的容器并不會(huì)完全按照你的設(shè)想工作初坠,這就要求你必須指定正確的啟動(dòng)選項(xiàng),尤其是容器需要額外的存儲(chǔ)和網(wǎng)絡(luò)時(shí)彭雾,這一部分內(nèi)容也比較多碟刺,下一篇再講。