# 快速學會使用Docker指南-中原大學電學618圖形識別研究室專用 ### 參考文件 * Docker的簡單介紹及原理:https://cwhu.medium.com/docker-tutorial-101-c3808b899ac6 最簡單快速上手的教學。 * Docker——從入門到實踐:https://philipzheng.gitbook.io/docker_practice Step by Step的從Docker概念到安裝都說明給你看。 * Docker Beginner Guide:https://github.com/twtrubiks/docker-tutorial 最詳細的教學。 ## ●映像檔Image Docker 映像檔是一個模板,用來重複產生容器實體。例如:一個映像檔裡可以包含一個完整的 MySQL 服務、一個 Golang 的編譯環境、或是一個 Ubuntu 作業系統。 透過 Docker 映像檔,我們可以快速的產生可以執行應用程式的容器(Container)。而 Docker 映像檔可以透過撰寫由命令行構成的 Dockerfile 輕鬆建立,或甚至可以從公開的地方下載已經做好的映像檔來使用。 舉例來說,如果我今天想要一個含有python3.8及tensorflow-gpu的執行環境跑我寫好的程式,我可以直接到 DockerHub 找到相對應的映像檔 ,而不需要自己想辦法打包一個執行環境。 一般來說電學618實驗室伺服器已下載好常用的映像檔,可以不用自己撰寫Dockerfile建立映像檔(但你要寫也不是不行),因此後續不會教學如何撰寫Dockerfile建立映像檔,如果想快速了解可看上方的***簡單介紹及原理***。 ## ●容器Container 就像是用蛋糕模具烤出來的蛋糕本體,容器是用映像檔建立出來的執行實例。它可以被啟動、開始、停止、刪除。每個容器都是相互隔離、保證安全的平台。 可以把容器看做是一個執行的應用程式加上執行它的簡易版 Linux 環境(包括 root 使用者權限、程式空間、使用者空間和網路空間等)。換句話說,在看不懂上述的情況下,可以暫時先把Container視為一種虛擬環境(但理論上並不是,可以自行查閱說明),裡面你要下載什麼套件、tool-kit,環境如何設定都可以,不會有需要superuser(指令要sudo)權限的問題,也不會影響到使用其他容器的使用者。 執行Container有兩種情況,一個是[當你還沒建立過Container時的指令(2-1)](https://hackmd.io/@TzuYingC/H1gkDY9fs#2-1%E5%BB%BA%E7%AB%8B%E4%B8%A6%E5%9F%B7%E8%A1%8C%E4%B8%80%E5%80%8B%E6%96%B0%E7%9A%84%E5%AE%B9%E5%99%A8Container),另一個是[當你已經有可以使用的Container時,要如何重新開啟這個Container使用(2-2)](https://hackmd.io/@TzuYingC/H1gkDY9fs#2-2%E4%B9%8B%E5%89%8D%E5%B7%B2%E7%B6%93%E5%BB%BA%E7%AB%8B%E4%BA%86%E4%B8%80%E5%80%8B%E5%AE%B9%E5%99%A8Container%EF%BC%8C%E6%83%B3%E8%A6%81%E9%87%8D%E6%96%B0%E9%80%B2%E5%85%A5%E9%80%99%E5%80%8B%E5%AE%B9%E5%99%A8Container)。後續均會說明。 ## ●從零開始使用實驗室伺服器跑程式 ### 1.查看有哪些映像檔 在實驗室伺服器中,已經安裝好幾個常見的映像檔,可以使用`docker images`查看 ![](https://i.imgur.com/qICsS4W.png) REPOSITORY是各個映像檔的名稱,TAG為版本標註,IMAGE ID是映像檔的ID。每個映像檔即使REPOSITORY跟TAG都不同,只要IMAGE ID一樣,其實都是同一個映像檔。 舉例來說可以看到tensorflow/tensorflow有兩個版本(TAG):latest-gpu、1.15.0-gpu-py3。 tensorflow/tensorflow:latest-gpu代表當你使用這個映像檔執行Container時,這個Container裡會自己幫你安裝好**最新版本**的tensorflow-gpu、tensorflow跟對應的python檔案以及python套件。 而tensorflow/tensorflow:1.15.0-gpu-py3則代表當你使用這個映像檔執行Container時,這個Container裡會自己幫你安裝好**1.15版本**的tensorflow-gpu、**1.15版本**的tensorflow、**python3以上版本**以及python套件。 實驗室通常都會已經裝好含有tensorflow的映像檔,因為大部分人做專題都會用到python的tensorflow跑,其他比較小的套件像是open-cv、matlibplot之類的,可以在進入Container之後在裡面安裝(pip install之類的,你之前怎麼安裝套件就怎麼安裝)。 如果有你想要的環境但上面的映像檔沒有的,並且你覺得很重要的(例如pytorch、nvidia cuda),可以直接詢問管理伺服器的學長姊,如果他們評估後有需要安裝就會幫忙安裝,不是很必要就請自行慢慢安裝套件。 ### 2-1.建立並執行一個新的容器(Container) 最常用的指令為 ```! docker run -v {local_path}:{container_path} --name {container_name} --gpus {gpu_cond} --shm-size {shm_size} -p {local_port}:{container_port} {images_ID_or_repo:image_tag} -it bash ``` 實際範例 ```! docker run -v /data/ourProj:/data_in_docker --name example --gpus all --shm-size=8G -p 1234:6666 tensorflow/tensorflow:latest-gpu -it bash ``` * `docker run` : 執行Container。 * `-v` : 執行時把Container裡面的檔案路徑Mapping到實體主機的檔案路徑。 - `{local_path}` : 是把實體主機的某個路徑掛載到container內的絕對路徑。 (通常你的資料集跟程式碼都會放在實驗室伺服器的`/data/`下,`ourProj`代表你的專題的檔案路徑,e.g.,/data/Pix2pix/)。 - `{container_path}` : 要掛載進 container 內的指定路徑 (預設路徑是在 `/` 下,可以使用相對於 `/`的相對路徑,或是絕對路徑,若是資料夾不存在則會自動建立資料夾)。 也就是說當你在container內使用到`{container_path}`的路徑時,container會自動mapping到對應的實體主機路徑。這樣的好處在於之後搬到其他電腦上,程式碼中會使用到的檔案路徑也不用一直改(維持`{container_path}`),只要在建立Container時修改對應的實體主機檔案路徑`{local_path}`就好。 * `--name` : 幫你的Container取名,以便跟其他人區分,也不用打一長串的CONTAINER ID。 * `--gpus` : 讓你的Container可以擷取到gpu,`all`是指擷取到所有的cpu,通常實驗室會指定讓你們用哪張顯卡,只時候就要根據顯卡編號去指定,例如`--gpus 1`。 * `--shm-size` : 指定container 可以使用的 shared memory,預設為64MB,若出現類似以下error時請重新建立container並加上此指令。 :::danger ERROR: Unexpected bus error encountered in worker. This might be caused by insufficient shared memory (shm). ::: * `-p` : 指定 container port 對應到 local 的port * `{local_port}` : 實體主機上的port,由於每台server都有不同組別使用,因此建議設定避免覆蓋到其他組別的port。當你要連上port時,請在網址列輸入`{server ip}:{local_port}` * `{container_port}` : container 內部的 port,也就是程式碼中使用的port,例如jupyter預設用6666,web預設用8888或80 * `{ImagesID | REPOSITORY:image_tag}` : 你要使用的映像檔,輸入`IMAGE ID`或是`REPOSITORY`:`TAG`。 * `-it` : `-i` 讓Container的標準輸入保持打開。`-t` 讓 Docker 分配一個虛擬終端(pseudo-tty)並綁定到Container的標準輸入上。 * `bash` : 啟動一個 bash 終端,允許使用者進行互動。 還有很多不同的參數選項,有需要可以自行用`docker run --help`指令查看,或是自己google。 執行指令之後就會自動進入Container內,通常指令輸入列尾端會從$變成# ![](https://i.imgur.com/8saWQaB.png) 接下來你要安裝什麼python套件,安裝什麼都可以,不會干擾到其他人(Container)。 ### 2-2.之前已經建立了一個容器(Container),想要重新進入這個容器(Container) #### 2-2-1 首先查看你之前建立並要使用的容器(Container)是哪個 `docker ps -a` ![](https://i.imgur.com/kC5uogy.png) 以此為範例,目前已經建立了四個Container,假設你的Container是從上數下來第三個 #### 2-2-2 如果你的容器(Container)的STATUS是Exited 代表Container正在終止,需要喚醒它(可以想成電腦休眠中要開機) ![](https://i.imgur.com/fbk7B2O.png) * 喚醒終止的Container `docker start [container ID|NAMES]` 使用CONTAINER ID或是NAMES都可以,以上圖為範例則是`docker start avalanche0908` * 確認它的狀態是否開啟,如果為Up代表正確喚醒 `docker ps -a` ![](https://i.imgur.com/z72TeUq.png) #### 2-2-3 如果你的容器(Container)STATUS是Up 代表Container可以直接使用,可以直接進入Container使用 ![](https://i.imgur.com/z72TeUq.png) * 進入已啟動的Container `docker exec -it [container ID|NAMES] bash` 以上圖為例則是`docker exec -it avalanche0908 bash` ![](https://i.imgur.com/Dvif1N5.png) 當指令輸入列的尾端$變成#代表成功進入Container,***接下來就可以執行你的程式,或是安裝需要的套件了!!!***