構(gòu)建Docker鏡像有兩種方式
1.使用 docker commit命令
2.使用docker build命令&Dockerfile文件
一.使用docker commit命令構(gòu)建鏡像
docker commit 容器名稱(chēng)/容器ID? 鏡像倉(cāng)庫(kù)名/鏡像名稱(chēng)[:TAG]
-a "作者信息"
-m "提交信息"
步驟:
1.選取一個(gè)基礎(chǔ)鏡像創(chuàng)建一個(gè)容器
2.對(duì)容器進(jìn)行相關(guān)修改
3.使用docker commit命令提交修改
example:基于ubuntu基礎(chǔ)鏡像制作包含apache2的鏡像
1.運(yùn)行一個(gè)基于ubuntu基礎(chǔ)鏡像的交互式容器:docker run -i -t ubuntu /bin/bash
2.進(jìn)入容器中利用apt-get包管理工具安裝apache:
apt-get update
apt-get install apache2
exit
3.退出容器后提交
docker commit?
使用 docker inspect 鏡像名? 查看詳情
可以看到:Parent字段存儲(chǔ)了父鏡像ubuntu的imageId,container:保存了docker commit 提交時(shí)容器的id
二.使用dockerfile構(gòu)建鏡像
對(duì)比使用docker commit構(gòu)建鏡像,dockerfile提供了鏡像構(gòu)建的可重復(fù)性湾盗,透明性谎痢,冪等性扑庞。
核心步驟:
1.創(chuàng)建Dockerfile文件屏积,在Dockerfile中使用DLS(Domain Specific Language)領(lǐng)域?qū)S谜Z(yǔ)言來(lái)定義每一步操作痹雅。
2.使用Docker build命令基于Dockerfile中的指令構(gòu)建一個(gè)新的鏡像蚀苛。
后續(xù)描述會(huì)基于一下形式描述
一些基本概念->鏡像構(gòu)建實(shí)例->docker build指令&dockerfile詳細(xì)語(yǔ)法詳解?
1.一些基本概念
構(gòu)建環(huán)境:保存Dockerfile文件的目錄在验,也稱(chēng)構(gòu)建上下文,在該目錄中可以存放在構(gòu)建鏡像中需要使用的代碼文件配置文件等堵未,Docker在構(gòu)建鏡像時(shí)將上下文和上下文中的目錄文件上傳至Docker守護(hù)進(jìn)程腋舌,這樣守護(hù)進(jìn)行就可以直接訪(fǎng)問(wèn)用戶(hù)想在鏡像中存儲(chǔ)的任何代碼,文件渗蟹,數(shù)據(jù)块饺。請(qǐng)為每個(gè)需要構(gòu)建的鏡像創(chuàng)建單獨(dú)的上下文目錄。
Dockerfile文件:用來(lái)存儲(chǔ)如何構(gòu)建鏡像的語(yǔ)句的文件雌芽,存儲(chǔ)于構(gòu)建上下文的根目錄下授艰。
.dockerignore:在構(gòu)建上下文的根目錄下,如果存在該文件世落,該文件內(nèi)容會(huì)被按行切割淮腾,每行都是一條文件過(guò)濾匹配模式,其作用類(lèi)似于git系統(tǒng)的.gitignore,該文件用來(lái)防止構(gòu)建上下文中不屬于構(gòu)建需要的文件被上傳至Docker守護(hù)進(jìn)程
2.一個(gè)簡(jiǎn)單的鏡像構(gòu)建實(shí)例
創(chuàng)建上下文環(huán)境:nginx_image
創(chuàng)建Dockfile文件
編輯Dockfile并保存
在上下文環(huán)境下運(yùn)行docker build -t "freesnow1992/nginx" .? ?構(gòu)建鏡像
此時(shí)一個(gè)可用的鏡像就已經(jīng)構(gòu)建好了屉佳,相關(guān)Dockfile指令&docker build命令含義參照下面的說(shuō)明
三.docker build指令&dockerfile詳細(xì)語(yǔ)法詳解?
Docker build?
構(gòu)建緩存:
Docker會(huì)為Dockerfile中的每一條語(yǔ)句新建一個(gè)鏡像谷朝,每個(gè)鏡像都是一個(gè)可復(fù)用模塊,后續(xù)其他構(gòu)建流程中可使用已經(jīng)構(gòu)建過(guò)的鏡像層來(lái)加速構(gòu)建流程武花。
任何事情都有兩面
好的一面:構(gòu)建緩存加速了構(gòu)建過(guò)程圆凰,同時(shí)也減少了存儲(chǔ),因?yàn)镈ocker使用? “寫(xiě)時(shí)復(fù)制”? 使用同一鏡像層構(gòu)建的新鏡像髓堪,增加的存儲(chǔ)只是本條命令產(chǎn)生的新文件送朱。
壞的一面:對(duì)于一些非冪等的語(yǔ)句由于使用了構(gòu)建緩存導(dǎo)致結(jié)果不符合預(yù)期娘荡,例如:RUN apt-get update 指令,如果使用了構(gòu)建緩存驶沼,此時(shí)的更新還是使用構(gòu)建緩存鏡像的更新炮沐。為了避免這個(gè)情況的發(fā)生可以使用--no-cache來(lái)強(qiáng)制不使用構(gòu)建緩存。
Docker build用于通過(guò)dockerfile定義的指令來(lái)構(gòu)建鏡像
格式:Docker build 額外參數(shù) 構(gòu)建上下文
構(gòu)建上下文:用于指明構(gòu)建上下文目錄的路徑回怜,其可以是git倉(cāng)庫(kù)源地址大年,必須保證dockerfile存在于構(gòu)建上下文的根目錄下
額外參數(shù)
-t? 倉(cāng)庫(kù)/鏡像:TAG? ? ?用于指定構(gòu)建后鏡像的鏡像名&Tag
-no-cache? 不使用構(gòu)建緩存,
查看鏡像構(gòu)建過(guò)程&鏡像層
docker history 鏡像ID
Dockerfile的指令
FROM
形式:FROM? 基礎(chǔ)鏡像名
含義:指定一個(gè)構(gòu)建過(guò)程的基礎(chǔ)鏡像玉雾,后續(xù)構(gòu)建過(guò)程將基于此鏡像展開(kāi)翔试。所以每個(gè)Dockerfile的第一條指令必須是FROM
例子:FROM ubuntu:14.04? 制定構(gòu)建基礎(chǔ)鏡像為ubuntu 14.04
MAINTAINER
形式:MAINTAINER? 作者相關(guān)信息
含義:用于說(shuō)明本次構(gòu)建鏡像的作者信息(作者姓名 聯(lián)系方式)
例子:MAINTAINER? ?linghu linghu@example.com
RUN
形式: RUN 命令 參數(shù)
? ? ? ? ? ? RUN ["命令","參數(shù)”,..]
含義:RUN指令會(huì)在當(dāng)前鏡像創(chuàng)建的容器中運(yùn)行制定指令复旬,默認(rèn)情況下RUN指令會(huì)在shell中使用命令包裝器/bin/sh -c 來(lái)執(zhí)行
? ? ? ? ? ?如果運(yùn)行的鏡像不支持shell平臺(tái)垦缅,或不希望在shell中運(yùn)行可使用exec格式的RUN指令? RUN ["指令","參數(shù)"]
例子:
RUN apt-get update && apt-get install -y nginx? 使用shell包裝器來(lái)執(zhí)行,apt-get包管理器更新&安裝nginx
RUN ["apt-get","update"]? ? 使用exec格式制定指令
RUN ["apt-get","install","-y","nginx"]
EXPORT
形式:EXPORT [端口/協(xié)議(默認(rèn)tcp驹碍,可指定tpc/udp):通知Docker容器在運(yùn)行時(shí)偵聽(tīng)指定的端口
含義:EXPOSE?指令實(shí)際上并未發(fā)布端口壁涎。它充當(dāng)構(gòu)建鏡像的人員和運(yùn)行容器的人員之間的一種文檔類(lèi)型,有關(guān)打算發(fā)布哪些端口的信息志秃。要在運(yùn)行容器時(shí)實(shí)際發(fā)布端口怔球,請(qǐng)?jiān)?docker run?上使用?-p?標(biāo)志來(lái)發(fā)布和映射一個(gè)或多個(gè)端口,或使用?-P?標(biāo)志來(lái)發(fā)布所有公開(kāi)的端口并將它們映射為高階端口浮还。
注意:如果將?-P?和?docker run?一起使用竟坛,將公開(kāi)EXPORT指定的端口,但是-P?在主機(jī)上使用臨時(shí)的高階主機(jī)端口钧舌,因此該端口對(duì)于? ? ? ? ? ? ? ? ?TCP 和 UDP 將是不同的担汤。論使用哪種?EXPOSE?設(shè)置,都可以在運(yùn)行時(shí)使用?-p?標(biāo)志覆蓋它們
例子:
EXPORT? 80/tcp
CMD?
形式: CMD ["命令","參數(shù)",".."]
????????????CMD 命令 參數(shù)? ? 使用該形式Docker會(huì)在指定的命令前加上 /bin/sh -c 洼冻,不建議使用
含義: CMD用于指定容器啟動(dòng)時(shí)要運(yùn)行的命令漫试,效果同docker run 中指定的命令
注意:CMD命令可以被docker run 中的命令覆蓋
? ? ? ? ? ? Dockerfile 中只能存在一條CMD指令,如果存在多條也只有最后一條會(huì)被執(zhí)行
? ? ? ? ? ? 如果容器想運(yùn)行多個(gè)進(jìn)程碘赖,可以使用類(lèi)似supervisor的服務(wù)管理工具
例子:
CMD ["nginx","-g","daemon off;"]
CMD nginx -g "daemon off;"
ENTRYPOINT
形式:ENTRYPOINT ["命令“,"參數(shù)",..]
? ? ? ? ? ?ENTRYPOINT?命令 參數(shù)? ? 使用該形式Docker會(huì)在指定的命令前加上 /bin/sh -c ,不建議使用
含義:ENTRYPOINT用于指定容器啟動(dòng)時(shí)要運(yùn)行的命令外构,效果同docker run 中指定的命令普泡,但是不會(huì)被docker run中的參數(shù)覆蓋,此時(shí)如果docker run 存在指令參數(shù)审编,將被作為ENTRYPOINT 指定的命令的參數(shù) 傳遞進(jìn)來(lái)撼班,如果docker run 中沒(méi)有指定參數(shù),但此時(shí)dockerfile文件中存在CMD指令垒酬,則cmd指令的參數(shù)將作為ENTRYPOINT指定的命令的參數(shù)傳遞進(jìn)來(lái)
注意:如果要強(qiáng)制覆蓋ENTRYPOINT的命令砰嘁,可使用 docker run --entrypoint 進(jìn)行覆蓋
例子:
Dokerfile文件中相關(guān)內(nèi)容如下
----------------------------------
CMD ["-g","daemon off;"]
ENTRYPOINT ["nginx"]
----------------------------------
docker? run -d -P freesnow1992/nginx :相當(dāng)于容器啟動(dòng)是的命令為 nginx -g “daemon off;"
docker run -d - P freesnow1992/nginx -h :相當(dāng)于容器啟動(dòng)時(shí)的命令為 nginx -h件炉,此時(shí)覆蓋了CMD中指定的參數(shù)
WORKDIR
形式: WORKDIR 路徑名
含義:用來(lái)從鏡像創(chuàng)建一個(gè)新容器時(shí),在容器內(nèi)部設(shè)置一個(gè)工作目錄矮湘,CMD斟冕,ENTRYPOINT指定的程序會(huì)在這個(gè)目錄下執(zhí)。同時(shí)可以? ? ? ? ? ? ? ?使用該指令為Dockerfile中的后續(xù)一系列指令設(shè)置工作目錄
注意:在運(yùn)行Docker run時(shí)可以通過(guò)-w參數(shù)予以覆蓋
例子:
WORKDIR /usr/local 切換當(dāng)前工作目錄為/usr/local
ENV
形式:ENV? 變量名? ?變量值 (只可以設(shè)置單個(gè)環(huán)境變量)
? ? ? ? ? ?ENV 變量名1=變量值 變量名2=變量值?
含義:用來(lái)在鏡像構(gòu)建過(guò)程中設(shè)置環(huán)境變量缅阳。新的環(huán)境變量可以在后續(xù)的任何RUN指令中使用磕蛇,同時(shí)環(huán)境變量也將在后續(xù)由該鏡像創(chuàng)建的任何容器中生效。
注意:在運(yùn)行Docker run時(shí) 可以通過(guò) -e 來(lái)傳遞環(huán)境變量此時(shí)只對(duì)該容器的運(yùn)行時(shí)有效
例子:
ENV WDPATH = /usr/local
WORKDIR $WDPATH
USER
形式: USER user/uid:group/gid(用戶(hù)名必須已經(jīng)存在十办,可使用鏡像中存在的秀撇,或在之前使用RUN useradd 進(jìn)行新增)
含義:用來(lái)指定該鏡像會(huì)以什么樣的用戶(hù)運(yùn)行,默認(rèn)會(huì)以root用戶(hù)運(yùn)行
注意:在運(yùn)行Docker run 時(shí)向族,可以通過(guò) -u 來(lái)更改用戶(hù)
例子:
USER 0 使用root用戶(hù)運(yùn)行容器
VOLUME
形式:VOLUME ["掛載點(diǎn)",...]
含義:用于向基于鏡像創(chuàng)建的容器添加卷呵燕。
注意:1.卷可以在容器間共享&重用
? ? ? ? ? ?2.卷的掛載點(diǎn)會(huì)繞過(guò)聯(lián)合文件系統(tǒng)
? ? ? ? ? ?3.對(duì)卷的修改會(huì)立即生效,但不會(huì)對(duì)更新鏡像產(chǎn)生影響
? ? ? ? ? ?4.卷會(huì)一直存在知道沒(méi)有任何容器使用它
例子:
VOLUME? ?["/opt/test"]
ADD
形式:ADD 構(gòu)建上下文的文件目錄/url地址? ? 鏡像中的目的地址
含義:用來(lái)將構(gòu)建上線(xiàn)文中的文件目錄復(fù)制到鏡像中
注意:
? ? ? ? ? ?ADD 指令通過(guò)目的地址的末尾字符來(lái)判定文件源時(shí)目錄還是文件件相,如果以/結(jié)尾再扭,那么Docker認(rèn)為源位置指向一個(gè)目錄,否則認(rèn)? ?為指向一個(gè)文件
????????????不能將構(gòu)建上下文之外的文件進(jìn)行ADD操作
? ? ? ? ? ?如果源文件是歸檔格式适肠,ADD命令會(huì)自動(dòng)進(jìn)行unpakc操作
? ? ? ? ? ?如果目的路徑不存在霍衫,ADD會(huì)自動(dòng)進(jìn)行創(chuàng)建,形如使用了mkdir -p
例子:
ADD? ? ?main.go? ? /usr/local/src/main.go
COPY
形式:ADD 構(gòu)建上下文的文件目錄? ? 鏡像中的位置
含義:同ADD命令侯养,但是不會(huì)針對(duì)歸檔文件進(jìn)行unpack操作
例子:
COPY? ? main.go /usr/local/src/main.go
LABLE
形式:LABEL 鍵="值"? ? 鍵="值"
含義:使用LABEL為鏡像添加元數(shù)據(jù)
例子:
LABEL version="1.0"? ? location="Shanghai"? ? role="Register Center"
STOPSIGNAL
形式:STOPSIGNAL 信號(hào)值/信號(hào)名稱(chēng)
含義:用于指定在執(zhí)行docker stop執(zhí)行停止容器時(shí)敦跌,會(huì)發(fā)給容器的信號(hào),默認(rèn)情況下會(huì)發(fā)出SIGTERM逛揩,其目的是為了讓容器能夠優(yōu)雅的退出柠傍,但是如果容器在接受相應(yīng)指令后(10s)內(nèi)還是沒(méi)有停止,此時(shí)Docker會(huì)幫它退出辩稽,此時(shí)會(huì)發(fā)送SIGKILL信號(hào)將容器殺死惧笛。
例子:
STOPSIGNAL 9
STOPSIGNAL SIGKILL
ARG
形式: ARG? 變量名?
? ? ? ? ?ARG? 變量名=默認(rèn)值
含義:設(shè)置構(gòu)建過(guò)程中使用的變量,和ENV不同逞泄,其在鏡像生成的容器中并不會(huì)存在患整。
特點(diǎn):1.ARG存在兩個(gè)作用域,在FROM命令前定義的變量?jī)H對(duì)FROM命令有效喷众,對(duì)后續(xù)命令無(wú)效各谚,在FROM后設(shè)置的ARG變量對(duì)后續(xù)命令有效
例子:
ARG base_image??
ARG tag="latest"
FROM ${base_image}:${tag}
Docker build --build-arg base_image=ubuntu
此時(shí)效果為
FROM ubuntu:latest
ONBUILD
形式:ONBUILD? ? Dockerfile內(nèi)部其他指令
含義:用于為鏡像構(gòu)建創(chuàng)建觸發(fā)器。當(dāng)以該鏡像作為基礎(chǔ)鏡像的子鏡像在構(gòu)建時(shí)到千,ONBUILD指令會(huì)執(zhí)行昌渤。
特點(diǎn):ONBUILD指令只能被繼承一次,即只會(huì)在子鏡像中執(zhí)行憔四,而不會(huì)在孫子鏡像中執(zhí)行膀息。ONBUILD常用于創(chuàng)建模版鏡像
? ? ? ? ? ?ONBUILD內(nèi)的指令不會(huì)在構(gòu)建本鏡像時(shí)執(zhí)行
例子:
創(chuàng)建nginx鏡像模版 freesnow1992/nginx_tpl
FROM ubuntu
MAINTAINER linghu "linghu@example.com"
RUN apt-get update && apt-get install -y nginx
RUN rm /usr/share/nginx/html/index.html
ONBUILD ADD /www /usr/share/nginx/html/
EXPOSE 80
LABEL role="nginx server"
CMD ["-g","daemon off;"]
ENTRYPOINT ["nginx"]
在后續(xù)以??freesnow1992/nginx_tpl 為基礎(chǔ)鏡像的子鏡像構(gòu)建過(guò)程中般眉,ONBUILD指令會(huì)在FROM之后執(zhí)行