Try   HackMD
tags: docker

[Study note][1] Docker note

避免環境衝突和程式的相依性,所以需要透過 docker 來產生專屬的 container

安裝教學

以下安裝步驟環境為透過 VirtualBox 上已經安裝好的 Ubuntu 18.04 來執行 Docker

參考資料

  • 安裝 Docker
$ sudo apt-get install docker.io
  • 確認 Docker 版本
$ docker version`

  • 將自己的使用者帳號加入至 Docker 群組:
$ sudo usermod -aG docker $(USER_NAME)

  • 啟動 Docker 服務
$ sudo docker service docker start

!! 完成後登出再重新登入

Create Dockerfile to build image

參考資料

  • 建立測試資料夾
$ mkdir $(FOLDER_NAME)
  • 進入測試資料夾
$ cd $(FOLDER_NAME)
  • 建立 Dockerfile(打包 image 的指令檔)
$ vim Dockerfile
  • 在 Dockerfile 中依序列下環境需要的更新和安裝 (image 剛建立時, 就像剛裝好的 OS 一樣),在打包 image 時會自動將這些步驟加入打包過程中

  • 建立 docker image (如遇到權限問題請再前面加上 sudo)

   $ docker build -t $(IMAGE_NAME) . --no-cache


.
.
.

執行 image 到 container 中

參考資料

  • 檢查目前有什麼 image
$ docker images

  • 下載 docker server 上的 image (i.e. ubuntu 16.04)
$ docker pull ubuntu:16.04
  • 透過 run 命令執行 image 到 container 中
$ docker run -it $(IMAGE_NAME)


可以看到 user name 已經從原本的使用者 prince 變成 root, 表示我們已經切換到 container 中了

  • 如何檢查 container 掛載的 volume 在 host OS 上的實際位置
    由於我們在 Dockerfile 中有寫到 volume 的設定, 所以在開啟 image 到 container 中時已經從 host OS 中自動掛載一個目錄到 container 下, 要透過下列步驟來取得實際路徑

    • 取得 container ID

      ​​​​$ docker ps -a
      

    • 透過 container ID 來取得掛載到 host OS 中的實際位置

      ​​​​$ docker inspect -f '{{.Mounts}}' $(CONTAINER_ID)
      


      實際存取該位置時需要切換到 root 權限

  • 在 container 中測試編譯

    • 把程式和 makefile 複製到 host OS 中對應到 volume 的位置
    • 測試編譯
  • 如果 container 停止了,可以透過下面命令重新執行,如果執行 run 重新啟動,其實是重新開啟一個 container 和重新掛載一個新 volume 位置

    • 重新啟動 container
      ​​​​$ docker start $(CONTAINER_NAME)`
      
    • 執行 container
      ​​​​$ docker exec -it $(CONTAINER_NAME) /bin/bash
      

Docker 相關指令

顯示目前所有 container 狀況

$ docker container ls -a

刪除指定 container

$ docker container rm $(CONTAINER_NAME)

檢查所有 image

$ docker images

刪除指定的 image

$ docker rmi $(IMAGE_ID)

實用小功能

當做好 Docker image 後發現有些操作 Dockerfile 漏掉了,該怎麼辦?

  • 請參考:How To Commit Changes To A Docker Image With Examples

  • 在 container 中將想要的修改完成

  • 退出 container

    ​​​​$ exit
    
  • 取得想要修改的 container 資訊

    ​​​​$ sudo docker ps -a
    

  • 透過指令來提交想要的 image(如果名稱相同將會覆蓋原來的 image)

    ​​​​$ sudo docker commit [CONTAINER_ID] [new_image_name]
    

  • 檢查 image 清單,發現 image 已經變更成功

  • 雖然已經完成 image 更新,但要記得再把需要更動的部分同步到Dockerfile 中,這樣需要透過 Dockerfile 打包新的 image 時才不會出現沒同步到的問題

如何匯出已經在使用的 image

參考資料:docker docs - docker save

  • 列出目前的 image
    ​​​​$ docker images
    
  • 將選擇的 image 打包成 gz 檔
    ​​​​$ docker save $(IMAGE_NAME) | gzip > $(NEW_IMAGE_NAME).tar.gz
    

如何匯入打包好的 image

參考資料:
[Docker] 比較 save, export 對於映象檔操作差異

Lsmod and modprobe not found

  • 複製打包好的 image 到 client 上

  • 透過下列命令把打包好的 image 匯入 client docker 上

    ​​​​$ docker load < $(NEW_IMAGE_NAME)
    
  • 匯入的 image 如果需要執行像 modprobe 的命令,請在啟動 container 時加上 --privileged 命令
    ex.

    ​​​​$ docker run -it --privileged $(IMAGE_NAME)
    ​​​​$ docker exec -it --privileged $(IMAGE_NAME) /bin/bash
    
  • 當 export image 的 OS 和 import image 的 OS 差異過大時,建議先將落後的版本升級上來

    查詢發行版本 $ cat /etc/*release , 查詢核心版本 $ uname -r

    • 以我在工作的環境中
      export OS : Ubuntu 18.04 (Kernel:5.3.0-62-generic)
      import OS : CentOS 7.8.2003 (Kernel 3.10.0-1227)
      由於版本差距過大,所以需要把 CentOS Kernel 升級到 v5.7,升級教學可以參考

如何備份正在使用中的 container 成為新的 images

參考資料:
Docker 容器備份及還原
docker docs - docker commit

$ docker commit -p $(CONTAINER_NAMES) $(TARGET_IMAGE_NAME)

參考資料:
1. 用30天來介紹和使用 Docker

2. 圖解Docker教學-前端學習Docker的4大原因 feat. 六角學院 |入門|程式|科技|開發