--- title: 'Docker 安裝、映像檔使用' disqus: kyleAlien --- Docker 安裝、映像檔使用 === ## OverView of Content 如有引用參考請詳註出處,感謝 :cat: [TOC] ## Docker 概述 ### Docker vs. 虛擬機 | 特性 | 容器 | 虛擬機 | | -------- | -------- | -------- | | 啟動速度 | 秒 | 分鐘 | | 性能 | 接近原生 | 較弱 | | 記憶體花費 | 少 | 多 | | 硬碟耗費 | MB | GB | | 運行數量 | 單個 PC 就可以運作上千個 | 單個 PC 大概幾十個 | | 隔離姓 | 安全隔離 | 完全隔離 | | 遷移性 | 佳 | 一般 | * Docker 與虛擬機的一大差異就是 **Docker 不需要 VMM (Virtual Machine Manager)、Hypervisor 支援**,Docker 是作業系統內核層級的虛擬化,**性能更高** ### Docker 虛擬化 * 虛擬化是一種資源管理技術,會將硬體的特性隔離出來,並透過抽象、Adapter 來完成實作的呼叫 (打破硬體差異的屏障) * 虛擬化有兩個大方向 1. 硬體虛擬化 2. 軟體虛擬化 (Docker),在軟體虛擬化的範疇中又有在細分為 | 虛擬化策略 | 說明 | 舉例 | | - | - | - | | 完全虛擬化 | 虛擬機完整模擬底層硬體環境、特權指令,使用者作業系統無須進行修改 | IBM p 和 z 系列虛擬化、VMware、Workstation、VirtualBox、QEMU | | 硬體補助虛擬化 | 利用硬體 (主要是 CPU) 支援控制敏感指令,來實現完全虛擬化,**使用者也不需要修改** | VMware Workstation、Xen、KVM | | 部分虛擬化 | 只針對部分硬體資源進行虛擬化,**使用者作業系統需要修改** | | | 準虛擬化 | 部分硬體介面以軟體的方式提供給客戶作業系統,**使用者作業系統需要修改** | 早起 Xen | | 作業系統虛擬化 | 核心透過建立多個虛擬的作業系統 (建立後會包含該系統所需的 Library),用來隔離不同的程序 | Docker、容器技術 | Docker 的虛擬化就是 **作業系統虛擬化** (透過核心建立,不需要 VMM、Hypervisor 效率更高) ## Docker 基礎 ### Docker 安裝 - Ubuntu * 這裡示範如何在 Ubuntu 安裝 Docker,但主要的安裝過程還是請參考 [**Docker 官方文檔**](https://docs.docker.com/engine/install/ubuntu/) 最準確 * **基礎工具、準備** ```shell= # 如果有舊的安裝,請先移除 sudo apt-get remove docker docker-engine docker.io containerd runc ``` >  1. 透過 apt 安裝必要 library ```shell= sudo apt-get update sudo apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release ``` 2. 下載 && 設定 GPG Key ```shell= curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg ``` 3. 設定 stable repository (這樣才能安裝 Docker 引擎) ```shell= echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null ``` * **安裝 Docker Engine** ```shell= sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin ``` :::danger * **Window 子系統 Ubuntu `Network Unreachable`** ? Window cmd 中關閉 wsl,重新啟動 ```shell= wsl --shutdown ``` ::: * **在 Ubuntu 中啟動 Docker 服務** 1. 首先將 Docker 加入自身群組,並重新登入 ```shell= # 查看自身 whoami # sudo usermode -aG docker <自身> sudo usermode -aG docker alien # 檢查群組 cat /etc/group | grep docker ``` 2. 啟動 docker 服務 ```shell= service docker status sudo service docker start ``` >  :::info * 查看 系統所有服務 ```shell= ls -laF /etc/init.d ``` >  ::: ### Docker 測試 hello-world * **測試 Docker 運行是否正常** 1. Docker version ```shell= docker version ``` >  2. 嘗試跑 docker run hello-world ```shell= docker run hello-world ``` >  :::warning * **Window WSL 子系統 Ubuntu 安裝 Docker,無法 run Docker 容器 !?** > docker: Error response from daemon: OCI runtime create failed: container_linux.go:346: starting container process caused "process_linux.go:319: getting the final child's pid from pipe caused \"EOF\"": unknown. > ERRO[0012] error waiting for container: context cancele 最好的方法是升級 Window 的 WSL 版本到 2,[**參考**](https://www.omgubuntu.co.uk/how-to-install-wsl2-on-windows-10) ::: * **Docker 運作 Log** ```shell= tail /var/log/docker.logtail /var/log/docker.log ``` >  ### Docker 核心概念 * Docker 大部分操作都圍繞著**三個核心** 1. **Docker 映像檔** Docker 映像 (Image) 類似於虛擬機,可以理解為一個 **唯讀 (read only) 模板**,一個映像檔可以包含一個基礎作業環境 + 一個應用程式 > Apache 映像檔 = 基礎作業系統 + Apache 2. **Docker 容器** 容器就是一個沙箱 (看不見彼此),用來 **運行、隔離** 不同應用,容器也是 Docker 運行映像檔後的實體 (Instance) :::info * 映像檔本身是唯獨,容器從映像檔啟動後,Docker 會在映像檔的上層建立一個可寫入層 ::: 3. **Docker 倉庫** Docker 有提供一個 映像檔 Hub,裡面有很多映像檔;可以依據需求下載區要的映像檔 ## 映像檔操作 以下來學習使用指令操作映像檔 ### 下載 Docker 映像檔 * 下載映像檔關鍵指令 | 指令關鍵 | 說明 | 其他 | | -------- | -------- | -------- | | docker search <關鍵字\> | 透過關鍵字,搜尋到倉庫中相關映像檔 | 可以指定搜尋倉庫 | | docker pull NAME[:TAG] | 下載映像檔 | 如果沒有設定 tag 就會使用最新的映像檔 | | docker images | 查看本地已經有的應向檔 | 同 image list | | docker tag <NAME\> <TAG\> | 為已有的映象檔創建添加一個 TAG 標籤 | 但仍相同 image id | | docker inspect <映像檔\> | 檢查映像檔資訊 | | | docker history <映像檔\> | 檢查映像檔的建立紀錄 | 應該是該 image 的 commit 紀錄 | | docker rmi <映像檔 or id\> | 刪除映像檔 | 有另外一個很像的 `docker rm` 是拿來移除容器 | ```shell= # 搜尋 ubuntu docker search ubuntu # 下載最新 ubuntu docker pull ubuntu # 透過 tag 下載指定版本 ubuntu docker pull ubuntu:14.04 ``` >  * 可以透過指定 Registry url 來選定要搜索、pull 的倉庫,假設我要搜尋 Google 的 Registry (請先安裝 [**Google gcloud**](https://cloud.google.com/sdk/docs/install#deb)) ```shell= docker pull gcr.io/google-samples/hello-app:1.0 docker images ``` >  * 對已有的 image 檔創建自己的 TAG (觀察一下,兩者是有相同的 IMAGE ID) ```shell= # 給 'python:latest 添加 py tag' docker tag python:latest py docker images ``` >  ### 建立 Docker 映像檔 | 指令關鍵 | 說明 | 其他 | | -------- | -------- | -------- | | docker commit | 依據已有的容器創建 | 可以記錄你對 container 的操作紀錄,方便以後重複使用 | | docker import | 透過下載、現有檔案創建 | | * 建立映像檔的方法有三種 1. 基於 **==現有映像檔產生的 ++容器++==** 建立:使用 **commit** 指令對現有的 container 建立 :::info * 格式:`docker commit [OPTIONS] <Container id | name> [Repository[:TAG]]` ::: 使用 commit 指令 (有點類似 git commit),對現有 container 進行提交,**提交後 container 就會產生新 sha id** > Respository 取名必須小寫 > >  ```shell= # 查看所有 container docker ps -a # 透過 指定 container id e35 來提交 docker commit -m "First commit for container by id" -a "alien" e35 alien_image:0.1 # 透過 指定 container name determined_hellman 來提交 docker commit -m "First commit for container by name" -a "alien" determined_hellman alien:0.2 ``` >  2. 基於 Linux 容器 (LXC) 範例匯入:使用 **import** 指令,直接從一個作業系統範本匯入一個映像檔 :::info * 格式:docker import [OPTIONS] <Url | file | -\>-[Repository[:TAG]] ::: 這裡示範下載 [**ubuntu**](http://cdimage.ubuntu.com/ubuntu-base/releases/22.04/release/) ```shell= # import by url docker import http://cdimage.ubuntu.com/ubuntu-base/releases/22.04/release/ubuntu-base-22.04-base-amd64.tar.gz ubuntu_import:22.04 ``` >  ```shell= # 先下載到 download 資料夾 wget -P download/ http://cdimage.ubuntu.com/ubuntu-base/releases/22.04/release/ubuntu-base-22.04-base-amd64.tar.gz # import by file cat download/ubuntu-base-22.04-base-amd64.tar.gz | docker import - ubuntu_image_2:22.04 ``` >  3. 基於 Darkfile 建立 (這先跳過,以後再說) ### 儲存 or 載入 印象檔 | 指令關鍵 | 說明 | 其他 | | -------- | -------- | -------- | | docker save -o | 儲存現有 image | - | | docker load -input | 加載本地 image | - | 1. save:儲存 hello-world image 到 `~/images`,壓縮成 `hello-world.tar` ```shell= mkdir images docker save -o ~/images/hello-world.tar hello-world ``` >  2. load:加載本地 tar ```shell= docker load --input ~/images/hello-world.tar ``` >  ## 容器操作 有點類似虛擬機的創建,但是 Docker 所創建的容器需要的資源很少、創建速度快 * Container 的創建基於 Image,所以要先確保有 Image 再創建 ```shell= docker images ``` >  ### 創建運行 Container | 指令關鍵 | 說明 | 其他 | | -------- | -------- | -------- | | docker create | 依據 image 創建 Container | 創建出的 Container 狀態是 **==Created== (尚未運行),可透過 start 指令運行 container** | | docker start | 運行特定 container | 透過 id 指定 container,**啟動後狀態為 ==UP==** | | docker run | 創建 + 運行 container,可以看做 create + start 指令的結合 | 如果沒有 image 也會從倉庫自動下載 | 1. create:依照 `ubuntu:22.04` 映像檔創建 Container ```shell= # docker create [OPTIONS] IMAGE [COMMAND] [ARG...] # 創建 container docker create -it ubuntu:22.04 # 查看所有 container docker ps -a ``` >  由於 create 指令的 option 相當多,這裡不會都提及 (有用到才會說明),以需要可以透過 `docker create --help` 查詢 2. start:運行指定 container ```shell= # 查看所有 container docker ps -a # 啟動 id 38 (id 不用全部輸入) 的 container docker start 38 docker ps -s ``` >  3. run:建立 & 運行 container ```shell= # 依照 ubuntu:20.04 image 創建 container # 並運行 bin/echo 'Hello World' docker run ubuntu:20.04 /bin/echo 'Hello World' ``` >  docker run 常見的 OPTION 指令,完整請查看 `docker run --help` | Run's OPTIONS | 說明 | 其他 | | -------- | -------- | -------- | | -d | 背景運行 | 可透過 `docker attach <container id>` 進入前景 (id 透過 pa -a 查詢) | | -i | 可以使用者戶交 (可輸入指令) | - | | -t | 分配一個虛擬終端機 (pseudo-tty) | - | ```shell= # 啟動 run docker run -it -d ubuntu:20.04 docker ps -s docker attach acb ``` >  ### 停止、重啟 Container | 指令關鍵 | 說明 | 其他 | | -------- | -------- | -------- | | docker kill <id\> | 直接關閉容器 | 暴力 | | docker stop <id\> | 會對容器發送 SIGTERM 信號,約略 10s 後發送 SIGKILL 信號 | | | docker restart | 重新啟動容器 | | ```shell= # 先查看有哪些容器 docker ps -a # 啟動指定 容器 (ac 是 id) docker start ac # 查看正在運行的容器 docker ps -s ``` >  ### 進入已運行 Container | 指令關鍵 | 說明 | 其他 | | -------- | -------- | -------- | | docker attach <id\> | 將 Container 回到前景 | 當多個視窗訪問同一個容器時,所有視窗都會一起顯示 | | docker exec [OPTIONS] <id\> <COMMAND\> | 在已經啟動的容器中,執行任意命令 | 就像是對該容器重新創建了一個 tty 終端機 | :::warning 這兩個命令只能用在已啟動的部分 ::: * attach:將已啟動的 container 回到前景時,若有多個終端機訪問同一個 Container 則會 **++同步++ 顯示** >  * exec:執行一個新的命令,兩個不同視窗的命令不會相互影響 ```shell= # 啟動兩個視窗 # 以下的「ac」是 container id 的簡稱 docker exec -it ac /bin/bash ``` ### 刪除 Container | 指令關鍵 | 說明 | 其他 | | -------- | -------- | -------- | | docker rm <id\> | 移除容器 | 當容器正在運行中則無法刪除 (可用 -f) | ```java= # 查看當前有的容器 docker ps -a # 移除 id 為 33 的容器 docker rm 33 # 再次檢查容器是否已被刪除 docker ps -a ``` >  :::warning * 當容器正在運行時,則無法刪除,可以使用 `-f` 來強制關閉 (但不太好) >  ::: ### 匯出、匯入容器 | 指令關鍵 | 說明 | 其他 | | -------- | -------- | -------- | | export -o <輸出檔案> <id\>| 將容器輸出到本地 | 提醒:映像檔是 save `-o` | | import file \| Url - [Respository[:TAG]] | 用法同 **IMAGE 匯入** | 也就是匯入 image,container 要手動啟動 | 1. 輸出指定 container ```shell= # 創建一個 container 資料夾 mkdir -p container # 輸出 container 到 ~/container 資料夾中 docker export -o ~/container/myContainer.tar e3 ``` >  2. 輸入指定 tar 檔案,再查看 image 檔 ```shell= cat ~/container/myContainer.tar | docker import - my_container:0.3 # 查看 images docker images ``` >  ## Appendix & FAQ :::info ::: ###### tags: `Docker`
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.