Tes Global 工程師總結的24條 Docker 實用建議
Tes Global的工程師Csaba Palfi從CLI、Dockerfiles、網絡、卷、安全方面總結了他們學習與使用Docker過程中的經驗,一共24條,非常實用。
在TES GLOBAL,我們已經愛上Docker并從Docker的0.8版本開始就在生產環境中使用它。我們的很多開發者都參加了在DockerCon歐洲上的培訓。下面是我們總結的一些tips,希望可以幫到已經有Docker基礎的同學。
1. CLI
1.1 美化docker ps的輸出
將Docker ps的輸出通過管道到 less -S,這樣表格式的行就不會被折疊。
docker ps - a | less -S
1.2 刷新日志
docker的日志不會即時刷新,除非你使用了-F選項:
docker logs <containerid> -F
1.3 從docker inspect中獲取一個單一的值
docker inspect 默認會輸出大量的 JSON 格式的數據。你可以用 jq,來得到某一特定鍵的值?;蛘吣憧梢允褂脙戎玫?go 模板功能:
最后一個docker容器現在運轉正常嗎?
docker inspect --format '{{.State.Running}}' $(docker ps -lq)
1.4 使用docker exec而不是sshd 或者 nsenter
如果你查看過 Docker 的發行版你會你會很清楚這個小技巧。exec 在是在1.3版本中添加的新功能,可以讓你在容器里面運行一個新的進程。這樣你就不必運行 sshd 或者在主機上安裝 nscenter。
2. Dockerfiles
2.1 docker build支持git倉庫
你不但可以從本地的 Dockerfile 中創建 Docker 鏡像,你還可以簡單的給 docker build 指定一個倉庫的 URL ,然后 docker build 會為你做完余下的事情。
2.2 沒有軟件包列表
默認的鏡像(如Ubuntu)是不包含軟件包列表的,目的是讓鏡像體積更小。因此需要在任何的基礎的 Dockerfile 中需要使用 apt-get update。
2.3 留意軟件包的版本
注意軟件包的安裝,因為這些命令也是會緩存起來的。意味著如果你清空了緩存,你可能會得到不同的版本;或者如果緩存長期不更新,你可能不會得到最新的安全更新。
2.4 小體積的基礎鏡像
在Docker Hub上有一個官方的真正零體積的Docker鏡像,它的名字叫做 scratch。所以如果你有這種需求,可以讓你的鏡像從零開始。而大多數的情況下,你最好還是從 busybox 開始,其大小只有2.5M。
2.5 FROM默認會獲取最新的
如果在 FROM 關鍵字后你沒有指定一個版本的 tag ,那么默認就會獲取最新的。請注意這點,并確保盡可能的指定一個特定的版本。
2.6 shell或者是exec模式
在 Dockerfile 中可以通過兩種方式來指定命令(如 CMD RUN 等)。如果你僅僅寫下命令那么Docker 會將其包裹在 sh -c 命令中執行。你也可以寫成一個字符串數組的形式。數組的寫法不需要依賴容器中的 shell,因為其會使用 go 的 exec。Docker 的開發者建議使用后一種方式。
2.7 ADD vs COPY
ADD 和 COPY 都能在創建容器的時候添加本地的文件。但是 ADD 有一些額外的魔力,如添加遠程的文件、unzip 或者 untar 一些文件包等。使用 ADD 之前請了解這種差別。
2.8 WORKDIR和ENV
每個命令都會創建一個新的臨時鏡像并在新的 shell 中運行,所以如果你在Dockerfile中不能運行 cd <directory> 或者 export <var>=<value>。使用 WORKDIR 在多個命令中設置工作目錄并使用 ENV 來設置環境變量。
2.9 CMD和ENTRYPOINT
CMD是當一個鏡像在運行時默認會執行的命令。默認的 ENTRYPOINT 是 /bin/sh -c,然后 CMD 會以參數的形式被傳入。我們可以在 Dockerfile 中覆蓋 ENTRYPOINT 以讓我們的容器像在接受命令行參數(默認的參數在 Dockerfile中的CMD指定)。
Dockerfile中
ENTRYPOINT /bin/ls
CMD ["-a"]
我們覆蓋了命令行但是netrypoint仍然是ls
docker run training/ls -l
2.10 將ADD置于末尾
如果文件發生改變,ADD 會讓緩存失效。不要 在Dockerfile 中添加經常變化的東西,以避免讓緩存失效。將你的代碼放在最后,將庫和依賴放在最前。對于 Node.js 的應用來說,這意味著將 package.json 放在前面,運行 nmp install 然后添加你的代碼。
3. Docker的網絡
Docker 有一個內置的 IP 池,用來指定容器的 ip 地址。它對外是不可見的,通過橋接的網口可以訪問到。
3.1 查找端口的映射
docker run 接收顯式的端口映射作為參數,或者你可以通過 -P 選項來映射所有的端口。第二種做法的好處是能防止沖突??梢酝ㄟ^以下命令查找指定的端口:
docker port containerID portNumber
或者
docker inspect --format '{{.NetworkSettings.Ports}}'
containerID
3.2 容器的IP地址
每一個容器都擁有自己屬于私有網段的 IP 地址(默認是172.17.0.0/16)。IP 可能會在重啟的時候發生變化,如果你想知道其地址,可以用:
docker inspect --format '{{.NetworkSettings.IPAddress}}' containerID
Docker 會嘗試檢查沖突,在需要的情況下會使用不同的網段的地址。
3.3 接管主機的網絡
docker run --net=host 能重用網絡。但是請不要這么做。
4. 卷(volume)
一個繞過目錄或者單一文件寫時復制(copy-on-write)的文件系統,接近零負載(綁定掛載)。
4.1 卷的內容在docker commit的時候不會被保存
在鏡像建立后寫入你的卷沒有太多的意義。
4.2 卷默認是可讀可寫的
但是有一個 :ro 的標志。
4.3 卷和容器是分開存在的
卷只要有一個容器使用他們就會存在??梢栽谌萜髦g通過 --volumes-from 選項共享。
4.4 掛載你的docker.sock
你可以僅僅掛載 docker.sock 就能讓你的容器訪問到 Docker 的 API 。然后你可以在該容器中運行 Docker 的命令。這樣容器甚至還可以殺死自己,在一個容器里面運行一個 Docker的守護者進程是沒有必要的。
5. 安全
5.1 以root身份運行Docker
Docker API 能給 root 的訪問權限,因為你可以將/映射成一個卷,然后讀或者寫?;蛘吣憧梢酝ㄟ^ --net host 接管宿主機的網絡。不要暴露 Docker API 如果你需要請使用 TLS。
5.2 Dockerfile中的USER
默認下 Docker 可以以 root 的身份運行任何命令,但是你可以使用 USER。Docker 沒有用戶的命名空間,因此容器將用戶看作是宿主機上的用戶。但是僅僅是 UID 因而你需要在容器里面添加該用戶。
5.3 使用TLS操作Docker API
Docker 1.3版本添加了對 TLS 的支持。他們使用手動的驗證機制:客戶端和服務端都有一個 Key。把 Key 看做是 root 用戶的密碼。從1.3版本開始,Boot2docker 默認使用 TLS 并且會為你生成 key。
另外生成 Key 需要 OpenSSL 1.0.1 以上版本的支持,然后 Docker daemon 進程需要加上 --tls-verify 選項運行,Docker 會使用安全的端口(2376)。
本文出自:http://www.open-open.com/lib/view/open1419219210718.html