Best Practice of Docker

 

RUN

  • source之類無效
  • 在container運行前作的事不會保留到之後
    • ex: roscore在這裡下, docker run後一樣不存在

ADD

  • build時與RUN wget一樣都有可能不會被cache
    • https://github.com/moby/moby/issues/12361
    • github的話個人只在windows的docker遇到, linux會正常cache
  • 用法ADD http://example.com/big.tar.xz /usr/src/things/

ARG

  • 只在build時有效, 也可以在build時帶入--build-arg
  • 必須是key=value

ENV

  • 在build & docker run時都有效
  • 可以是key value or key=value

在ENV與ARG參數的設定上,可以透過下面方式

  • ${variable:-word} 代表,如果variable有給值,則以variable設定的文字為主,如未設定,則以word字串為主。
  • ${variable:+word} 代表,如果variable有給值,則值為word;如果variable未給值,則最後結果為空字串(empty)。

有沒有大括號都可


==docker build失敗會產生多餘的container**

https://stackoverflow.com/questions/36808476/why-docker-build-image-from-docker-file-will-create-container-when-build-exit-in

Layers

太多行的RUN可能會導致build的非常慢

https://stackoverflow.com/questions/47079114/should-i-minimize-the-number-of-docker-layers

最好的實作辦法:

  • making sure the most general steps, and the longest are first, that will then cached
  • making sure the longest RUN command come first and in their own layer (again to be cached)

optimized的tools

  • dive: https://github.com/wagoodman/dive

exclude特定files

https://docs.docker.com/engine/reference/builder/#dockerignore-file You can even ==use the .dockerignore file to exclude the Dockerfile and .dockerignore files.== These files are still sent to the daemon because it needs them to do its job. But the ADD and COPY instructions do not copy them to the image.

build用/bin/sh

如何用/bin/bash來跑dockerfile內的RUN

https://stackoverflow.com/questions/20635472/using-the-run-instruction-in-a-dockerfile-with-source-does-not-work https://github.com/moby/moby/issues/7281

不能用RUN來執行background process

以下無效

要用CMD才行

https://stackoverflow.com/a/57175879

  • 上面的&還是會有執行該指令的output, 只是ctrl+c不會中斷他
  • 要做到完全無output要用nohup
    • https://stackoverflow.com/questions/9190151/how-to-run-a-command-in-the-background-and-get-no-output

nohup /path/to/your/script.sh > /dev/null 2>&1 &

https://charleslin74.pixnet.net/blog/post/405455902 https://kknews.cc/zh-tw/code/r3z2e3v.html ==2>&1表明將文件描述2(標準錯誤輸出)的內容重定向到文件描述符1(標準輸出)==,為什麼1前面需要&?當==沒有&時,1會被認為是一個普通的文件==,有&表示重定向的目標不是一個文件,而是一個文件描述符。 1與2誰先幾乎無差, https://blog.csdn.net/u011630575/article/details/52151995

暫時性操作無效, 像是修改環境變數

COPY新檔案失效

docker build --no-cache .

確保container不會結束

解法有三種

  • bin/bash or tail -f /dev/null
  • xxx.sh ; sleep infinity
  • &後面要導向output, ex: roscore &

詳細解釋

use tail -f /dev/null or /bin/bash to make sure you shell done and suspend a process in system so that docker container not shutdown

https://stackoverflow.com/questions/42218957/dockerfile-cmd-instruction-will-exit-the-container-just-after-running-it

像是把roscore &寫在dockerfile的cmd話也會觸發end, 因為roscore &這個指令執行完了 但如果只用roscore因為有output卡住就不會end

You run a container, which ==runs a shell script to perform some tasks. When the shell script completes, the container will exit==, because there’s nothing left for the container to run. https://www.tutorialworks.com/why-containers-stop/

docker的偵測process機制(PID 1)

https://stackoverflow.com/a/30632659 PID 1是啟動init 進程,是系統的第一個進程,又叫超級進程,也叫根進程。它負責產生其他所有用戶進程。所有的進程都會被掛在這個進程下,如果這個進程退出了,那麼所有的進程都被kill 。如果一個子進程的父進程退了,那麼這個子進程會被掛到PID 1 下面。(注:PID 0 是內核的一部分,主要用於內進換頁) https://coolshell.cn/articles/17998.html

官方文件對run mulitple background process的教學

https://docs.docker.com/config/containers/multi-service_container/

可以用runit來把container當小vm用

https://github.com/wk8/docker-runit

如果在背景run service也有可能遇到相同問題

https://stackoverflow.com/questions/25775266/how-to-keep-docker-container-running-after-starting-services

當然實際在delpoy時設計的container應該是

  • there is only one process running (i.e. you should have one container for Nginx, and one for supervisord or the app it’s running)
  • additionally, that process should run in the foreground

    https://stackoverflow.com/a/25775424