基于Dockerfile構(gòu)建鏡像
1. Dockerfile:source code for building Docker file
Docker可以通過從Dockerfile文件中讀取指令自動構(gòu)建鏡像
Dockerfile是一個文本文檔贞绳,它包含用戶可以在命令行上調(diào)用的所有命令來組裝映像
使用Docker build命令浇辜,用戶可以通過逐條執(zhí)行幾條命令自動創(chuàng)建鏡像
2. Dockerfile語法格式:
首行必須是以#開頭的行
不區(qū)分大小寫听哭,但約定俗成的慣例都是使用全部大寫厘灼。
Docker按順序在Dockerfile中運(yùn)行指令
第一個指令必須是“FROM”这吻,以便指定要從其中構(gòu)建的基本映像
3. 環(huán)境變量(使用ENV語句聲明)也可以在某些指令中使用,作為由Dockerfile解釋的變量巢墅。
在Dockerfile中讲冠,環(huán)境變量可以是$variable_name或${variable_name}
${variable_name}語法還支持一些標(biāo)準(zhǔn)bash修飾符
${variable:-word}表示,如果設(shè)置了變量俭正,那么結(jié)果將是該值胁出。如果變量未設(shè)置,則結(jié)果為word段审。
${variable:+word}表示如果設(shè)置了變量全蝶,那么結(jié)果將是word,否則結(jié)果將是空字符串寺枉。
4. .dockerignore文件
在工作目錄中若有子目錄抑淫,而子目錄中有些文件不想引用,就可以用.dockerignore來隱藏文件姥闪。
.dockerignore文件內(nèi)指明不引用的文件始苇。
5. FROM
用來指定基礎(chǔ)鏡像,若指定的鏡像不存在筐喳,會先到Docker Hub中下載
語法:
FROM <image> [AS <name>] #[AS <name>]:別名
FROM <image>[:<tag>] [AS <name>] #tag:標(biāo)簽
FROM <image> [@<digest>] [AS <name>] #digest:哈希碼
6. docker build命令
Build an image from a Dockerfile
Options
-t, --tag list Name and optionally a tag in the 'name:tag' format
-m, --memory bytes Memory limit
-c, --cpu-shares int CPU shares (relative weight)
7. LABEL
添加鏡像文件的元數(shù)據(jù),可出現(xiàn)多次催式,強(qiáng)烈建議只使用一條函喉,因為一條指令會添加一個層,層數(shù)越多荣月,運(yùn)行效率越低管呵。
語法格式:
LABEL <key>=<value> <key>=<value> <key>=<value>... #可指定多個LABEL
LABEL <key> <value> #只可指定一個LABEL,第一個空格后的內(nèi)容都會被當(dāng)作value
示例
只修改一個鏡像的FROM哺窄、LABEL
創(chuàng)建工作目錄image
[root@docker ~]# mkdir image[root@docker ~]# cd image
編輯Dockerfile文件捐下,添加以下內(nèi)容:
[root@docker image]# vim Dockerfile#Test Image BuildFROM alpineLABEL maintainer="lixinkuan <lixinkuan@163.com>"
制作鏡像:
[root@docker image]# docker build .Sending build context to Docker daemon? 2.048kBStep 1/2 : FROM alpine ---> 3fd9065eaf02Step 2/2 : LABEL maintainer="lixinkuan " --->Runningine1ce9acfc453Removing intermediate container e1ce9acfc453 ---> 1deb17a1af32Successfully built 1deb17a1af32
查看:REPOSITORY和TAG都為空的即為新創(chuàng)建的鏡像文件
[root@docker image]#dockerimagelsREPOSITORYTAGIMAGEIDCREATEDSIZE? ? ? ? ? ? ? ? ? ? ? ? ? ? 1deb17a1af325minutesago4.15MBnginxlatestcd5239a0906a3weeksago109MBbusyboxlatest8c811b4aec355weeksago1.15MBhttpd2.4fb2f3851a9718weeksago178MBalpinelatest3fd9065eaf025monthsago4.15MB
創(chuàng)建docker鏡像時,可使用-t后跟 'name:tag' 指定TAG
也可用如下命令添加標(biāo)簽:
[root@docker image]# docker image tag 1deb17a1af32 alpine:lxk[root@docker image]# docker imagesREPOSITORY? ? ? ? ? ? ? ? ? TAG? ? ? ? ? ? ? ? IMAGE ID? ? ? ? ? ? CREATED? ? ? ? ? ? SIZEalpine? ? ? ? ? ? ? ? ? ? ? lxk1deb17a1af325minutes ago4.41MB
8. COPY
用于從Docker宿主機(jī)復(fù)制文件至創(chuàng)建的新映像文件
語法:
COPY <src> ... <dest>
COPY ["",... ""]
<src>:要復(fù)制的源文件或目錄萌业,支持使用通配符
<dest>:目標(biāo)路徑坷襟,即正在創(chuàng)建的image的文件系統(tǒng)路徑;建議為<dest>使用絕對路徑生年,否則婴程,COPY指定則以WORKDIR為其起始路徑
注意:在路徑中有空白字符時,通常使用第二種格式
文件復(fù)制準(zhǔn)則:
<src>必須是build上下文中的路徑抱婉,不能是其父目錄中的文件
如果<src>是目錄排抬,則其內(nèi)部文件或子目錄會被遞歸復(fù)制,但<src>目錄自身不會被復(fù)制
如果指定了多個<src>授段,或在<src>中使用了通配符,則<dest>必須是一個目錄番甩,且必須以/結(jié)尾
如果<dest>事先不存在侵贵,它將會被自動創(chuàng)建,這包括其父目錄路徑
示例:復(fù)制單個文件
在image目錄下為index.html添加內(nèi)容:
[root@docker image]#? echo '<h1>hello,docker!</h1>' > index.html
編輯Dockerfile文件,添加語句:
[root@docker image]# vim Dockerfile #Test Image BuildFROM alpineLABEL maintainer="lixinkuan <lixinkuan@163.com>"COPY index.html/var/www/html/
用alpine啟動一個容器,查看是否有/var/www/html目錄
[root@docker image]# docker run -it --name a1 alpine/# ps aux PID? USER? ? TIME? COMMAND1root0:00/bin/sh7root0:00ps aux/# ls /var/www/htmlls: /var/www/html: No such fileordirectory
制作鏡像
[root@docker image]# docker build -t cpindex:latest .Sending build context to Docker daemon? 3.072kBStep 1/3 : FROM alpine ---> 3fd9065eaf02Step 2/3 : LABEL maintainer="lixinkuan " --->Runningin9d96e0655a82Removing intermediate container 9d96e0655a82 ---> 56049399eb78Step 3/3 : COPY index.html /var/www/html/ ---> bace8e55c97bSuccessfully built bace8e55c97bSuccessfully tagged cpindex:latest
查看制作的鏡像:
[root@docker image]# docker image lsREPOSITORY? ? ? ? ? TAG? ? ? ? ? ? ? ? IMAGE ID? ? ? ? ? ? CREATED? ? ? ? ? ? SIZEcpindex? ? ? ? ? ? latest? ? ? ? ? ? ? bace8e55c97b52seconds ago4.15MB
以制作的鏡像啟動一個容器,并查看文件是否存在
[root@docker image]# docker run --name copyfile -it --rm cpindex:latest/# ls /var/www/htmlindex.html/# cat /var/www/html/index.html
hello,docker!
示例:復(fù)制目錄下的多個文件至目錄
復(fù)制一個目錄至/root/image下
[root@docker image]# cp -r /etc/default/ ./ [root@docker image]# lsdefaultDockerfile? index.html[root@docker image]# ls default/grub? kibana? nss? useradd
修改Dockerfile文件為以下內(nèi)容:
#Test Image BuildFROM alpineLABEL maintainer="lixinkuan <lixinkuan@163.com>"COPYdefault/tmp/
制作鏡像:
[root@docker image]# docker build -t cpdir:latest ./Sending build context to Docker daemon? 9.216kBStep 1/3 : FROM alpine ---> 3fd9065eaf02Step 2/3 : LABEL maintainer="lixinkuan " ---> Using cache ---> 56049399eb78Step 3/3 : COPY default /tmp/ ---> 18cacf50aef9Successfully built 18cacf50aef9Successfully tagged cpdir:latest
查看并驗證:
[root@docker image]# docker image lsREPOSITORY? ? ? ? ? TAG? ? ? ? ? ? ? ? IMAGE ID? ? ? ? ? ? CREATED? ? ? ? ? ? SIZEcpdir? ? ? ? ? ? ? latest18cacf50aef924seconds ago4.15MB[root@docker image]# docker run --name cpdir -it --rm cpdir:latestWARNING: IPv4 forwardingisdisabled. Networking willnotwork./# ls /tmpgrub? ? kibana? nss? ? ? useradd
示例:使用數(shù)組格式創(chuàng)建配置文件
修改配置文件如下:
#Test Image BuildFROMalpineLABEL maintainer="lixinkuan <lixinkuan@163.com>"COPY ["default","/tmp/default"]
創(chuàng)建鏡像并驗證
[root@docker image]# docker build -t cp:latest ./Sending build context to Docker daemon9.216kBStep1/3: FROM alpine --->3fd9065eaf02Step2/3: LABEL maintainer="lixinkuan <lixinkuan@163.com>"---> Using cache --->56049399eb78Step3/3: COPY ["default","/tmp/default"] ---> bf0799319943Successfully built bf0799319943Successfully tagged cp:latest[root@docker image]# docker run --name cp -it --rm cp:latest/# cd /tmp/tmp# lsdefault/tmp # cd default//tmp/default# lsgrub? ? kibana? nss? ? ? useradd/tmp/default# exit
9. ADD
ADD類似于COPY指令,ADD支持tar文件和URL路徑
Syntax
ADD <src>...<dest>
ADD ["<src>"..."<dest>"]
操作準(zhǔn)則:
同COPY指令
如果<src>為URL且<dest>不以/結(jié)尾缘薛,則<src>指定的文件將被下載并直接被創(chuàng)建為<dest>窍育;如果<dest>以/結(jié)尾,則文件名URL指定的文件將被直接下載并保存為<dest>/<filename>
如果<src>是一個本地系統(tǒng)上的壓縮格式的tar文件宴胧,它將被展開為一個目錄漱抓,其行為類似于“tar -x”命令;然而恕齐,通過URL獲取到的tar文件將不會自動展開乞娄;
如果<src>有多個,或其間接或直接使用了通配符显歧,則<dest>必須是一個以/結(jié)尾的目錄路徑仪或;如果<dest>不以/結(jié)尾,則其被視作一個普通文件士骤,<src>的內(nèi)容將被直接寫入到<dest>
示例:下載一個文件至鏡像文件
在工作目錄下編寫Dockerfile文件(使用URL時,用ftp協(xié)議失敗)
#Test Image BuildFROM alpineLABEL maintainer="lixinkuan <lixinkuan@163.com>"COPY ["default","/tmp/default"]ADDhttps://mirrors.aliyun.com/centos/7.5.1804/os/x86_64/Packages/zsh-5.0.2-28.el7.x86_64.rpm /tmp/
創(chuàng)建鏡像文件
[root@docker image]# docker build -t zsh:latest ./Sending build context to Docker daemon? 9.216kBStep 1/4 : FROM alpine ---> 3fd9065eaf02Step 2/4 : LABEL maintainer="lixinkuan " ---> Using cache ---> 56049399eb78Step 3/4 : COPY ["default","/tmp/default"] ---> Using cache ---> bf0799319943Step 4/4 : ADD https://mirrors.aliyun.com/centos/7.5.1804/os/x86_64/Packages/zsh-5.0.2-28.el7.x86_64.rpm /tmp/Downloading [==================================================>]? 2.494MB/2.494MB ---> 538ab9c6983eSuccessfully built 538ab9c6983eSuccessfully tagged zsh:latest
創(chuàng)建容器并查看
[root@docker image]# docker run -it --name zsh --rm zsh:latest/# cd /tmp/tmp# lsdefaultzsh-5.0.2-28.el7.x86_64.rpm
示例:ADD一個壓縮包至鏡像文件
復(fù)制壓縮包至工作目錄,并在工作目錄編輯Dockerfile文件
[root@docker image]# cp /root/wordpress-4.8.1-zh_CN.tar.gz ./[root@docker image]# vim Dockerfile #Test Image BuildFROM alpineLABEL maintainer="lixinkuan <lixinkuan@163.com>"ADD wordpress-4.8.1-zh_CN.tar.gz/tmp/
制作鏡像文件
[root@docker image]# docker build -t wordpress:latest ./Sending build context to Docker daemon? 8.652MBStep 1/3 : FROM alpine ---> 3fd9065eaf02Step 2/3 : LABEL maintainer="lixinkuan " ---> Using cache ---> 56049399eb78Step 3/3 : ADD wordpress-4.8.1-zh_CN.tar.gz /tmp/ ---> 58c32caba31eSuccessfully built 58c32caba31eSuccessfully tagged wordpress:latest
創(chuàng)建容器并查看
[root@docker image]# docker run --name a1 -it --rm wordpress:latest/# ls /tmp/wordpress/index.php? ? ? ? ? ? wp-admin? ? ? ? ? ? ? wp-content? ? ? ? ? ? wp-load.php? ? ? ? ? wp-signup.phplicense.txt? ? ? ? ? wp-blog-header.php? ? wp-cron.php? ? ? ? ? wp-login.php? ? ? ? ? wp-trackback.phpreadme.html? ? ? ? ? wp-comments-post.php? wp-includes? ? ? ? ? wp-mail.php? ? ? ? ? xmlrpc.phpwp-activate.php? ? ? wp-config-sample.php? wp-links-opml.php? ? wp-settings.php/# exit
10. WORKDIR
用于為Dockerfile中所有的RUN范删、CMD、ENTRYPOINT拷肌、COPY和ADD指定設(shè)定工作目錄
Syntax
WORKDIR
在Dockerfile文件中到旦,WORKDIR指令可出現(xiàn)多次旨巷,其路徑也可以為相對路徑,不過添忘,其是相對此前一個WORKDIR指令指定的路徑
另外采呐,WORKDIR也可調(diào)用由ENV指定定義的變量
例如:
WORKDIR /var/log
WORKDIR $STATEPATH
示例
在工作目錄下編輯Dockerfile文件:
#Test Image BuildFROMalpineLABEL maintainer="lixinkuan <lixinkuan@163.com>"WORKDIR /tmpADD wordpress-4.8.1-zh_CN.tar.gz src
創(chuàng)建鏡像:
[root@docker image]# docker build -t wordpress:v0.1 ./Sending build context to Docker daemon? 8.652MBStep 1/4 : FROM alpine ---> 3fd9065eaf02Step 2/4 : LABEL maintainer="lixinkuan " ---> Using cache ---> 56049399eb78Step 3/4 : WORKDIR /tmpRemoving intermediate container 08bef4630472 ---> 54f97eda6b49Step 4/4 : ADD wordpress-4.8.1-zh_CN.tar.gz src ---> 0811aff4fa7dSuccessfully built 0811aff4fa7dSuccessfully tagged wordpress:v0.1
創(chuàng)建容器后,默認(rèn)工作路徑就是WORKDIR所指的目錄/tmp
[root@docker image]# docker run --name a1 -it --rm wordpress:v0.1/tmp# lssrc/tmp # ls src/wordpress/tmp # ls src/wordpress/index.php? ? ? ? ? ? wp-admin? ? ? ? ? ? ? wp-content? ? ? ? ? ? wp-load.php? ? ? ? ? wp-signup.phplicense.txt? ? ? ? ? wp-blog-header.php? ? wp-cron.php? ? ? ? ? wp-login.php? ? ? ? ? wp-trackback.phpreadme.html? ? ? ? ? wp-comments-post.php? wp-includes? ? ? ? ? wp-mail.php? ? ? ? ? xmlrpc.phpwp-activate.php? ? ? wp-config-sample.php? wp-links-opml.php? ? wp-settings.php/tmp# exit
11. VOLUME
用于在image中創(chuàng)建一個掛載點目錄,以掛載Docker host上的卷或其它容器上的卷
Syntax
VOLUME <mountpoint>
VOLUME ["<mountpoint>"]
如果掛載點目錄路徑下此前有文件存在昔汉,docker run命令會把原文件隱藏.
如果此前掛載點不存在,docker 會自動創(chuàng)建該目錄.
掛載點下文件變化都可以在宿主機(jī)查看
查看方法:
docker volume ls #查看宿主機(jī)所有掛載的目錄
docker inspect -f {{.Mounts}} a1 #通過查看指定容器信息查看掛載點路徑
示例
在需要掛載的目錄下提供文件
[root@docker image]# echo "hello,test dockerfile" > /var/www/html/index.html
在工作目錄下編輯Dockerfile文件
#Test Image BuildFROM alpineLABEL maintainer="lixinkuan "#WORKDIR /tmp#ADD wordpress-4.8.1-zh_CN.tar.gz src/VOLUME /var/www/html
創(chuàng)建鏡像文件
[root@docker image]# docker build -t file:v0.1 ./Sending build context to Docker daemon? 8.651MBStep 1/3 : FROM alpine ---> 3fd9065eaf02Step 2/3 : LABEL maintainer="lixinkuan " ---> Using cache ---> 56049399eb78Step 3/3 : VOLUME /var/www/html ---> [Warning] IPv4 forwarding is disabled. Networking will not work. --->Runninginda84d9f4ca1eRemoving intermediate container da84d9f4ca1e ---> b26c2d7ea64cSuccessfully built b26c2d7ea64cSuccessfully tagged file:v0.1
創(chuàng)建容器:
[root@docker image]# docker run --name a1 -it --rm file/# cd /var/www/html//var/www/html# echo abc > index.html/var/www/html# cat index.htmlabc
查看宿主機(jī)上的文件:
[root@docker ~]# docker volume ls? ? ? #查看本機(jī)所有容器掛載的目錄DRIVER? ? ? ? ? ? ? VOLUME NAMElocal6368d0a0b462f5329a4b3bdcb7030e0d6f724bf9f801386f87fdac7660cd1735[root@docker ~]# docker inspect -f {{.Mounts}} a1? ? ? #查看a1容器的掛載文件路徑[{volume6368d0a0b462f5329a4b3bdcb7030e0d6f724bf9f801386f87fdac7660cd1735 /var/lib/docker/volumes/6368d0a0b462f5329a4b3bdcb7030e0d6f724bf9f801386f87fdac7660cd1735/_data /var/www/htmllocaltrue }][root@docker ~]# cd /var/lib/docker/volumes/6368d0a0b462f5329a4b3bdcb7030e0d6f724bf9f801386f87fdac7660cd1735/_data/[root@docker _data]# lsindex.html[root@docker _data]# cat index.html abc#該內(nèi)容與容器中index.html內(nèi)容一樣
12. EXPOSE
用于為容器打開指定要監(jiān)聽的端口以實現(xiàn)與外部通信
實質(zhì)是通過iptables添加DNAT規(guī)則,把外網(wǎng)主機(jī)訪問宿主機(jī)的請求轉(zhuǎn)發(fā)至指定容器.
需要宿主機(jī)開啟核心轉(zhuǎn)發(fā)功能.
可通過iptables -t nat -nvL查看添加的規(guī)則.
通過Dockerfile制作鏡像時若不用EXPOSE指定要暴露的端口,可用以下兩種方法暴露端口:
容器運(yùn)行后,自行添加DNAT規(guī)則實現(xiàn)端口暴露.
docker run時使用-p選項指定暴露的端口.
docker run時使用-P選項暴露所有容器內(nèi)監(jiān)聽的端口.
docker run時,使用-p選項指定的優(yōu)先級要高于Dockerfile制作鏡像時指定要暴露的端口.
Syntax
EXPOSE [/] [[/] ...]
<protocol>用于指定傳輸層協(xié)議懈万,可為tcp或udp二者之一,默認(rèn)為TCP協(xié)議
EXPOSE指令可一次指定多個端口靶病,例如
EXPOSE 11211/udp 11211/tcp
不用EXPOSE時,宿主機(jī)內(nèi)容器若要被外網(wǎng)主機(jī)訪問的情況
下載redis:4-alpine
[root@docker ~]# docker pull redis:4-alpine4-alpine: Pulling from library/redisff3a5c916c92: Pull complete 5fbab8756652: Pull complete ff7d4663b06c: Pull complete 0b5cf71258c2: Pull complete 54bbb9bad8ba: Pull complete 8fe9a341d124: Pull complete Digest: sha256:686ab026fae07b3b99a8e74210c361714a80311ecc55f23b349ae930ed2f5a95Status: Downloaded newer image for redis:4-alpine[root@docker ~]# docker imagesREPOSITORY? ? ? ? ? TAG? ? ? ? ? ? ? ? IMAGE ID? ? ? ? ? ? CREATED? ? ? ? ? ? SIZEredis? ? ? ? ? ? ? 4-alpine? ? ? ? ? ? caaeda72bf8f? ? ? ? 12 days ago? ? ? ? 27.8MB
運(yùn)行redis鏡像
[root@docker ~]# docker run --name db1 -d --rm -p 6379 redis:4-alpine881d5648c7388449a39c67024206c5710b1538f4c941039fa3905bb601b09699[root@docker ~]# docker exec -it db1 ifconfigeth0Linkencap:Ethernet? HWaddr02:42:AC:11:00:02inetaddr:172.17.0.2Bcast:172.17.255.255Mask:255.255.0.0UP BROADCAST RUNNING MULTICASTMTU:1500Metric:1RXpackets:8errors:0dropped:0overruns:0frame:0TXpackets:0errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:0RXbytes:648(648.0B)? TXbytes:0(0.0B)lo? ? ? ? Linkencap:Local Loopback? ? ? ? ? ? inetaddr:127.0.0.1Mask:255.0.0.0UP LOOPBACK RUNNINGMTU:65536Metric:1RXpackets:0errors:0dropped:0overruns:0frame:0TXpackets:0errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:1RXbytes:0(0.0B)? TXbytes:0(0.0B)[root@docker ~]# docker exec -it db1 /bin/sh/data# netstat -tnlActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address? ? ? ? ? Foreign Address? ? ? ? State? ? ? tcp000.0.0.0:63790.0.0.0:*LISTEN? ? ? tcp00:::6379:::*LISTEN? ? ? /data#
查看映射的端口
[root@docker ~]# docker container port db16379/tcp ->0.0.0.0:32768
外網(wǎng)主機(jī)訪問本地宿主機(jī)容器
[root@node1 tmp]#redis-cli-h192.168.1.106-p32768192.168.1.106:32768>select1OK192.168.1.106:32768[1]>setmykeyhiOK192.168.1.106:32768[1]>keys*1) "mykey"192.168.1.106:32768[1]>exit
查看本地容器內(nèi)是否有數(shù)據(jù)
[root@docker ~]# docker exec -it db1 /bin/sh/data# redis-cli 127.0.0.1:6379>select1OK127.0.0.1:6379[1]>keys *1)"mykey"127.0.0.1:6379[1]>exit/data# exit
開啟自動端口暴露
在工作目錄下編寫Dockerfile文件
#Test Image BuildFROMredis:4-alpineLABEL maintainer="lixinkuan <lixinkuan@163.com>"EXPOSE6379/tcp26379/tcp
制作鏡像文件
[root@docker images]# docker build -t expose_db:latest ./Sending build context to Docker daemon? 8.645MBStep 1/3 : FROM redis:4-alpine ---> caaeda72bf8fStep 2/3 : LABEL maintainer="lixinkuan " --->Runninginf43f9e43b27aRemoving intermediate container f43f9e43b27a ---> e98bb940a8a2Step 3/3 : EXPOSE 6379/tcp 26379/tcp --->Runninginf53a9be4f661Removing intermediate container f53a9be4f661 ---> ea40417716a0Successfully built ea40417716a0Successfully tagged expose_db:latest
運(yùn)行并查看效果
[root@docker images]# docker run --name a1 -d --rm -P redis_expose:latestad1225390f8f246cc5bde693ea99b120ee3a2f474416603b0797cda94787cc03[root@docker images]# docker container port a16379/tcp ->0.0.0.0:32772
換一臺主機(jī)連接數(shù)據(jù)庫查看
[root@node1 ~]#redis-cli-h192.168.200.45-p32772192.168.200.45:32772>select1OK192.168.200.45:32772[1]>keys*(emptylistorset)192.168.200.45:32772[1]>settestdockerfileOK192.168.200.45:32772[1]>keys*1) "test"192.168.200.45:32772[1]>gettest"dockerfile"
在a1容器上查看:
[root@docker images]# docker exec -it a1 /bin/sh/data# redis-cli 127.0.0.1:6379>select1OK127.0.0.1:6379[1]>get test"dockerfile"
示例:驗證Dockerfile與docker run時使用-p的優(yōu)先級
編輯Dockerfile
[root@docker images]# cat Dockerfile #Test Image BuildFROM redis:4-alpineLABEL maintainer="lixinkuan <lixinkuan@163.com>"EXPOSE6379/tcp80/tcp
制作鏡像:
[root@docker images]# docker build -t expose_port .Sending build context to Docker daemon? 8.645MBStep 1/3 : FROM redis:4-alpine ---> caaeda72bf8fStep 2/3 : LABEL maintainer="lixinkuan " ---> Using cache ---> 188775dd2e3eStep 3/3 : EXPOSE 6379/tcp 80/tcp --->Runninginb0f5bfbaafaeRemoving intermediate container b0f5bfbaafae ---> 165e707c2b23Successfully built 165e707c2b23Successfully tagged expose_port:latest
運(yùn)行容器時指定要暴露的端口:
[root@docker images]# docker run --name db1 -d --rm -p 25 expose_porte00f3e304103954c00651d44b00ae9961608900e0d5688eee4c08f140340f480[root@docker images]# docker container port db125/tcp ->0.0.0.0:32779
查看防火墻規(guī)則,只有暴露25端口的DNAT規(guī)則
[root@docker images]# iptables -t nat -nvLChain DOCKER (2 references) pkts bytes target? ? prot optinoutsourcedestination? ? ? ? ? ? 0? ? 0 RETURN? ? all? --? docker0 *? ? ? 0.0.0.0/0? ? ? ? ? ? 0.0.0.0/0? ? ? ? ? ? ? 0? ? 0 DNAT? ? ? tcp? --? !docker0 *? ? ? 0.0.0.0/0? ? ? ? ? ? 0.0.0.0/0? ? ? ? ? ? tcp dpt:32779 to:172.17.0.2:25
13. ENV
用于為鏡像定義所需的環(huán)境變量会通,并可被Dockerfile文件中位于其后的其它指令(如ENV、ADD娄周、COPY等)所調(diào)用
調(diào)用格式為$variable_name或${variable_name}
Syntax
ENV <key> <value>
ENV <key>=<value> ...
第一種格式中涕侈,<key>之后的所有內(nèi)容均會被視作其<value>的組成部分,因此煤辨,一次只能設(shè)置一個變量
第二種格式可用一次設(shè)置多個變量裳涛,每個變量為一個"<key>=<value>"的鍵值對,如果<value>中包含空格众辨,可以以反斜線()進(jìn)行轉(zhuǎn)義端三,也可通過對<value>加引號進(jìn)行標(biāo)識;另外鹃彻,反斜線也可用于續(xù)行
定義多個變量時郊闯,建議使用第二種方式,以便在同一層中完成所有功能
示例
編輯Dockerfile文件
FROMbusyboxLABEL maintainer="lixinkuan <lixinkuan@163.com>"ENV DOCROOT="/data/web/html/"COPY index.html${DOCROOT}VOLUME${DOCROOT}
提供index及所需掛載目錄:
[root@docker bbox]# mkdir -pv /data/web/htmlmkdir: created directory ‘/data’mkdir: created directory ‘/data/web’mkdir: created directory ‘/data/web/html’[root@docker bbox]# echo hello Docker > index.html[root@docker bbox]# cat index.htmlhello Docker
制作鏡像:
[root@docker bbox]# docker build -t bbox_file:latest ./Sending build context to Docker daemon? 3.072kBStep 1/5 : FROM busyboxlatest: Pulling from library/busybox07a152489297: Pull complete Digest: sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47Status: Downloaded newer image for busybox:latest ---> 8c811b4aec35Step 2/5 : LABEL maintainer="lixinkuan " --->Runningin87a1f2c22ad6Removing intermediate container 87a1f2c22ad6 ---> 56f723d6220cStep 3/5 : ENV DOCROOT="/data/web/html/" --->Runningin21fd1fcb0474Removing intermediate container 21fd1fcb0474 ---> c095f8dd8418Step 4/5 : COPY index.html ${DOCROOT} --->ee77cd16629aStep 5/5 : VOLUME ${DOCROOT} --->Runningin00474fde8b85Removing intermediate container 00474fde8b85 ---> d51ea735fdd3Successfully built d51ea735fdd3Successfully tagged bbox_file:latest
運(yùn)行容器并查看
[root@docker bbox]# docker run --name a1 -it --rm bbox_file:latest/# ls /data/web/htmlindex.html/# cat /data/web/html/index.htmlhello Docker
另啟終端查看掛載的卷:
[root@docker ~]# docker volume lsDRIVER? ? ? ? ? ? ? VOLUME NAMElocal1dcd37d2c4f2e6a71e0b96a385714ff01cad5d578e396c9b012922e9993aecbflocalb2df5fcd0e1aa58c403d2e8f0ec880feb7dcb1a80a688697e76122adec55e789[root@docker ~]# docker inspect -f {{.Mounts}} a1[{volume1dcd37d2c4f2e6a71e0b96a385714ff01cad5d578e396c9b012922e9993aecbf /var/lib/docker/volumes/1dcd37d2c4f2e6a71e0b96a385714ff01cad5d578e396c9b012922e9993aecbf/_data /data/web/htmllocaltrue }]
14. CMD與RUN
CMD
用于定義鏡像啟動為容器時默認(rèn)運(yùn)行的應(yīng)用程序蛛株。
類似于RUN指令团赁,CMD指令也可用于運(yùn)行任何命令或應(yīng)用程序,不過谨履,二者的運(yùn)行時間點不同
RUN指令運(yùn)行于映像文件構(gòu)建過程中欢摄,而CMD指令運(yùn)行于基于Dockerfile構(gòu)建出的新映像文件啟動一個容器時
CMD指令的首要目的在于為啟動的容器指定默認(rèn)要運(yùn)行的程序,且其運(yùn)行結(jié)束后笋粟,容器也將終止怀挠;不過,CMD指定的命令其可以被docker run的命令行選項所覆蓋
在Dockerfile中可以存在多個CMD指令害捕,但僅最后一個會生效
Syntax
CMD <command>
CMD [“<executable>”, “<param1>”, “<param2>”]
CMD ["<param1>","<param2>"]
前兩種語法格式的意義同RUN
第三種則用于為ENTRYPOINT指令提供默認(rèn)參數(shù)
RUN
指定docker build過程中運(yùn)行的程序唆香。必須是鏡像中存在的命令。
Syntax
RUN <command>
RUN ["<executable>", "<param1>", "<param2>"]
第一種格式中吨艇,<command>通常是一個shell命令躬它,且以“/bin/sh -c”來運(yùn)行它,這意味著此進(jìn)程在容器中的PID不為1东涡,不能接收Unix信號冯吓,因此倘待,當(dāng)使用docker stop <container>命令停止容器時,此進(jìn)程接收不到SIGTERM信號组贺;
第二種語法格式中的參數(shù)是一個JSON格式的數(shù)組凸舵,其中<executable>為要運(yùn)行的命令,后面的<paramN>為傳遞給命令的選項或參數(shù)失尖;然而啊奄,此種格式指定的命令不會以“/bin/sh -c”來發(fā)起,因此常見的shell操作如變量替換以及通配符(?,*等)替換將不會進(jìn)行掀潮;不過菇夸,如果要運(yùn)行的命令依賴于此shell特性的話,可以將其替換為類似下面的格式仪吧。
示例:RUN ["/bin/bash", "-c", "<executable>", "<param1>"]
示例1:基于centos基礎(chǔ)鏡像創(chuàng)建一個運(yùn)行nginx的鏡像
編輯Dockerfile文件:
FROM centosLABEL maintainer="lixinkuan <lixinkuan@163.com>"COPYbase.repo epel.repo /etc/yum.repos.d/RUN yum -y install nginx \? ? ? ? && yum clean all \? ? ? ? && rm -rf /var/cache/yum
提供base.repo epel.repo文件:
[root@docker nginx]# wget lixinkuan.top/base.repo--2018-06-3011:29:08--http://lixinkuan.top/base.repoResolving lixinkuan.top (lixinkuan.top)...47.94.102.99Connecting to lixinkuan.top (lixinkuan.top)|47.94.102.99|:80... connected.HTTP request sent, awaiting response...200OKLength:630Savingto:‘base.repo’100%[=================================================================================>]630--.-K/sin0s2018-06-3011:29:08 (87.9MB/s) - ‘base.repo’ saved [630/630][root@docker nginx]# wget lixinkuan.top/epel.repo--2018-06-3011:29:16--http://lixinkuan.top/epel.repoResolving lixinkuan.top (lixinkuan.top)...47.94.102.99Connecting to lixinkuan.top (lixinkuan.top)|47.94.102.99|:80... connected.HTTP request sent, awaiting response...200OKLength:214Savingto:‘epel.repo’100%[=================================================================================>]214--.-K/sin0s2018-06-3011:29:16(44.2MB/s) - ‘epel.repo’ saved [214/214][root@docker nginx]# lsbase.repo? Dockerfile? epel.repo
創(chuàng)建鏡像:
[root@docker nginx]# docker build -t nginx:v0.1 ./Sending build context to Docker daemon? 4.608kBStep 1/4 : FROM centoslatest: Pulling from library/centos7dc0dca2b151: Pull complete Digest: sha256:b67d21dfe609ddacf404589e04631d90a342921e81c40aeaf3391f6717fa5322Status: Downloaded newer image for centos:latest ---> 49f7960eb7e4Step 2/4 : LABEL maintainer="lixinkuan " --->Runningin6b16128ed7caRemoving intermediate container 6b16128ed7ca ---> b6ef19a3311fStep 3/4 : COPY base.repo epel.repo /etc/yum.repos.d/ ---> e571c2837442Step 4/4 : RUN yum -y install nginx? ? && yum clean all? ? && rm -rf /var/cache/yum --->Runningin445372de8e8dLoaded plugins: fastestmirror, ovl.....執(zhí)行安裝過程省略...Cleaning repos: base epel extras updatesCleaning up everythingMaybe you want: rm -rf /var/cache/yum, to also free up space taken by orphaned data from disabled or removed reposCleaning up list of fastest mirrorsRemoving intermediate container 445372de8e8d ---> 5cf6e8e3517eSuccessfully built 5cf6e8e3517eSuccessfully tagged nginx:v0.1
創(chuàng)建容器并查看:
[root@docker nginx]#dockerrun--nameweb-itnginx:v0.1[root@5e7adf4282c1 /]#rpm-qnginxnginx-1.12.2-2.el7.x86_64#nginx已安裝[root@5e7adf4282c1 /]#
示例2:以busybox制作一個掛載本地/data/web/html目錄并自動運(yùn)行httpd的鏡像
在工作目錄編輯Dockerfile文件
FROM busyboxLABEL maintainer="lixinkuan <lixinkuan@163.com>"ENV DOCROOT="/data/web/html/"COPY index.html${DOCROOT}VOLUME${DOCROOT}CMD /bin/httpd-f-h${DOCROOT}
提供index.html并創(chuàng)建要掛載的目錄
[root@docker bbox]# echo hello Docker > index.html[root@docker bbox]# cat index.htmlhello Docker
創(chuàng)建鏡像文件:
[root@docker bbox]# docker build -t web:v0.1 ./Sending build context to Docker daemon? 3.072kBStep 1/6 : FROM busybox ---> 8c811b4aec35Step 2/6 : LABEL maintainer="lixinkuan " ---> Using cache ---> 56f723d6220cStep 3/6 : ENV DOCROOT="/data/web/html/" ---> Using cache ---> c095f8dd8418Step 4/6 : COPY index.html ${DOCROOT} ---> Using cache --->ee77cd16629aStep 5/6 : VOLUME ${DOCROOT} ---> Using cache ---> d51ea735fdd3Step 6/6 : CMD /bin/httpd -f -h ${DOCROOT} --->Runninginf2fa2b284306Removing intermediate container f2fa2b284306 ---> b8613217ad3cSuccessfully built b8613217ad3cSuccessfully tagged web:v0.1
以新創(chuàng)建的鏡像文件運(yùn)行容器并查看
[root@docker bbox]# docker run --name web -d --rm web:v0.17b71084ebd922728ebf21d22a4e5ff3462443761c82bc22c640764c6d4925b2a[root@docker bbox]# docker container inspect -f {{.Config.Cmd}} web[/bin/sh-c /bin/httpd -f -h ${DOCROOT}][root@docker bbox]# docker exec -it web /bin/sh/# ps auxPID? USER? ? TIME? COMMAND1root0:00/bin/httpd -f -h /data/web/html/7root0:00/bin/sh13root0:00ps aux/# netstat -tnlActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address? ? ? ? ? Foreign Address? ? ? ? State? ? ? tcp00:::80:::*LISTEN
示例3:docker run 時不運(yùn)行鏡像默認(rèn)進(jìn)程,運(yùn)行指定指令
查看當(dāng)前鏡像文件:
[root@docker bbox]#dockerimagesREPOSITORYTAGIMAGEIDCREATEDSIZEwebv0.1b8613217ad3c2hoursago1.15MB
以web:v0.1創(chuàng)建容器,不運(yùn)行默認(rèn)命令
[root@docker bbox]# docker run --name web -it --rm web:v0.1 /bin/sh/# netstat -tnlActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address? ? ? ? ? Foreign Address? ? ? ? State? ? ? /# ps auxPID? USER? ? TIME? COMMAND1root0:00/bin/sh7root0:00ps aux
15. ENTRYPOINT
類似CMD指令的功能庄新,用于為容器指定默認(rèn)運(yùn)行程序,從而使得容器像是一個單獨的可執(zhí)行程序
與CMD不同的是薯鼠,由ENTRYPOINT啟動的程序不會被docker run命令行指定的參數(shù)所覆蓋择诈,而且,這些命令行參數(shù)會被當(dāng)作參數(shù)傳遞給ENTRYPOINT指定指定的程序
不過出皇,docker run命令的--entrypoint選項的參數(shù)可覆蓋ENTRYPOINT指令指定的程序
Syntax
ENTRYPOINT <command>
ENTRYPOINT ["<executable>", "<param1>", "<param2>"]
docker run命令傳入的命令參數(shù)會覆蓋CMD指令的內(nèi)容并且附加到ENTRYPOINT命令最后做為其參數(shù)使用
Dockerfile文件中也可以存在多個ENTRYPOINT指令羞芍,但僅有最后一個會生效
示例1:
編輯Dockerfile文件
FROM busyboxLABEL maintainer="lixinkuan <lixinkuan@163.com>"VOLUME/data/web/html/COPY index.html/data/web/html/EXPOSE80/tcpENTRYPOINT ["/bin/httpd","-f","-h","/data/web/html"]
創(chuàng)建鏡像
[root@docker bbox]# docker build -t web:v0.2 ./Sending build context to Docker daemon? 3.072kBStep 1/6 : FROM busybox ---> 8c811b4aec35Step 2/6 : LABEL maintainer="lixinkuan " ---> Using cache ---> 56f723d6220cStep 3/6 : VOLUME /data/web/html/ --->Runningin3095065d0ebbRemoving intermediate container 3095065d0ebb ---> 36dc68fabc6fStep 4/6 : COPY index.html /data/web/html/ ---> e47f81ec7728Step 5/6 : EXPOSE 80/tcp --->Runninginf86f957ec882Removing intermediate container f86f957ec882 ---> 01a005644fe6Step 6/6 : ENTRYPOINT ["/bin/httpd","-f","-h","/data/web/html"] --->Runningin7a5f8b4f4acfRemoving intermediate container 7a5f8b4f4acf ---> 43d514096d34Successfully built 43d514096d34Successfully tagged web:v0.2
創(chuàng)建容器運(yùn)行并查看:
[root@docker bbox]# docker exec -it web /bin/sh/# ps auxPID? USER? ? TIME? COMMAND1root0:00/bin/httpd -f -h /data/web/html7root0:00/bin/sh13root0:00ps aux/# netstat -tnlActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address? ? ? ? ? Foreign Address? ? ? ? State? ? ? tcp00:::80:::*LISTEN? ? ? /#
運(yùn)行容器時指定執(zhí)行/bin/sh
[root@docker bbox]# docker run --name web -it --rm web:v0.2 /bin/sh
換另一tty查看
[root@docker bbox]# docker exec -it web /bin/sh/# ps auxPID? USER? ? TIME? COMMAND? ? 1 root? ? ? 0:00 /bin/httpd-f-h /data/web/html /bin/sh? ? 7 root? ? ? 0:00 /bin/sh? 13 root? ? ? 0:00 ps aux
并未執(zhí)行/bin/sh,而是執(zhí)行默認(rèn)程序,/bin/sh被當(dāng)作參數(shù)傳遞給/bin/httpd
示例:在docker run時使用entrypoint的時候更換默認(rèn)運(yùn)行的程序
--entrypoint string Overwrite the default ENTRYPOINT of the image
使用鏡像web:v0.2創(chuàng)建容器運(yùn)行時添加--entrypoint選項
[root@docker bbox]# docker run --name web -it --rm --entrypoint /bin/sh web:v0.2/# ps auxPID? USER? ? TIME? COMMAND1root0:00/bin/sh7root0:00ps aux/# netstat -tnlActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address? ? ? ? ? Foreign Address? ? ? ? State? ? ? /#
示例
編輯Dockerfile文件
FROM busyboxLABEL maintainer="lixinkuan <lixinkuan@163.com>"ENV DOCROOT="/data/web/html/"MYPORT="80"COPY index.html ${DOCROOT} COPY entrypoint.sh /bin/COPY test.conf /etc/VOLUME ${DOCROOT}EXPOSE80/tcp#CMD /bin/httpd -f -h ${DOCROOT}#CMD ["/bin/sh","-c","/bin/httpd","-f","-h","${DOCROOT}"]ENTRYPOINT ["/bin/entrypoint.sh"]CMD["/bin/httpd","-f","-h","/data/web/html/"]
提供必須文件(腳本文件需加執(zhí)行權(quán)限)
[root@docker bbox]# cat entrypoint.sh #!/bin/shsed -i"s@^PORT=.*@PORT=${MYPORT}@g"/etc/test.confexec"$@"[root@docker bbox]# cat test.conf PORT=8080
制作鏡像:
[root@docker bbox]# docker build -t web:v0.3 ./Sending build context to Docker daemon? 5.12kBStep 1/10 : FROM busybox ---> 8c811b4aec35Step 2/10 : LABEL maintainer="lixinkuan " ---> Using cache ---> 56f723d6220cStep 3/10 : ENV DOCROOT="/data/web/html/" MYPORT="80" --->Runninginf237100ec645Removing intermediate container f237100ec645 ---> f754b5dcea84Step 4/10 : COPY index.html ${DOCROOT} ---> 3c31424c9b3dStep 5/10 : COPY entrypoint.sh /bin/ ---> 46ec2f5ede8cStep 6/10 : COPY test.conf /etc/ ---> 7db53e00338aStep 7/10 : VOLUME ${DOCROOT} --->Runningin5ae02469f585Removing intermediate container 5ae02469f585 ---> 0e1e3e966318Step 8/10 : EXPOSE 80/tcp --->Runninginae76bcf870caRemoving intermediate container ae76bcf870ca ---> dea89896460dStep 9/10 : ENTRYPOINT ["/bin/entrypoint.sh"] --->Runningin6862bf4a336eRemoving intermediate container 6862bf4a336e ---> ca568e1ff983Step 10/10 : CMD ["/bin/httpd","-f","-h","/data/web/html/"] --->Runningin2aa5dea11848Removing intermediate container 2aa5dea11848 ---> 26bb44795880Successfully built 26bb44795880Successfully tagged web:v0.3
運(yùn)行容器并查看配置文件是否被修改
[root@docker bbox]# docker run --name web -d --rm web:v0.36ec1f5a008e6a08047e8666f6ed3ad4673360805148789faf780baf335ee5637[root@docker bbox]# docker exec -it web /bin/sh/# netstat -tnlActive Internet connections (only servers)Proto Recv-Q Send-Q Local Address? ? ? ? ? Foreign Address? ? ? ? State? ? ? tcp00:::80:::*LISTEN? ? ? /# cat /etc/test.confPORT=80/# exit
示例:通過傳遞變量更改配置文件的方法:
[root@docker bbox]# docker run --name web1 -d --rm -e MYPORT=10080 web:v0.37e3b353e423839d598ee9423e881673066cf99626940b6590e78f34b7622834d[root@docker bbox]# docker exec -it web1 /bin/sh/# cat /etc/test.conf PORT=10080/#