2017年2月13日 星期一

Docker 新手第二課: 前景/背景/收工休息 圖解狀態轉換

docker 基本指令 這篇觀念教學文是為略懂 docker 的讀者寫的。 你喜歡在你的 linux 電腦上試玩一些有的沒的; 但是不時會遇到一些軟體需要牽拖一大串三姑六婆相依套件, 擔心會把你的工作環境弄亂。 有時甚至還會有相依套件版本跟已安裝軟體不相容的問題。 你發現 docker 正好可以解決這個問題。 安裝好 docker、 對於 volume 跟 port 略有概念、 爬了一些文 [ 門外漢的 Docker 小試身手 三十分钟 Docker 新手入门]、 對 docker 已經有一些概念、 會用 docker ps -a 查看 (執行中或已收工的) docker instances 及當初的完整指令、 用 docker images 查看已下載的映像檔、 docker 常用指令 大概可以看懂兩三成。 但是對於 attach/interactive/terminal/... 又有點頭昏... 對於沒有立志要成為 docker 高手的人來說, 只需要再熟悉這張概念圖就夠了。 從此以後可以專心亂玩其他軟體, 不必再煩惱 docker 指令了! 同場加映不求專精工程師爬文後的一些小技巧及心得。

一、 前景/背景/收工休息

我自己最常使用 docker 的流程大致是這樣:

  1. 比方說想要玩引發 熱烈討論 (<= 好玩!) 的 「畫風轉移/混搭」 混圖魔法好了。 (另文討論) 得知它底層的類神經網路官網名稱是 neural-style; 但是懶得安裝一堆相依套件。
  2. 搜尋 「neural style docker」, 找到很多網友製作好的現成 docker 可用。 挑選一個有原始碼 (Dockerfile)、 文件清楚的版本, 例如 ffedoroff/neural-style
  3. 把 image 下載回自己的硬碟: docker pull ffedoroff/neural-style
  4. [B=>C] 啟動容器, 直接進入 bash (因為我是命令列控): docker run -ti --name nstyle -v /root/share:/out ffedoroff/neural-style bash 以下都假設我們這個 docker instance 叫做 nstyle; 當然你要打一長串的 16 進位數字 container ID 也可以。
  5. 在容器裡面啟動某個跑很久的指令, 等到不耐煩。
  6. [C=>D] (在容器裡面) 按 ^p ^q, 逃離容器, 但它還在背景裡繼續執行。
  7. 在 host 裡面做別的事, 隔一陣子忍不住又想看容器裡的指令的進度。
  8. [D=>C] 把背景的容器帶到前景來: docker attach nstyle 。 如果你用 ssh 連線到遠方主機、 執行 docker, 卻突然斷線, 也可以再度 ssh 連線, 然後用 attach 延續剛才斷掉的連線。 可能需要多按一次 Enter, 才會出現提示符號。
  9. [C=>E]在容器裡面, 事情做完了, 收工: 按 ^d 容器結束執行, 回到 host。
  10. 下次 (甚至可能是重新開機過後) 又要執行同一個容器: [E=>C] 再次啟動 (既有的) 容器, 直接進入 bash: docker start -ai
  11. [C=>E] 事情做完了, 收工: 在容器裡面按 ^d
  12. 不滿意啟動容器時的參數 (例如想要重新調整 -v 所分享的目錄位置)。 [E=>X] 把容器燒毀! docker rm nstyle

以上狀態轉換的重點是標色的部分。 其中 ^p ^q^d 是在容器裡面按的; 其他 docker 指令都是在 host 裡面下的。

執行 run 時如果沒有給 -ti 的選項、 執行 start 時如果沒有給 -ai 的選項, 那麼容器就自動進入背景執行。 因為我看到 bash 才有安全感, 所以比較少這樣用。 不過其實也可以用 docker log nstyle 來查看背景執行的容器印了什麼東西出來。

平常在 linux 下, 若啟動了一個很耗時的指令, 可以開另一個終端機甚或是 ctrl-alt-f1 (到 ctrl-alt-f6) 切換到另一個 bash 繼續做別的事; 那如果是 docker 呢? 可以這樣下: docker exec -it nstyle bash

二、 管理映像檔

如果對某個已下載的映像檔不滿意, 就用 docker rmi 映像名稱 把它刪掉。 相反地, 如果對某個映像檔很滿意, 可能會動手幫它加一些設定或套件。 不過你修改的是一個 (running) docker instance, 當它被 docker rm 時, 一切就隨風而去了。 如果想保留修改, 請先收工離開、 回到 host 底下, 執行 docker commit -m '註解加了什麼' -a '作者(自己)的聯絡資訊' nstyle ffedoroff/neural-style:m1 把修改過的 nstyle 寫入一個新的映像檔, 隨便取一個新的 tag (這裡取名為 m1), 這樣才會保留下來。 以後 run ... ffedoroff/neural-style:m1 就會執行你改過的 m1 版了。

如果硬碟空間快爆掉了, 可以參考 這個問答 把沒用的映像檔通通刪掉。

三、 撇步/常識/心得

以下是我一路上跌跌撞撞學到的雜七雜八知識跟技巧:

  1. 如果 run 的時候忘記取名字, 並不需要把它砍掉重練。 用 rename 就可改名。
  2. 想要讓 docker 內的時區與 host 一致, 可以用 -v /etc/localtime:/etc/localtime [ 來源]
  3. run 的時候, 可以有好幾組 -p (host 的哪些 ports 要借給容器的哪些 ports)、 好幾組 -v (host 的哪些目錄要讓容器看見)、 好幾組 -e (設定環境變數), 但是 所有的選項都必須放在 image 名稱之前, 不然會出現很奇怪看不懂的錯誤訊息。
  4. 如果嫌 ps 指令顯示的資訊太少, 可以用 docker inspect nstyle 查看一個 docker instance 詳細的資訊 => 不要問我, 從這裡再研究下去你已經超過我的程度了。

再來是 docker daemon 除錯與設定。 上網問問題之前, 最好先用 docker info 查看你的系統的 docker daemon 版本等等資訊, 並擇要貼上, 高手才幫得上忙。 有時還需要用 journalctl -u docker 查看 daemon 印的錯誤訊息。 有時高手會告訴你: 啟動 docker daemon 時要給某某選項。 根據 這個 issue, 在 ubuntu 16.04 底下, 你要修改的設定檔不是 /etc/default/docker 而是 /etc/docker/daemon.json 。 語法請見 Daemon configuration file 這一節。 (更精確但更囉嗦的做法請見 這裡。)

四、 安全考量及結論

  1. 不要在 docker 裡面安裝 ssh 服務!
  2. 用 「非 root 帳號」 執行 docker 比較安全嗎? 未必!
  3. 如果你的 commit 有一天有可能會 push 到 dockerhub 去分享, 請務必注意: 凡是遇到需要在 docker 裡面放密碼或金鑰等等私密資訊的情況, 要特別小心!

用了一陣子之後的心得: 基於安全性、 存活長短、 沒有 IP 位址等等因素, 如果沒有其他配套措施的話, 其實 docker 並不太適合直接讓網管拿來提供服務。 最適合用 docker 的, 真的就是我們這種愛亂玩軟體的家庭用戶無誤。 所以對於 docker, 我只學到夠用就好而已; 剩下的時間要拿去玩別的好玩東東啊!

1 則留言:

  1. 啊, 昨天才發現最近這幾篇的程式碼 <code>...</code> 部分都壞掉了 (哭) 因為我手殘, 存檔前多按了一個 (自訂的) 快速鍵, 把所有半型標點變成全形標點。 今天把它修好了。 可是先前都沒有讀者發現... 有點傷心啊~~

    回覆刪除

因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。