24條 Docker 建議
在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 卷和容器是分開存在的
卷只要有一個容器使用他們就會存在。可以在容器之間透過--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)。
相關文章
- Docker安全部署的17條建議Docker
- 構建Docker Image的五個建議Docker
- 避開NullPointerException的10條建議NullException
- 控制IT預算的5條建議
- 使用Backbone構建精美應用的7條建議
- 高效設計構建軟體的十三條建議
- 程式碼簡潔的十條建議
- 成為最差開發者的10條建議
- Pinterest:九條實用的旅行建議REST
- 融入開源社群的4條建議
- Android 優化APP 構建速度的17條建議Android優化APP
- Android 優化 APP 構建速度的 17 條建議Android優化APP
- 避免誤刪檔案的12條建議
- PHP程式碼優化的40條建議PHP優化
- Python效能優化的20條建議Python優化
- JAVA程式碼編寫的30條建議 .Java
- 不當工作狂的11條建議
- JAVA程式碼編寫的30條建議Java
- 也給圖靈教育提一條建議圖靈
- 高效專案管理的十條建議(轉)專案管理
- 提高軟體測試能力的19條建議
- 總結 90 條寫 Python 程式的建議Python
- 提升 JumpServer 安全的10條建議 | IDCFServer
- 關於遊戲本地化的13條建議遊戲
- 一個PHP開發者總結的九條建議PHP
- 讓論文摘要更出彩的十條建議
- 提高工作效率的6條建議
- 老程式設計師的10條中肯建議程式設計師
- 成為優秀Swift開發者的10條建議Swift
- 降低Java垃圾回收開銷的5條建議Java
- 提高程式設計能力的7條建議程式設計
- 雅虎軍規——前端優化的35條建議前端優化
- 快速學習新技術的幾條建議
- 一條sql語句的建議調優分析SQL
- 給新程式設計師的10條建議程式設計師
- JAVA程式碼編寫的30條建議(轉)Java
- 工作總結!日誌列印的11條建議
- 給程式設計師“菜鳥”的6條建議程式設計師