【Docker進階】Dockerfile最佳實踐(一)

jopen 9年前發布 | 31K 次閱讀 Docker

本文是Docker入門教程第三章-DockerFile的進階篇,作者主要介紹了緩存、標簽、端口以及CMD與ENTRYPOINT的最佳用法,并通過案例分析了注意事項,比如我們應該使用常用且不變的Dockerfile開頭、通過-t標記來構建鏡像、勿在Dockerfile映射公有端口等等。

Dockerfile使用簡單的語法來構建鏡像。下面是一些建議和技巧以幫助你使用Dockerfiles。

1:使用緩存

Dockerfile的每條指令都會將結果提交為新的鏡像,下一個指令將會基于上一步指令的鏡像的基礎上構建,如果一個鏡像存在相同的父鏡像和指令(除了ADD),Docker將會使用鏡像而不是執行該指令,即緩存。

為了有效地利用緩存,你需要保持你的Dockerfile一致,并且盡量在末尾修改。我所有的Dockerfile的前五行都是這樣的:

FROM ubuntu
MAINTAINER Michael Crosby <michael@crosbymichael.com>
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
RUN apt-get upgrade -y


更改MAINTAINER指令會使Docker強制執行RUN指令來更新apt,而不是使用緩存。

所以,我們應該使用常用且不變的Dockerfile開始(譯者注:上面的例子)指令來利用緩存。

2:使用標簽

除非你正在用Docker做實驗,否則你應當通過-t選項來docker build新的鏡像以便于標記構建的鏡像。一個簡單的可讀標簽將幫助你管理每個創建的鏡像。

docker build -t="crosbymichael/sentry" .

注意,始終通過-t標記來構建鏡像。

3:公開端口

兩個Docker的核心概念是可重復和可移植。鏡像應該可以運行在任何主機上并且運行盡可能多的次數。在 Dockerfile中你有能力映射私有和公有端口,但是你永遠不要通過Dockerfile映射公有端口。通過映射公有端口到主機上,你將只能運行一個容器化應用程序實例。(譯者注:運行多個端口不就沖突啦)

#private and public mapping
EXPOSE 80:8080

#private only EXPOSE 80</pre>

如果鏡像的使用關心容器公有映射了哪個公有端口,他們可以在運行鏡像時通過-p參數設置,否則,Docker會自動為容器分配端口。

切勿在Dockerfile映射公有端口。

4:CMD與ENTRYPOINT的語法

CMD和ENTRYPOINT指令都非常簡單,但它們都有一個隱藏的容易出錯的“功能”,如果你不知道的話可能會在這里踩坑,這些指令支持兩種不同的語法。

CMD /bin/echo
#or
CMD ["/bin/echo"]


這看起來好像沒什么問題,但仔細一看其實兩種方式差距很大。如果你使用第二個語法:CMD(或ENTRYPOINT)是一個數組,它執行的命令完全像你期望的那樣。如果使用第一種語法,Docker會在你的命令前面加上/bin/sh -c,我記得一直都是這樣。

如果你不知道Docker修改了CMD命令,在命令前加上/bin/sh -c可能會導致一些意想不到的問題以及不容易理解的功能。因此,在使用這兩個指令時你應當使用數組語法,因為數組語法會確切地執行你打算執行的命令。

使用CMD和ENTRYPOINT時,請務必使用數組語法。

5. CMD和ENTRYPOINT 結合使用更好

docker run命令中的參數都會傳遞給ENTRYPOINT指令,而不用擔心它被覆蓋(跟CMD不同)。當與CMD一起使用時ENTRYPOINT表現會更好。讓我們來研究一下我的Rethinkdb Dockerfile,看看如何使用它。

#Dockerfile for Rethinkdb 
#http://www.rethinkdb.com/

FROM ubuntu

MAINTAINER Michael Crosby <michael@crosbymichael.com>

RUN echo "deb  RUN apt-get update RUN apt-get upgrade -y

RUN apt-get install -y python-software-properties RUN add-apt-repository ppa:rethinkdb/ppa RUN apt-get update RUN apt-get install -y rethinkdb

#Rethinkdb process EXPOSE 28015 #Rethinkdb admin console EXPOSE 8080

#Create the /rethinkdb_data dir structure RUN /usr/bin/rethinkdb create

ENTRYPOINT ["/usr/bin/rethinkdb"]

CMD ["--help"]</pre>

這是Docker化Rethinkdb的所有配置文件。在開始我們有標準的5行來確保基礎鏡像是最新的、端口的公開等。當ENTRYPOINT指令出現時,我們知道每次運行該鏡像,在docker run過程中傳遞的所有參數將成為ENTRYPOINT(/usr/bin/rethinkdb)的參數。

在Dockerfile中我還設置了一個默認CMD參數--help。這樣做是為了docker run期間如果沒有參數的傳遞,rethinkdb將會給用戶顯示默認的幫助文檔。這是你所期望的與rethinkdb交互有著相同的功能。

docker run crosbymichael/rethinkdb


輸出

Running 'rethinkdb' will create a new data directory or use an existing one,
and serve as a RethinkDB cluster node.
File path options:
-d [ --directory ] path           specify directory to store data and metadata
--io-threads n                    how many simultaneous I/O operations can happen
                                at the same time

Machine name options: -n [ --machine-name ] arg         the name for this machine (as will appear in                                 the metadata).  If not specified, it will be                                 randomly chosen from a short list of names.

Network options: --bind {all | addr}               add the address of a local interface to listen                                 on when accepting connections; loopback                                 addresses are enabled by default --cluster-port port               port for receiving connections from other nodes --driver-port port                port for rethinkdb protocol client drivers -o [ --port-offset ] offset       all ports used locally will have this value                                 added -j [ --join ] host:port           host and port of a rethinkdb node to connect to .................</pre>

現在,讓我們帶上--bind all參數來運行容器。

docker run crosbymichael/rethinkdb --bind all


輸出

info: Running rethinkdb 1.7.1-0ubuntu1~precise (GCC 4.6.3)...
info: Running on Linux 3.2.0-45-virtual x86_64
info: Loading data from directory /rethinkdb_data
warn: Could not turn off filesystem caching for database file: "/rethinkdb_data/metadata" (Is the file located on a filesystem that doesn't support direct I/O (e.g. some encrypted or journaled file systems)?) This can cause performance problems.
warn: Could not turn off filesystem caching for database file: "/rethinkdb_data/auth_metadata" (Is the file located on a filesystem that doesn't support direct I/O (e.g. some encrypted or journaled file systems)?) This can cause performance problems.
info: Listening for intracluster connections on port 29015
info: Listening for client driver connections on port 28015
info: Listening for administrative HTTP connections on port 8080
info: Listening on addresses: 127.0.0.1, 172.16.42.13
info: Server ready
info: Someone asked for the nonwhitelisted file /js/handlebars.runtime-1.0.0.beta.6.js, if this should be accessible add it to the whitelist.


就這樣,一個全面的可以訪問db和管理控制臺的Rethinkdb實例就運行起來了,你可以用與鏡像交互一樣的方式來與其交互。它功能非常強大但是簡單小巧。

CMD和ENTRYPOINT 結合在一起使用更好。

我希望這篇文章可以幫助你使用Dockerfiles以及構建鏡像。Dockerfile是Docker的重要一部分,它簡單而且使用方便,無論你是構建或是使用鏡像。我打算投入更多的時間來提供一個完整的、功能強大但簡單的解決方案來使用Dockerfile構建Docker鏡像。

原文鏈接:
Dockerfile Best Practices - take 1 (翻譯:田浩 校對:李穎杰)
來自:http://dockerone.com/article/131

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!