镜像制作大法
鏡像制作大法
一、前言
上一節(jié)《程序員背鍋救星-docker》中,我們講述了docker最基本的概念以及鏡像、容器以及倉庫的概念和使用,還包含了實踐內(nèi)容,我們通過拉取centos鏡像,創(chuàng)建容器并且進入容器對linux系統(tǒng)進行操作;但是那只是利用了倉庫中的鏡像,然后創(chuàng)建容器進行操作的,那我們?nèi)绻枰约旱溺R像改怎么做呢?這次就和大家一起看看鏡像是怎么制作的~
二、制作鏡像
一般制作鏡像有兩種方式,一種是基于commit命令,另外一種是基于dockerfile創(chuàng)建鏡像;
過程如下圖所示:
對于這兩種創(chuàng)建鏡像的方式,我們會實地操作一下,并且會區(qū)分一下兩種鏡像創(chuàng)建的優(yōu)點缺點;
一般在工作中,會采用第二種方式,至于為什么不采用第一種,后面細說~
<1>基于commit命令
基于commit命令
命令:
docker commit :從容器創(chuàng)建一個新的鏡像。
docker?commit?[OPTIONS]?CONTAINER?[REPOSITORY[:TAG]]OPTIONS說明:
- -a :提交的鏡像作者;
- -c :使用Dockerfile指令來創(chuàng)建鏡像;
- -m :提交時的說明文字;
- -p :在commit時,將容器暫停。
實踐:
按照之前《程序員背鍋救星-docker》中的實例,我們把這個容器制作成一個新的鏡像;
1、拉取鏡像
docker?pull?centos:centos72、運行鏡像
docker?run?-itd?--name?centos-test?centis:centos73、進入容器并安裝gcc、vim
4、在vim中編寫C代碼并編譯運行
int?main()
{
????printf("this?is?test\n");
????return?0;
}
5、退出容器
exit6、獲取容器
docker?pa?-a7、從容器中制作鏡像
docker?image?10ba02adb18f8、再次制作容器
docker?run?-it?--name?test?mycentos:V1?/bin/bash進去發(fā)現(xiàn),我們之前所有的環(huán)境都存在,證明我們的鏡像制作的很成功
以上就是使用commit制作docker進行全部過程啦~
<2>基于dockerfile
基于dockerfile
1、dockerfile概念
Dockerfile是由一系列命令和參數(shù)構(gòu)成的腳本,這些命令應(yīng)用于基礎(chǔ)鏡像并最終創(chuàng)建一個新的鏡像。它們簡化了從頭到尾的流程并極大的簡化了部署工作。Dockerfile從FROM命令開始,緊接著跟隨者各種方法,命令和參數(shù)。其產(chǎn)出為一個新的可以用于創(chuàng)建容器的鏡像。
Dockerfile由一行行命令語句組成,支持#注釋。一般分為四個部分:基礎(chǔ)鏡像,維護者信息,鏡像操作指令和容器啟動時執(zhí)行指令
2、Dockerfile 命令
下面簡單的介紹幾個命令:
FROM
指明構(gòu)建的新鏡像是來自于基礎(chǔ)鏡像是什么,比如:
FROM?gcc:latest
RUN
用于執(zhí)行后面跟著的命令行命令,有兩種格式:
shell 格式:RUN <命令行命令>(終端操作命令一樣),例如:
RUN?mkdir?tmp
exec 格式:RUN ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"],例如:
RUN?["./test"]
COPY
拷貝文件或目錄到鏡像中,COPY...,例如:
COPY?test.cpp?/home/CPP
ADD
拷貝文件或目錄到鏡像中,ADD...例如:
ADD?test.cpp?/home/CPP
如果是URL或壓縮包,會自動下載或自動解壓。
WORKDIR
為RUN、CMD、ENTRYPOINT以及COPY和AND設(shè)置工作目錄,例如:
WORKDIR?/home/CPP
CMD
啟動容器時執(zhí)行的Shell命令,例如:
CMD?[“./test”]
- CMD 在docker run 時運行。
- RUN 是在 docker build。
注:如果 Dockerfile 中如果存在多個 CMD 指令,僅最后一個生效。
ENV
設(shè)置環(huán)境變量,定義了環(huán)境變量,那么在后續(xù)的指令中,就可以使用這個環(huán)境變量。
格式:
ENV?<key>?<value>
基本的命令就是這些了,對于我們構(gòu)建一個鏡像也差不多了,后續(xù)需要其他命令,可以自行學習~
實踐
構(gòu)建一個運行C++程序的鏡像
1、編寫C++代碼
#include?<iostream>#include?<unistd.h>
using?namespace?std;
int?main()
{
????while(1)
????{
????????sleep(1);
????????cout<<"this?is?test"<<endl;
????}
????return?0;
}
2、編寫dockerfile
FROM?codenvy/cpp_gccRUN?mkdir?/home/test
ADD?test.cpp?/home/test
WORKDIR?/home/test
RUN?g++?test.cpp
CMD?["./a.out"]
3、創(chuàng)建鏡像
執(zhí)行命令:
docker?build?-f?./test_dockerfile?-t?test_cpp_dockerfile?.如果提示下面的錯誤:
?--->?Running?in?de73d0b0da3emkdir:?cannot?create?directory?‘/home/test’:?Permission?denied
The?command?'/bin/sh?-c?mkdir?/home/test'?returned?a?non-zero?code:?1
需要在dockerflie中加上
USER?root5、查看鏡像是否創(chuàng)建成功
docker?images6、運行容器
docker?run?test_cpp_dockerfile我們會發(fā)現(xiàn)我們的程序運行正常,沒有異常。
三、總結(jié)
這就是我們一般使用這兩種方式構(gòu)建鏡像,但是我們一般使用**Dockerfile **進行創(chuàng)建,原因如下:(采用網(wǎng)絡(luò)資料)
使用docker commit命令雖然可以比較直觀的幫助理解鏡像分層存儲的概念,但是實際環(huán)境中并不會這樣使用。
首先,如果在安裝軟件,編譯構(gòu)建,那會有大量的無關(guān)內(nèi)容被添加進來,如果不小心清理,將會導致鏡像及其臃腫。
此外,使用docker commit 意味著所有對鏡像的操作都是黑箱操作,生成的鏡像也被稱為黑箱鏡像,換句話說,就是除了制定鏡像的人知道執(zhí)行過什么命令,怎么生成的鏡像,別人根本無從得知,而且,即使是這個制作鏡像的人,過一段時間后也無法記清具體的操作的。雖然docker diff或許可以得到一點線索,但是遠遠不到可以確保生成一致鏡像的地步。這種黑箱鏡像的維護工作是非常痛苦的。
而且,任何修改的結(jié)果僅僅是在當前層進行標記,添加,修改,而不會改動上一層。如果使用docker commit制作鏡像,以及后期修改的話,每一次修改都會讓鏡像更加臃腫一次,所刪除的上一層的東西并不會丟失,會一直如影隨形的跟著這個鏡像,即使根本無法訪問到,這會使鏡像更加臃腫。
docker commit有一些特殊的應(yīng)用場合,比如被入侵后保存現(xiàn)場等。但是,不要使用docker commmit定制鏡像,定制行為應(yīng)該使用Dockerfile來完成。
祝大家早日熟練使用docker相關(guān)命令~
總結(jié)
- 上一篇: 统计学入门基础概念问答(统计学方法的分类
- 下一篇: 嵌入式分享合集94