# Docker入門 ###### tags: `Container` `Docker` ## 簡介 Docker用比較熟知的東西來介紹的話,就是傳統虛擬機(VMware之類的)的概念。 跟傳統虛擬機的具體差別在於: 1. 虛擬機會基於原有的OS再安裝一個Guest OS,並且共同使用本機的硬體資源,所以使用會占用很多資源。 2. Docker是直接在原有的OS上形成一個「容器Container」,並將需要模擬的東西全都放在這裡面執行,不需要多加一個Guest OS吃硬體資源。 基於以上,同樣的裝置可能只跑10個虛擬機就會卡到往生,但可以跑數百甚至數千個Docker。 ### Docker特點 1. 部署容易: 可以建立一個固定的映像檔重複使用,統一Docker Container中的內容,實現「標準化」。 2. 兼容性高: Docker可以在各式各樣的平台上執行,所以很容易遷移到不同端點→可以在這邊開發,最後實用在那邊。 ### Docker vs. Virtual Machine | 特性 | Docker | Virtual Machine | | -------- | -------- | -------- | | 啟動時間 | 秒級 | 分鐘級 | | 佔用空間 | MB | GB | | 效能 | 接近原生 | 弱於原生 | | 驅動數量 | 數千 | 數十 | | 隔離級別 | 系統級 | 進程級 | ## Docker的組成 1. 映像檔(Image) 2. 容器(Container) 3. 倉庫(Repository) > **倉庫註冊伺服器**中有若干**倉庫**,倉庫中又有若干**映像檔**。 > (Registry包著Repository然後包著Image) ### 映像檔 Image * 用來**建立容器** * 如同虛擬機要灌作業系統的iso檔 > 註:映像檔是<font color = "red">唯讀</font>的。 ### 容器 Container * 如同灌在虛擬機的**作業系統**的用途 * 彼此間**完全隔離,不互相干擾** ### 倉庫 Repository * 存放映像檔的地方 * 分為<font color = "green">公有Public</font>跟<font color = "green">私有Private</font> * 概念與Github相似,都是用push上傳、pull下載 * 最大的公有倉庫是[Docker Hub](https://hub.docker.com/) ## 映像檔 Image 映像檔是建立容器的必要條件。 需要用到的映像檔必須存在本機上;如果在本機端找不到,會從Repository中找尋並下載(預設是Docker Hub)。 ### 取得映像檔 `docker pull 註冊伺服器位址/倉庫名稱:TAG` 若無特別指定註冊伺服器位址,則預設是從Docker Hub抓取映像檔。 ### 列出已有映像檔 `docker images`可以列出本機現有的映像檔。  * REPOSITORY:倉庫名稱 * TAG:該映像檔的標籤 * IMAGE ID:該映像檔的ID(唯一) * CREATED:下載映像檔的時間 * VIRTUAL SIZE:映像檔的大小 > 註:映像檔的ID是唯一的,如果看到重複的ID表示兩者是一樣的映像檔,彼此間以TAG區分。建立/下載映像檔時,若沒有特別寫明TAG,預設以lastest表示。 ### 修改映像檔 先啟動,然後對它作想修改的事情後,輸入`exit`退出。 > [color=#FF0000] 啟動後,會出現root@ID,要記住這個ID才可以在之後commit時順利更新,不然就要用`docker image`自己找了。 接著用`docker commit`更新。 舉例:`docker commit -m "說明文字" -a "使用者資訊" ID 倉庫名稱:TAG` > 前面有提到映像檔是<font color="red">唯讀</font>的,所以所謂的修改其實應該是指「增加功能」。 ### 建立映像檔 要建立一個映像檔必須先有Dockerfile,因為裡面有建立時所需要用到的指令。 ```bash mkdir 資料夾名稱 #先創立一個資料夾 cd 資料夾名稱 #進入創立的資料夾 touch Dockerfile #建立Dockerfile ``` Dockerfile中,每一行都是一個指令。 建立好Dockerfile後,用編輯器打開來增修內容(`vi Dockerfile`或`vim Dockerfile`等)。 舉例: ```dockerfile FROM 倉庫名稱:TAG #基底映像檔 MAINTAINER 維護者/開發者資訊 RUN apt-get -qq update #執行這個映像檔時要做的事情 RUN gem install sinatra ``` > 註:執行Dockerfile的期間,每一個指令都會建立一個容器,並做出對應的修改,等到全部執行完之後,會把過程中建立的容器清除。 好了之後用`docker build`建立映像檔。 舉例:`docker build -t="倉庫:TAG" 路徑` * -t:增加TAG * 路徑:用 .表示原本的路徑,也可以直接指定絕對路徑 ### 上傳映像檔 `docker push 倉庫名稱` 如此可以把指定倉庫的映像檔全都推上註冊伺服器。 ### 刪除映像檔 先用`docker rm`刪除依賴於欲刪除之映像檔的容器,再用`docker rmi 倉庫名稱`把本機端的指定倉庫刪除。 因為容器是基於映像檔建立的,所以有依賴性,不能直接刪掉映像檔。 ### 小結 從修改、更新、上傳映像檔的功能來看,可以理解為何docker的擴充性很好。 ## 容器 Container ### 啟動容器 `docker run -it ubuntu /bin/bash` * -英文字母:有的沒的功能 -i:交互式操作(互動模式,反正就是可以用終端下指令) -t:Docker分配一個虛擬終端至容器上 * ubuntu:映像檔名稱 * /bin/bash:命令。因為用-i需要有交互式Shell,因此用的是 /bin/bash 使用`docker run`的指令時,內部存在以下行為: 1. 檢查本地是否存在指定的映像檔,不存在就從公有倉庫下載 2. 利用映像檔建立並啟動一個容器 3. 分配一個檔案系統,並在唯讀的映像檔層外面掛載一層可讀寫層 4. 從宿主主機設定的網路橋界面中橋接一個虛擬埠到容器中去 5. 設定一個 ip 位址給容器執行使用者指定的應用程式 6. 執行完畢後容器被終止 (這一步也可以用`docker stop`自己來) 容器的核心為所執行的應用程式,所需要的資源都是應用程式執行所必需的。除此之外,並沒有其它的資源。可以在虛擬終端中利用 ps 或 top 來查看程式訊息。 ### 後台執行容器 有時候容器不需要在前台一直運作,只要在後台就可以了,這時候只要加入`-d`參數就能達到。 `docker run -d 倉庫:TAG` * -d:表示Daemonized(守護態),亦即在後台執行 如果需要查看相關資訊,可以用以下指令: * `docker ps`列出容器資訊,包含<font color="brown">ID、基於什麼映像檔而成、命令、創建時間、現在狀態、Port、名稱</font>等。 * `docker log`可以看後臺執行的容器的輸出。 ### 進入後台執行中的容器 有以下幾個方式: * 命令 1. `docker exec`用法相當於`docker run`,不過是針對容器 如`docker exec -it 容器名稱 bash`就是以bash方式跟指定容器溝通。 2. `docker attach`是直接進入容器 可以多個窗口同時叫出同一個容器,但每個窗口會同步 (有一個窗口死掉的話,其他的也會同時死掉) * 工具 - nsenter 具體使用方法[參考這裡](https://www.awaimai.com/737.html)。 ### 終止容器 `docker stop 容器ID`可以停掉整個容器。 如果是只包含一個終端機的容器的話,輸入`exit`或按`ctrl+D`也會終止。 一般而言,被終止的容器用`docker ps`是看不到相關資訊的,如果還想看的話必須加上參數`-a`。 想要啟動停止的容器的話,可以使用`docker start`。 想要重新啟動正在運作的容器的話,可以使用`docker restart`。 ### 匯出匯入 * 匯出 1. `docker export 容器ID > 指定檔名.附檔名` 這個指令會將<font color="red">容器**快照**</font>匯出,存成指定檔案。 > 快照:僅保存容器**當下**的狀態,不包含歷史訊息。 2. `docker save 指定檔名.附檔名 > 倉庫:TAG` 可以發現存的東西是映像檔的TAG,所以儲存最原始的、沒被改過的映像檔。 基本上這個對存容器沒什麼用,應該也不會用到...,畢竟映像檔可以直接從倉庫抓。 近年來幾乎不太用`save`跟`export`了,都直接用Dockerfile做。 * 匯入 1. 容器快照 `docker import 檔案 倉庫:TAG` 此指令會讓容器連著映像檔一起匯入。 2. 映像檔 `docker load 檔案` 單純匯入映像檔,跟上倉庫抓一模一樣。 ### 刪除容器 1. 刪除終止的容器 `docker rm` 2. 刪除執行中的容器 `docker rm -f` (-f是force的意思,Docker會發送`SIGKILL`信號給容器。) ## 倉庫 Repository 倉庫是存放映像檔的地方,容易混淆的概念是註冊伺服器。實際上註冊伺服器是管理倉庫的具體伺服器,每個伺服器上可以有多個倉庫,而每個倉庫下面有多個映像檔,所以可以將倉庫認為是一個具體的專案或目錄。 倉庫分為公有及私有,最大的公有倉庫是Docker Hub,基本上任何需求的映像檔都可以直接從上面抓取。 ### 登入Docker Hub `docker login 位址` 位址是選填的,可以不寫,預設為Docker Hub。 ### 搜尋公有倉庫中的映像檔 先登入公有倉庫後,輸入`docker search 作者/映像檔名稱` 作者為選填,可以不寫,就會列出所有對應名稱的映像檔;如果寫了作者就只會列出該作者的對應映像檔。 Docker Hub就像Github一樣,可以給星星,所以如果想要找「幾顆星以上」的映像檔的話,可以加入參數`-s N`,N為星星數量。 ### 建立私有倉庫 使用官方提供的docker-registry工具,建立私有的映像檔倉庫。 1. 安裝docker-registry工具 以Ubuntu為例: ```shell apt-get install -y build-essential python-dev libevent-dev python-pip liblzma-dev swig pip install docker-registry ``` 或是直接clone Github上的對應專案: ```shell apt-get install build-essential python-dev libevent-dev python-pip libssl-dev liblzma-dev libffi-dev git clone https://github.com/docker/docker-registry.git cd docker-registry python setup.py install ``` 直接clone的話要記得做[一些設定](https://philipzheng.gitbook.io/docker_practice/repository/config)。 2. 開始建立私有倉庫 `docker run -d -p 1234:5678 -v 路徑 --restart=always --name 指定倉庫名稱 registry` * 參數說明: * -d:在背景執行(=守護態模式)(非必要) * -p:主機的port mapping到容器的port(必須,數字自訂) * -v:指定私有倉庫的路徑(非必須,未指定則預設在容器的/tmp/registry下) * --restart:當Docker重新啟動或停止時,這個本地倉庫是否要重新啟動。 * --name:想要給這個私有倉庫的名稱。 ### 上傳映像檔至私有倉庫 1. 先使用`docker tag 欲推映像檔 私有倉庫位址:PORT/(USERNAME/)名稱:TAG`給欲上傳的映像檔標記。 2. 接著用`docker push 私有倉庫位址:PORT/(USERNAME/)名稱:TAG`,這樣就會把映像檔推到指定位址的私有倉庫上了。 3. 之後在別的機器上用`docker pull 私有倉庫位址:PORT/(USERNAME/)名稱:TAG`就可以把剛剛推上去的映像檔給拉下來。 > <font color="red">注意:推上倉庫的容器中的資料不會保存,只會存容器本身的設定(基底映像檔、有何app...),若要儲存執行中所經手的資料,就要用到別的工具,如**Volumes**。</font> ## 參考文件 1. [Docker Docs - Product Manual](https://docs.docker.com/engine/) 2. [Docker - 從入門到實踐](https://philipzheng.gitbook.io/docker_practice/) 3. [雲原生的基石,一文讀懂容器](https://blog.csdn.net/jdcdev_/article/details/105083933) 4. [全面易懂的Docker指令大全](https://joshhu.gitbooks.io/dockercommands/content/index.html) 5. [Docker教程](https://www.runoob.com/docker/docker-tutorial.html) 6. [比較save, export對於映象檔操作差異](https://blog.hinablue.me/docker-bi-jiao-save-export-dui-yu-ying-xiang-dang-cao-zuo-chai-yi/) 7. [用30天來介紹和使用 Docker](https://ithelp.ithome.com.tw/users/20103456/ironman/1320) 8. [Docker 基本教學 - 從無到有 Docker-Beginners-Guide](https://github.com/twtrubiks/docker-tutorial)
×
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
.