1.docker介紹
1.1什麼是docker
Docker 是一個開源的應用容器引擎,基於 Go 語言 並遵從Apache2.0協議開源。
Docker 可以讓開發者打包他們的應用以及依賴包到一個輕量級、可移植的容器中,然後發佈到任何流行的 Linux 機器上。
1.2.docker底層原理介紹
Namespaces
命名空間(namespaces)是 Linux 爲我們提供的用於分離進程樹、網絡接口、掛載點以及進程間通信等資源的方法。在日常使用 Linux 或者 macOS 時,我們並沒有運行多個完全分離的服務器的需要,但是如果我們在服務器上啓動了多個服務,這些服務其實會相互影響的,每一個服務都能看到其他服務的進程,也可以訪問宿主機器上的任意文件,這是很多時候我們都不願意看到的,我們更希望運行在同一臺機器上的不同服務能做到完全隔離,就像運行在多臺不同的機器上一樣。
進程
進程是 Linux 以及現在操作系統中非常重要的概念,它表示一個正在執行的程序,也是在現代分時系統中的一個任務單元。在每一個 *nix 的操作系統上,我們都能夠通過 ps 命令打印出當前操作系統中正在執行的進程,比如
網絡
如果 Docker 的容器通過 Linux 的命名空間完成了與宿主機進程的網絡隔離,但是卻有沒有辦法通過宿主機的網絡與整個互聯網相連,就會產生很多限制,所以 Docker 雖然可以通過命名空間創建一個隔離的網絡環境,但是 Docker 中的服務仍然需要與外界相連才能發揮作用。
每一個使用 docker run 啓動的容器其實都具有單獨的網絡命名空間,Docker 爲我們提供了四種不同的網絡模式,Host、Container、None 和 Bridge 模式。
掛載點
雖然我們已經通過 Linux 的命名空間解決了進程和網絡隔離的問題,在 Docker 進程中我們已經沒有辦法訪問宿主機器上的其他進程並且限制了網絡的訪問,但是 Docker 容器中的進程仍然能夠訪問或者修改宿主機器上的其他目錄,這是我們不希望看到的。
在新的進程中創建隔離的掛載點命名空間需要在 clone 函數中傳入 CLONE_NEWNS,這樣子進程就能得到父進程掛載點的拷貝,如果不傳入這個參數子進程對文件系統的讀寫都會同步回父進程以及整個主機的文件系統。
1.3.Docker VS VM
Docker與虛擬機(虛擬機)的區別可以看:
左圖是虛擬機的工作原理圖,對資源進行抽象,着重體現在硬件層面的虛擬化上,這種方式增加了兩場調用鏈,對性能的損耗比較大,而且還會佔用大量的內存資源
有圖是Docker的工作原理圖,屬於OS級別的虛擬化,kernel通過創建多個鏡像來隔離不同的app進程,由於kernel是是共享,而且本身linux image也不大,性能損耗幾乎可以不計,而且內存佔用也不大,大大節約了設備成本。
Docker架構總覽
最核心的是 Docker Daemon我們稱之爲Docker守護進程,也就是Server端,Server端可以部署在遠程,也可以部署在本地,因爲Server端與客戶端(Docker Client)是通過Rest API進行通信。
docker CLI 實現容器和鏡像的管理,爲用戶提供統一的操作界面,這個 客戶端提供一個只讀的鏡像,然後通過鏡像可以創建一個或者多個容器(container),這些容器可以只是一個RFS(Root File System),也可以是一個包含了用戶應用的RFS。容器在docker Client中只是一個進程,兩個進程是互不可見的。
用戶不能與server直接交互,但可以通過與容器這個橋樑來交互,由於是操作系統級別的虛擬技術,中間的損耗幾乎可以不計
1.4.Image & Container
在docker中,我們重點關注的就是鏡像和容器了。因爲在實際應用中,我們封裝好鏡像,然後通過鏡像來創建容器,在容器運行我們的應用就好了。而server端掌控網絡和磁盤,我們不用去關心,啓動docker sever 和 docker client都是一條命令的事情。後面會詳細講docker的啓動過程。
Image: 一個只讀的鏡像模板。可以自己創建一個鏡像也可以從網站上下載鏡像供自己使用。鏡像包含了一個RFS.一個鏡像可以創建很多容器。
Container:由docker client通過鏡像創建的實例,用戶在容器中運行應用,一旦創建後就可以看做是一個簡單的RFS,每個應用運行在隔離的容器中,享用獨自的權限,用戶,網絡。確保安全與互相干擾
兩者在創建後,都是一堆layer的統一視角,唯一的卻別是鏡像最上面那一層是隻讀的,不可以修改,但是容器最上面一層是rw的,提供給用戶操作
repository:倉庫,這個東西沒有單獨介紹不是因爲它不重要,而是因爲之前做個比較多的Android源碼編譯,所以這裏就沒有仔細往下看,大概就是一個鏡像庫,最大的是docker hub,類似於google 的aosp,當然也可以本地搭,比如mig事業羣就有自己的repo。
1.5.Docentos安裝dokcer
# 安裝依賴包
sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
# 配置docker倉庫源
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# 安裝 docker
sudo yum install docker-ce docker-ce-cli containerd.io
# 啓動
docker sudo systemctl start docker
1.6.Docker常用命令
獲取鏡像
從倉庫獲取所需要的鏡像。
使用示例:
sudo docker pull tomcat:8.5
8.5: Pulling from library/tomcat
741437d97401: Pull complete
34d8874714d7: Pull complete
0a108aa26679: Pull complete
eea0f08c7492: Pull complete
ca74b3d90c15: Pull complete
f11a643c4a85: Pull complete
05eafed73b65: Pull complete
f24105f282aa: Pull complete
e27e73cbbd3f: Pull complete
801f808615c2: Pull complete
294f3735a5f6: Pull complete
Digest: sha256:2af4741120ac4b2e1993412e34b73565d1b859d8a44b1b5f0e1963d97cc921a1
Status: Downloaded newer image for tomcat:8.5
實際上相當於 docker pull registry.hub.docker.com/tomcat:8.5
命令,即從註冊服務器 registry.hub.docker.com 中的 tomcat倉庫來下載標記爲 8.5 版本的鏡像。
查看鏡像列表
sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat 8.5 168588387c68 2 weeks ago 463MB
hello-world latest fce289e99eb9 8 weeks ago 1.84kB
利用 Dockerfile 來創建鏡像
docker build
首先需要創建一個 Dockerfile
Dockerfile 中每一條指令都創建鏡像的一層,例如:
FROM tomcat:8.5
MAINTAINER test <[email protected]>
# move all configuration files into container
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
EXPOSE 8080
CMD ["catalina.sh", "run"]
Dockerfile 基本的語法是
- 使用#來註釋
- FROM 指令告訴 Docker 使用哪個鏡像作爲基礎
- 接着是維護者的信息
- RUN開頭的指令會在創建中運行,比如設置時區
更詳細的語法說明請參考 Dockerfile
編寫完成 Dockerfile 後可以使用 docker build 來生成鏡像。
sudo docker build -t yininfo/tomcat:8.5 .
Sending build context to Docker daemon 8.192kB
Step 1/6 : FROM tomcat:8.5
---> 168588387c68
Step 2/6 : MAINTAINER test <[email protected]>
---> Running in 3c123152dbb6
Removing intermediate container 3c123152dbb6
---> 1a4b1faa7d12
Step 3/6 : RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
---> Running in c47fd4b7e2d5
Removing intermediate container c47fd4b7e2d5
---> 54740c484571
Step 4/6 : RUN echo 'Asia/Shanghai' >/etc/timezone
---> Running in c14929176831
Removing intermediate container c14929176831
---> 106387d57685
Step 5/6 : EXPOSE 8080
---> Running in 10b1ff94dd17
Removing intermediate container 10b1ff94dd17
---> 02ca9a046384
Step 6/6 : CMD ["catalina.sh", "run"]
---> Running in 6fce494276e5
Removing intermediate container 6fce494276e5
---> 788874a002c0
Successfully built 788874a002c0
Successfully tagged yininfo/tomcat:8.5
其中 -t 標記來添加 tag,指定新的鏡像的用戶信息。 “.” 是 Dockerfile 所在的路徑(當前目錄),
也可以替換爲一個具體的 Dockerfile 的路徑。注意一個鏡像不能超過 127 層。
用docker images 查看鏡像列表
sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
yininfo/tomcat 8.5 788874a002c0 33 seconds ago 463MB
tomcat 8.5 168588387c68 2 weeks ago 463MB
hello-world latest fce289e99eb9 8 weeks ago 1.84kB
上傳鏡像
docker push
用戶可以通過 docker push 命令,把自己創建的鏡像上傳到倉庫中來共享。例如,用戶在 Docker Hub 上完成註冊後,可以推送自己的鏡像到倉庫中。
運行實例:
$ docker push yininfo/tomcat:8.5
創建容器
docker create <image-id>
docker create 命令爲指定的鏡像(image)添加了一個可讀寫層,構成了一個新的容器。注意,這個容器並沒有運行。
docker create 命令提供了許多參數選項可以指定名字,硬件資源,網絡配置等等。
運行示例:
創建一個centos的容器,可以使用倉庫+標籤的名字確定image,也可以使用image-id指定image。返回容器id
#查看本地images列表
docker images
#用倉庫+標籤
sudo docker create -it --name tomcat-8080 -p 8080:8080 yininfo/tomcat:8.5
6a006f9837f32c459d7b6945f367a7ab3896d6e238dadb4d9a0878a7a5d1b957
#可以使用 docker ps查看一件存在的容器列表,不加參數默認只顯示當前運行的容器
$ docker ps -a
可以使用 -v 參數將本地目錄掛載到容器中。
$ docker create -it --name tomcat-8080 -v /src/webapp:/opt/webapp yininfo/tomcat:8.5
這個功能在進行測試的時候十分方便,比如用戶可以放置一些程序到本地目錄中,來查看容器是否正常工作。本地目錄的路徑必須是絕對路徑,如果目錄不存在 Docker 會自動爲你創建它。
啓動容器
docker start <container-id>
Docker start命令爲容器文件系統創建了一個進程隔離空間。注意,每一個容器只能夠有一個進程隔離空間。
運行實例:
#通過名字啓動
sudo docker start -i tomcat-8080
#通過容器ID啓動
sudo docker start -i 6a006f9837f3
進入容器
docker exec <container-id>
在當前容器中執行新命令,如果增加 -it參數運行bash 就和登錄到容器效果一樣的。
sudo docker exec -it tomcat-8080 /bin/bash
停止容器
docker stop <container-id>
刪除容器
docker rm <container-id>
運行容器
docker run <image-id>
docker run就是docker create和docker start兩個命令的組合,支持參數也是一致的,如果指定容器
名字是,容器已經存在會報錯,可以增加 --rm 參數實現容器退出時自動刪除。
運行示例:
docker create -it --rm --name tomcat-8080 yininfo/tomcat:8.5
查看容器列表
docker ps
docker ps 命令會列出所有運行中的容器。這隱藏了非運行態容器的存在,如果想要找出這些容器,增加 -a 參數。
刪除鏡像
docker rmi <image-id>
刪除構成鏡像的一個只讀層。你只能夠使用docker rmi來移除最頂層(top level layer)
(也可以說是鏡像),你也可以使用-f參數來強制刪除中間的只讀層。
commit容器
docker commit <container-id>
將容器的可讀寫層轉換爲一個只讀層,這樣就把一個容器轉換成了不可變的鏡像。
鏡像保存
docker save <image-id>
創建一個鏡像的壓縮文件,這個文件能夠在另外一個主機的Docker上使用。和export命令不同,這個命令
爲每一個層都保存了它們的元數據。這個命令只能對鏡像生效。
使用示例:
#保存centos鏡像到centos_images.tar 文件
docker save -o yinfino-tomcat-8.5.tar yininfo/tomcat:8.5
容器導出
docker export <container-id>
創建一個tar文件,並且移除了元數據和不必要的層,將多個層整合成了一個層,只保存了當前統一視角看到
的內容。expoxt後的容器再import到Docker中,只有一個容器當前狀態的鏡像;而save後的鏡像則不同,
它能夠看到這個鏡像的歷史鏡像。
inspect
docker inspect <container-id> or <image-id>
docker inspect命令會提取出容器或者鏡像最頂層的元數據