Dockerfile編寫的注意事項


一.Dockerfile合理分層

Dockerfile的寫法不合理,有時候會導致鏡像膨脹,由於Docker是分層設計,而在Dockerfile中,每一條指令都擁有自己的context,而執行到下一條指令時,則會將下一層的構建層疊加到上一層上。因此,假如你在上一層指令做了一些包下載操作安裝操作,然后在下一層再做清理,其實沒什么用,只能說明你下一層引入的diff是0而已。

可以實驗一下:

對照組A:下載清理操作全在同一層

FROM centos
MAINTAINER **

RUN yum -y update
RUN yum -y install wget

RUN wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u121-b13/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-linux-x64.tar.gz" -O /tmp/jdk8_x64.tar.gz && gunzip /tmp/jdk8_x64.tar.gz && tar -C /opt -xf /tmp/jdk8_x64.tar && ln -s /opt/jdk1.8.0_121 /opt/jdk && yum clean all && rm -fr /tmp/*

 

對照組B:下載清理操作放在不同層

FROM centos
MAINTAINER **

RUN yum -y update
RUN yum -y install wget

RUN wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u121-b13/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-linux-x64.tar.gz" -O /tmp/jdk8_x64.tar.gz && gunzip /tmp/jdk8_x64.tar.gz && tar -C /opt -xf /tmp/jdk8_x64.tar && ln -s /opt/jdk1.8.0_121 /opt/jdk 
RUN yum clean all 
RUN rm -fr /tmp/*

 

分別執行構建操作,得到的鏡像差異很大,其中test1為對照組A的構建結果,test2為對照組B的構建結果,兩者相差400M.

alex@ubuntu:~/workspace/docker_project$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
test2               latest              a65c6cced43b        13 minutes ago      1.1 GB
test1               latest              67897397b053        14 minutes ago      729 MB

 二.CMD跟ENTRYPOINT的合理使用

舉個例子,假設你需要容器啟動時,去執行一個后台常駐腳本,那我們一般想到的是在CMD中執行腳本即可。

假設對照組A的Dockerfile:

FROM centos
MAINTAINER **

EXPOSE 8000
WORKDIR /

CMD [ "/bin/bash","-c","/usr/bin/python2.7 -m SimpleHTTPServer" ]

那正常鏡像構建成功后,啟動容器

alex@ubuntu:~/test$ docker build -t test1 .
Sending build context to Docker daemon 2.048 kB
Step 1/5 : FROM centos
 ---> 98d35105a391
Step 2/5 : MAINTAINER shufeng, shufeng.lsf@alibaba-inc.com
 ---> Using cache
 ---> 054ed64f1b34
Step 3/5 : EXPOSE 8000
 ---> Running in e706b62c3c16
 ---> f1fd512940dc
Removing intermediate container e706b62c3c16
Step 4/5 : WORKDIR /
 ---> daa58d7899df
Removing intermediate container 5c51961e6e87
Step 5/5 : CMD /bin/bash -c /usr/bin/python2.7 -m SimpleHTTPServer
 ---> Running in 5dfa9742ccaf
 ---> 6ff71edb9bad
Removing intermediate container 5dfa9742ccaf
Successfully built 6ff71edb9bad

啟動容器:

alex@ubuntu:~/test$ docker run -it -d -p 8001:8000 6ff71edb9bad
a4318a775ec005473f6bc9342cd3c14b55981b334cc6160e7ea17e802f6eff15

查看一下映射情況

可以發現映射成功了。但這樣啟動有適合什么情況呢,只適合后台啟動的情況,讓我們試試另一種啟動容器的方式

alex@ubuntu:~/test$ docker run -it -d -p 8001:8000 6ff71edb9bad /bin/bash
0fdaf33f00fb9307394e4b91577af026627801ab6364ef6729aaf9754eb84455
alex@ubuntu:~/test$ 
alex@ubuntu:~/test$ telnet 127.0.0.1 8001
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Connection closed by foreign host.

可以發現當我需要在容器啟動后進入命令行時,/bin/bash的操作直接將CMD的指令覆蓋了。因此,這時候需要用ENTRYPOINT來代替CMD,對應的Dockerfile如下。

FROM centos
MAINTAINER **

EXPOSE 8000
WORKDIR /
ENTRYPOINT ["/bin/bash","-c","/usr/bin/python2.7 -m SimpleHTTPServer"]

在這里說下CMD跟ENTRYPOINT的區別。

docker run命令行可以覆蓋CMD指令,而ENTRYPOINT則不會,此外,可以通過docker run在命令行中指定的參數,來傳遞給ENTRYPOINT指令中指定的命令,這樣就可以達到動態執行的效果。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM