Google Code Prettify

2018年1月6日 星期六

使用 Dockerfile 創建 docker 鏡像

繼「製作包含 java 的 docker 鏡像」手動的製作 docker image 後,這一篇要將手動的流程自動化。docker 提供了一個自動化的方式,就是寫一個叫作 Dockerfile 的 script 文檔,這個文檔不一定要命名為 Dockerfile,這只是預設的檔名。上一篇的 images 是在 centos 中安裝 java 9,所以,我先在 home 目錄下建立一個暫時的目錄 tmp,將 openjdk-9.0.1_linux-x64_bin.tar.gz 放入目錄裡,並於目錄中新增如下的 Dockerfile。
FROM centos:latest
MAINTAINER "Steven Shi"<hi.steven@gmail.com>
ADD openjdk-9.0.1_linux-x64_bin.tar.gz /usr/local
RUN ln -s /usr/local/jdk-9.0.1 /usr/bin/java
ENV JAVA_HOME /usr/bin/java
ENV PATH $JAVA_HOME/bin:$PATH
CMD java -version
然後下這樣的指令:
docker build -t steven/java9 .
console 會出現如下的訊息後,幾秒就完成了一個鏡像,其中有了 -t 參數後面才能帶我們想要的鏡像名稱,最後的句點 (.) 是指在現在的目錄裡尋找 Dockerfile。
接下來說明一下 Dockerfile 中指令的用途:
  • FROM centos:latest
每個鏡像需要有個"基礎鏡像",FROM 即指出要使用的基礎鏡像是 centos 的最新版本。
  • MAINTAINER "Steven Shi"<hi.steven@gmail.com>
MAINTAINER 指令指出這個鏡像由誰創建和維護,後面的參數並沒有規定格式,姓名加上 email,這只是眾多用法中的一種。
  • ADD openjdk-9.0.1_linux-x64_bin.tar.gz /usr/local
ADD 指令的第一個參數是要安裝的檔案的路徑,因為我將 openjdk-9.0.1_linux-x64_bin.tar.gz 和 Dockerfile 放在同一路徑,所以直接寫檔名即可,第二個參數是安裝進 container 的路徑。ADD 指令具有解壓縮的功能,另外一個類似的指令 COPY 就只能將檔案複製到指定的路徑。
  • RUN ln -s /usr/local/jdk-9.0.1 /usr/bin/java
上一篇在解壓縮好 JDK 後,我們有建立一個連結以方便後續的存取,要在 container 中執行命令就用 RUN。如果有多個命令要執行,可以寫好幾個 RUN,但是,建議是在每個命令後加上反斜線 \,然後於次行寫下一個命令,這個方式製作出來的鏡像會比較小,因為每執行一次 RUN,docker 會產生一個鏡像層,多出一點體積。
  • ENV JAVA_HOME /usr/bin/java
  • ENV PATH $JAVA_HOME/bin:$PATH
上一篇手工製作時,我們沒有指定 JAVA_HOME 並設定 PATH,但是一般來說,Java 安裝好之後,這是必要的事。如果要設定環境變數,就用 ENV。
  • CMD java -version
CMD 可以用來在 container 啟動後執行命令,要特別注意的是 CMD 只可以不寫或只寫一次! 這裡簡單的執行 java -version 以確定鏡像製作有成功。
想要了解更多? 可以參考官網 https://docs.docker.com/engine/reference/builder/
【補充】
製作好 image 可以試著把它推到 docker hub,首先當然要註冊一個帳號,我註冊的是 twleader,接著 create 一個 repository,我 create 一個命名為 java9 的 repository,接著如下:
  • docker login
 登入 docker hub,輸入帳號、密碼。
  •  docker tag f6cc7ec468a3 docker.io/twleader/java9
  •  docker push docker.io/twleader/java9
使用 tag 指令,為原本的 steven/java9 加上一個標籤,我命名 docker.io/twleader/java9 這樣才能 push 到 docker hub 的 twleader 帳號裡的 java9 repository,接著就是下 push 指令推到 docker hub 上。



2018年1月5日 星期五

製作包含 java 的 docker 鏡像

在看完「docker 基本指令」後,我們已經可以製作一個 centos 的鏡像,這篇要在這個鏡像中安裝 Java 9,並且包裝成鏡像。首先下載 Open JDK,下載後我將它放在 /home/steven/Software 目錄下,如下: (openjdk-9.0.1_linux-x64_bin.tar.gz)
接下來 … 要開始了 …
  • docker run -i -t -v /home/steven/Software:/mnt/software centos /bin/bash
下了 docker run 後,因為我之前安裝的 centos 鏡像已經被我移除,在本機找不到後,docker 自動連到 docker hub 再下載一個。這次的 docker run 指令後又多了 -v 參數,這是要掛載磁碟,將本機的 /home/steven/Software 掛載到 centos container 裡的 /mnt/software,所以,在進入 container 後,下 ls -l 指令,又可以看到和本機 /home/steven/Software 一樣的內容。

-i: 即 --interactive, 這個參數要求 docker 保持標準輸入裝置 (stdin)
-t: 即 --tty,這個參數要求 docker 分配一個終端裝置
  •  tar zxvf openjdk-9.0.1_linux-x64_bin.tar.gz -C /usr/local
進入 /mnt/software 目錄後,以上述指令將 open jdk 9 解壓縮到 /usr/local 目錄下,如上圖,可以看到 /usr/local 目錄裡產生了 jdk-9.0.1。
  • ln -s /usr/local/jdk-9.0.1 /usr/bin/java
為了方便存取,建立一個連結到 /usr/bin/java。
  • ./java -version
進入 /usr/bin/java/bin 目錄,下 java -version 指令看一下 jdk 版本,如上,果然是 9.0.1 版。
  • docker ps -a
離開 container 回到本機,下 docker ps -a 看一下剛剛創建的 container,如上圖。
  •  docker commit 87426bc47a5e steven/java9
如上下 docker commit 提交一個鏡像,我們將它命名為 steven/java9 (87426bc47a5e 為 container ID),這個指令執行需要一點點時間,然後提交後顯示出鏡像 ID。
  • docker images
下 docker images 列出所有鏡像,果然可以看到 steven/java9,IMAGE ID 也正確。
  • docker run --rm steven/java9 /usr/bin/java/bin/java -version
使用 docker run 指令啟動剛製作好的鏡像的 container,並且執行該 container 中的 /usr/bin/java/bin/java -version 看看是不是和之前安裝好後執行出來的版本一樣? 如上圖這樣就確認我們確實有安裝好了! --rm 參數是要求 docker 在執行完指令退出 container 後立即刪除該 container。



2018年1月3日 星期三

docker 基本指令

在「Installing and Configuring Docker (Scientific Linux 7.3)」中已經安裝好 docker,這裡來試用看看 …
  • docker images
這個指令會列出所有已安裝的鏡像,因為這個時候才剛安裝好 docker,沒有任何鏡像。
  •  docker pull centos
由 docker hub 上拉取 CentOS 鏡像,再下一次 docker images,如下,可以看到 centos 鏡像已經存在本機。
上圖列出來的項目共有五欄,說明如下:
    • REPOSITORY: 鏡像名稱 (docker.io/centos)
    • TAG: 鏡像的標籤,上圖顯示 latest,表示這個鏡像是最新版本。
    • IMAGE ID: 鏡像的序號,這個序號很重要,每個 image 會有一個唯一的序號,後續如果要操作這個鏡像,會用到這個序號。
    • CREATED: 鏡像創建的時間,表示的方式是離現在的時間多久。
    • SIZE: 鏡像的大小
  •  docker search centos
search 指令可以在 docker hub 上找出指定的鏡像,如上圖,列出了所有 centos 的鏡像。
  •  docker save centos > centos.tar
想把鏡像存起來? 用這個指令,導出成一個 tar 檔,完成後,可以 ls 看一下,約 200 MB,帶著這個 tar 檔,可以在別的 docker 機器上導入,這在公司裡應該會常用到,因為大部分的公司會有防火牆,server 不一定可以隨意的連線到 docker hub,所以在可以連線的地方先拉取一個鏡像儲存後,帶到要安裝的 server 導入。
  •  docker load < centos.tar
上面就是導入鏡像的指令
  •  docker run -i -t centos /bin/bash
如上,即可啟動容器,參數說明如下:
    • -i : 啟動容器打開標準輸入 (STDIN) ,之後即可使用鍵盤輸入。
    • -t : 啟動容器後給予容器一個虛擬的終端設備 (pseudo-TTY),讓使用者可以與容易對話。 
    • centos : 要運行的鏡像名稱,更嚴謹的輸入方式是 centos:latest,表示要使用最新版本,沒有打 latest,就預設是最新版本。
    • /bin/bash : 容器啟動後執行的程式,這裡指定 bash (UNIX 的一種 shell),所以可以看到如上圖所示,進入了一個提示字元為 [root@27b5c5977301 /] 的環境,27b5c5977301 是容器的序號。
  •  docker ps
在本機開啟另一個命令視窗,輸入如上指令,可以看到正在運行的容器,各欄位說明如下:
    • CONTAINER ID: 容器序號
    • IMAGE: 鏡像名稱
    • COMMAND: 啟動容器時執行的命令
    • CREATED: 容器創建的時間
    • STATUS: 容器運行的狀態
    • PORTS: 容器暴露的端埠號
    • NAMES: 容器的名稱,由 docker 自動產生,不喜歡這個名稱? 可以在 run 時加上 -name 來指定名稱。
docker ps 後面還可以帶參數,常用的如下:
    • -a : 列出所有容器 (包含運行中及已停止的)
    • -l : 列出最近創建的容器
    • -n : 列出 n 個最近創建的容器
    • -q : 僅列出 CONTAINER ID 欄位
    • -s : 在輸出的欄位中,增加 SIZE 欄位,用來顯示容器大小。
  •  docker attach 27b5c5977301
剛剛下 run 啟動容器後,如果離開了又想重新進入,就用 attach 指令,並以容器序號當參數。
  •  docker start 27b5c5977301
 容器關閉後要啟動就用 start,關閉用 stop,重新啟動用 restart,除了 stop 外,也可以用 kill 關閉容器,兩者差別在於 kill 是立即關閉,stop 則會略等一小段時間後關閉。
  •  docker rm 27b5c5977301
刪除容器用 rm,運行中的容器無法直接刪除,可以加上 -f 強制刪除。
  •  docker rmi -f docker.io/centos
rmi 指令用在刪除鏡像,加上 -f 也是強制刪除。上面的參數用鏡像名稱,也可以使用鏡像序號。
  • docker export 容器序號(或容器名稱) > xxx.tar
  • docker import xxx.tar 容器名稱/centeos:latest
前面提供使用 save、load 儲存鏡像和導入鏡像,如果要儲存容器及導入容器則是用上面這兩個指令。差別在於,儲存容器是指儲存正在運行的容器的當時狀態,這會包含容器已運行的一些歷史紀錄,所以檔案會比較大。