Docker從入門到放棄
轉載自簡書https://www.jianshu.com/p/46334b8e13bf,作者https://www.jianshu.com/u/94303315d3f7
內容目錄
- docker 是什麼
- docker 解決什麼問題
- 解決虛擬機器資源消耗問題。
- 快速部署。
- 提供一次性的環境。
- 提供彈性的雲服務。
- 組建微服務架構。
- docker 安裝部署與使用
- 安裝 docker 引擎
- 使用 docker
- 理解 docker 的架構
- docker 命令
- 卷的概念
- 自制映象併發布
- docker 網路
- docker pipework
- docker 網路埠對映
- 總結
docker 可能會改變軟體行業
1. docker 是什麼
大家都知道虛擬機器吧,windows 上裝個 linux 虛擬機器是大部分程式設計師的常用方案。公司生產環境大多也是虛擬機器,虛擬機器將物理硬體資源虛擬化,按需分配和使用,虛擬機器使用起來和真實作業系統一模一樣,當廢棄不用時直接刪除虛擬機器檔案即可回收資源,很方便集中管理。
由於虛擬機器非常龐大,同時對硬體資源的消耗也大,linux 發展出了另一種虛擬化技術,即 linux 容器(Linux Containers,縮寫為 LXC),它並不像虛擬機器那樣模擬一個完整的作業系統,卻提供虛擬機器一樣的效果。如果說虛擬機器是作業系統級別的隔離,那麼容器就是程序級別的隔離,可以想象這種級別隔離的優點,無疑是快速的,節省資源的。
docker 就是對 linux 容器的封裝,提供簡單實用的使用者介面,是目前最流行的 linux容器解決方案。
下面是百科的定義:
docker 是基於 Go 語言的開源的應用容器引擎,並遵從Apache2.0協議,docker 讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後釋出到任何流行的 linux 機器上,也可以實現虛擬化。容器是完全使用沙箱機制,相互之間不會有任何介面。
2. docker 解決什麼問題
1. 解決虛擬機器資源消耗問題。
伺服器作業系統之上執行著虛擬機器,虛擬機器上執行著客戶作業系統,客戶作業系統之上執行著使用者的應用程式,一臺伺服器 80% 的資源開銷都花費在了硬體虛擬化和客戶機作業系統本身。
圖1. 虛擬機器架構與容器架構區別
如圖 1 所示,如果採用 docker 容器技術,容器上執行著虛擬伺服器,虛擬伺服器中執行著使用者的應用程式,虛擬伺服器和伺服器作業系統使用同一核心,虛擬伺服器的檔案系統使用物理伺服器的檔案系統,但做了隔離,看上去每個虛擬伺服器都有自己獨立的檔案系統;在物理伺服器上建立了虛擬網橋裝置,每個虛擬伺服器通過虛擬網橋裝置連線網路。虛擬伺服器直接使用物理伺服器的CPU、記憶體、硬碟,並不對硬體進行虛擬化,因此沒有硬體虛擬化和客戶機作業系統佔用的資源消耗,每一臺虛擬伺服器的效能接近於物理伺服器效能。
一臺普通家用電腦執行一個 Linux 虛擬機器可能已經非常卡,但是卻可以使用 docker 虛擬出幾十甚至上百臺虛擬的 linux 伺服器。如果換成效能強勁的伺服器,使用 docker 就可以提供私有云服務了。
2. 快速部署。
軟體開發的難題在於環境配置,在自己電腦上執行的軟體,換一臺機器可能就無法執行,除非保證作業系統的設定正確,各種元件和庫的正確安裝。比如部署一個 Java 開發的 web 系統,計算機必須安裝 Java 和正確的環境變數,可能還需要安裝 tomcat、nginx。換臺機器部署就要重來一次。
使用 docker 可以將應用程式及依賴打包在一個檔案裡(docker 映象檔案),執行這個檔案就會啟動虛擬伺服器,在虛擬伺服器啟動應用程式或服務,就像在真實在物理機上執行一樣,有了 docker,就可以一次部署,處處執行,也可以用於自動化釋出。
3. 提供一次性的環境。
比如,本地測試他人的軟體、持續整合的時候提供單元測試和構建的環境,啟動或關閉一個虛擬伺服器就像啟動或關閉一個程序一樣簡單和快速。
4. 提供彈性的雲服務。
因為 Docker 容器可以隨開隨關,很適合動態擴容和縮容。
5. 組建微服務架構。
通過多個容器,一臺機器可以跑很多個虛擬伺服器,因此在一臺機器上就可以模擬出微服務架構,也可以模擬出分散式架構。
3. docker 安裝部署與使用
本文介紹 ubuntu 18.04 系統下的安裝與使用。其他作業系統請參考官方文件https://docs.docker.com/。
1. 安裝 docker 引擎
獲取最新版本的 Docker 安裝包
[email protected]:~$ wget -qO- https://get.docker.com/ | sh
執行上述命令,輸入當前使用者密碼,即可自動下載最新版的 docker 安裝包,並自動安裝。
安裝完成後有個提示:
If you would like to use Docker as a non-root user, you should now consider
adding your user to the "docker" group with something like:
sudo usermod -aG docker aaron
Remember that you will have to log out and back in for this to take effect!
WARNING: Adding a user to the "docker" group will grant the ability to run
containers which can be used to obtain root privileges on the
docker host.
Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
for more information.
當要以非 root 使用者可以直接執行 docker 時,需要執行
sudo usermod -aG docker aaron
命令將使用者 aaron 新增到 docker 使用者組中,然後重新登陸,否則會報下面的錯誤:
docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.38/containers/create: dial unix /var/run/docker.sock: connect: permission denied.
See 'docker run --help'.
執行下列命令啟動 docker 引擎
[email protected]:~$ sudo service docker start
安裝成功後已預設設定開機啟動並自動啟動,如果要手動設定,執行下面命令:
sudo systemctl enable docker
sudo systemctl start docker
測試執行
[email protected]:~$ sudo docker run hello-world
2. 使用 docker
1. 理解 docker 的架構
使用前先了解下 docker 的架構,如下圖所示:
docker 架構圖
docker 鏡象(image) 是存放在 docker 倉庫(Registry)的檔案,是用於建立 docker 容器 的模板。
docker 容器 是獨立執行的一個或一組應用,可以理解為前述介紹的虛擬伺服器。
docker 主機 是一個物理或者虛擬的機器用於執行 docker 守護程序和容器。
docker 客戶端 通過命令列或者其他工具使用 docker API 與 docker 的守護程序通訊。
作為使用者,我們直接使用的是 docker 客戶端。
2. docker 命令
檢視docker 命令的幫助資訊
docker --help #docker 全部命令幫助資訊
docker COMMAND --help #docker 具體命令COMMAND的幫助資訊
檢視docker 資訊
docker info
可以看到容器的池、已用資料大小、總資料大小,基本容器大小、當前執行容器數量等。
搜尋映象,從網路中搜索別人做好的容器映象。
docker search ubuntu
docker search centos
ubuntu 映象
從這裡可以看出有的映象已經集成了 php、java、ansible 等應用,我們也可以製作包含自己應用或服務的映象檔案,將此檔案傳給別人,別人即可直接使用 docker 開啟容器,不需要任何額外的操作,也不像虛擬機器那樣消耗資源,即可執行你的應用或服務,是不是非常方便?!
從網路中下載別人做好的容器映象。
docker pull centos
docker pull ubuntu
匯入下載好的容器映象檔案
docker load < image_xxx.tar
檢視映象
docker images
docker images -a
檢查映象
docker inspect ubuntu
可以看到容器映象的基本資訊。
刪除映象,通過映象的 id 來指定刪除
docker rmi ubuntu
刪除全部映象
docker rmi $(docker images -q)
顯示映象歷史
docker history ubuntu
執行容器
Docker容器可以理解為在沙盒中執行的程序,這個沙盒包含了該程序執行所必須的資源,包括檔案系統、系統類庫、shell 環境等。但這個沙盒預設是不會執行任何程式的,需要在沙盒中執行一個程序來啟動某一個容器。這個程序是該容器的唯一程序,所以當該程序結束的時候,容器也會完全停止。
執行 ubuntu 容器並進入互動式環境
[email protected]:~$ docker run -i --name="ubuntu1" --hostname="ubuntu1" ubuntu /bin/sh
cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 ubuntu1
whoami
root
uname -a
Linux ubuntu1 4.15.0-34-generic #37-Ubuntu SMP Mon Aug 27 15:21:48 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
上述命令我們建立了一個名字為 ubuntu1 的容器,設定容器的主機名為 ubuntu1,進入 /bin/sh 命令後我們列印了 hosts 檔案的內容,查看了核心版本(與本機作業系統版本一致),這裡可以使用各種 linux 命令,就像在新的作業系統中使用命令一個樣。同樣的方法,我們在新的終端建立一個 ubuntu2 的容器,並使用
docker ps
檢視正在執行的容器。
檢視正在執行的容器
輸入 exit 退出容器。
docker run -d ubuntu
會出現一串長的字母數字組成的串,為容器的 id,請注意容器要有持續執行的程序存在,否則,容器會很快自動退出。
執行容器並指定MAC地址
docker run -d --name='centos3' --hostname='centos3' --mac-address="02:42:AC:11:00:24" docker-centos6.10-hadoop-spark
列出所有的容器
docker ps -a
列出最近一次啟動的容器
docker ps -l
檢查容器
docker inspect centos1
可以獲取容器的相關資訊。
獲取容器CID
docker inspect -f '{{.Id}}' centos1
獲取容器PID
docker inspect -f '{{.State.Pid}}' centos1
獲取容器IP
docker inspect -f '{{.NetworkSettings.IPAddress}}' centos1
獲取容器閘道器
docker inspect -f '{{.NetworkSettings.Gateway}}' centos1
獲取容器 MAC
docker inspect -f '{{.NetworkSettings.MacAddress}}' centos1
檢視容器 IP 地址
docker inspect -f '{{.NetworkSettings.IPAddress}}' centos1
連線容器
ssh 容器的 IP 地址
輸入密碼:123456
容器執行後,可以通過另一種方式進入容器內部
docker exec -it centos /bin/sh
檢視容器執行過程中的日誌
docker logs centos1
列出一個容器裡面被改變的檔案或者目錄,列表會顯示出三種事件,A 增加的;D 刪除的;C 被改變的
docker diff centos1
和初始容器映象專案,使用者或系統增加/修改/刪除了那些目錄檔案,都可以檢視到。
檢視容器里正在執行的程序
docker top centos1
拷貝容器裡的檔案/目錄到本地伺服器
docker cp centos1:/etc/passwd /tmp/
ls /tmp/passwd
通過網路 IP 地址也可以將容器的檔案拷貝到伺服器,這種方式比較方便。
停止容器
docker stop centos1
停止所有容器
docker kill $(docker ps -a -q)
啟動容器
docker start centos1
刪除單個容器
docker stop centos1
docker rm centos1
刪除容器之前要先停止該容器的執行。
刪除所有容器
docker kill $(docker ps -a -q)
docker rm $(docker ps -a -q)
3. 卷的概念
為了能夠儲存(持久化)資料以及共享容器間的資料,docker 提出了卷的概念。卷 Volume 就是容器的特定目錄,該目錄下的檔案儲存在宿主機上,而不是容器的檔案系統內。
資料卷是一個可供一個或多個容器使用的特殊目錄,它繞過容器預設的檔案系統,可以提供很多有用的特性:
(1)資料卷可以在容器之間共享和重用;
(2)對資料卷的修改會立馬生效;
(3)對資料卷的更新,不會影響映象;
(4)資料卷預設會一直存在,即使容器被刪除。
注意:資料卷的使用,類似於 Linux下對目錄進行掛載 mount,容器中被指定為掛載點的目錄中的檔案會隱藏掉,能顯示看的是掛載的資料卷。
建立、使用資料卷
mkdir -p /root/volume1
mkdir -p /root/volume2
docker run -d -v /volume1 --name='centos5' docker-centos6.10-hadoop-spark
docker run -d -v /root/volume1:/volume1 --name='centos6' docker-centos6.10-hadoop-spark
docker run -d -v /root/volume1:/volume1 -v /root/volume2:/volume2 --name='centos7' docker-centos6.10-hadoop-spark
docker run -d -v /root/volume1:/volume1:ro --name='centos8' docker-centos6.10-hadoop-spark
使用docker run命令建立容器,指定 -v 標記來建立一個數據卷並掛載到容器裡;可以掛載多個數據卷;可以設定卷的只讀屬性;可以不指定伺服器對映的目錄,由系統自動指定目錄,通過 docker inspect 來檢視對映的路徑。
分別進入這些容器,檢視 /volume1、/volume2目錄。
資料卷共享
如果要授權一個容器訪問另一個容器的資料卷,可以使用-volumes-from 引數來執行。
資料卷容器
如果有一些持續更新的資料需要在容器之間共享,最好建立資料卷容器。
資料卷容器,其實就是一個正常的容器,專門用來提供資料卷供其它容器掛載的。
(1)建立一個名為 dbdata 的資料卷容器
docker run -d -v /dbdata --name dbdata docker-centos6.10-hadoop-spark
(2)在其他容器中使用--volumes-from來掛載 dbdata 容器中的資料卷
docker run -d --volumes-from dbdata --name db1 docker-centos6.10-hadoop-spark
docker run -d --volumes-from dbdata --name db2 docker-centos6.10-hadoop-spark
這樣就可以實現容器之間的資料共享。
分別進入這些容器,檢視 /volume1、/volume2 目錄。
4. 自制映象併發布
儲存容器修改,提交一個新的容器映象
docker commit centos1 centos111
將現有的容器提交形成一個新的容器映象,使用 docker images 可以看到 centos111 映象。通過此方法,可以建立一個新的容器映象。
檢視映象
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos111 latest d691a75ee371 23 minutes ago 501.5 MB
根據新容器映象建立容器
docker run -d --name='centos111' centos111
檢視容器
docker inspect centos111
匯出和匯入映象
當需要把一臺機器上的映象遷移到另一臺機器的時候,需要匯出映象與匯入映象。
機器A
docker save docker-centos6.10-hadoop-spark > docker-centos6.10-hadoop-spark2.tar
或
docker save -o docker-centos6.10-hadoop-spark docker-centos6.10-hadoop-spark2.tar
使用 scp 命令同其他方式將 docker-centos6.10-hadoop-spark2.tar 拷到機器 B 上
機器B
docker load < docker-centos6.10-hadoop-spark2.tar
或
docker load -i docker-centos6.10-hadoop-spark2.tar
釋出容器映象
docker push centos6.8-lamp1
將容器釋出到網路中。
4. docker 網路
docker 啟動時會在宿主機器上建立一個名為 docker0 的虛擬網路介面。它會從RFC 1918 定義的私有地址中隨機選擇一個主機不用的地址和子網掩碼,並將它分配給 docker0,預設選擇 172.18.0.1/16,一個 16 位的子網掩碼給容器提供了 65534 個 IP 地址。
docker0 並不是正常的網路介面,只是一個在繫結到這上面的其他網絡卡間自動轉發資料包的虛擬乙太網橋,可以使容器與主機相互通訊、容器與容器間相互通訊。
docker 每建立一個容器,就會建立一對對等介面(Peer Interface),類似於一個管子的兩端,在一邊可以收到另一邊傳送的資料包。docker會將對等介面中的一個做為 eth0 介面連線到容器上,並使用類似於vethAQI2QT 這樣的惟一名稱來持有另一個,該名稱取決於主機的名稱空間。通過將所有 veth* 介面繫結到 docker0 橋接網絡卡上,docker 在主機和所有 docker 容器間建立一個共享的虛擬子網。
docker NAT 網路
docker 容器預設通過 nat 方式訪問網路,docker 啟動時會在宿主主機上建立一個名為 docker0 的虛擬網路介面,docker0 只是一個在繫結到這上面的其他網絡卡間自動轉發資料包的虛擬乙太網橋,它可以使容器和主機相互通訊、容器與容器間通訊。
docker0 的閘道器地址是172.18.0.1,掩碼是 16 位,提供了 65534 個IP地址。
NAT 方式,虛擬器容器可以訪問外網(宿主機以外),但宿主機以外的機器不能訪問容器內網。
docker Bridage 網路
docker 容器可以通過 bridge 方式訪問網路。
bridge方式,虛擬器容器可以訪問外網(宿主機以外),宿主機以外的機器也能訪問容器內網。
6. docker pipework
docker 自身的網路功能比較簡單,不能滿足很多複雜的應用場景。因此有很多開源專案用來改善 docker 的網路功能,如 pipework、weave、flannel 等。
pipework 是由 docker 的工程師 Jérôme Petazzoni 開發的一個 docker 網路配置工具,由 200 多行 shell 實現,方便易用。
安裝 pipework
git clone https://github.com/jpetazzo/pipework
cp pipework/pipework /bin/
或
wget [http://172.17.1.240/docker/software/pipework](http://172.17.1.240/docker/software/pipework)
chmod a+x pipework
cp pipework /bin/
執行容器
docker run -d --net='none' --name='centos9' docker-centos6.10-hadoop-spark
配置容器網路,並連到網橋 docker0 上;閘道器在IP地址後面加 @ 指定。
pipework docker0 centos9 172.18.0.100/[email protected]
7. docker 網路埠對映
容器如果使用 docker0 虛擬網路,那麼容器的網路是 172.17.0.0/16,容器可以通過 NAT 方式訪問外網;但外網不能訪問內網。如果容器使用 br0 虛擬網路,容器和伺服器可以在同一個網路地址段;容器可以訪問外網;外網也可以訪問容器網路。
對於使用 docker0 虛擬網路的容器,可以通過埠對映的方式,讓外網訪問容器某些埠。
執行容器
docker run -d -p 38022:22 --name='centos10' docker-centos6.10-hadoop-spark
連線容器
ssh localhost -p 38022
在其他伺服器上通過訪問物理伺服器加埠即可訪問容器,可以一次對映多個埠。
執行容器
docker run -d -p 38022:22 -p 38080:80 --name='centos11' docker-centos6.10-hadoop-spark
其實現原理是在伺服器上通過 iptables 轉發來實現。當然也可以通過iptables 轉發整個容器 IP 地址。
4. 總結
由於容器是程序級別的,相比虛擬機器有很多優勢。
(1)啟動快
容器裡面的應用,直接就是底層系統的一個程序,而不是虛擬機器內部的程序。所以,啟動容器相當於啟動本機的一個程序,而不是啟動一個作業系統,速度就快很多。
(2)資源佔用少
容器只佔用需要的資源,不佔用那些沒有用到的資源;虛擬機器由於是完整的作業系統,不可避免要佔用所有資源。另外,多個容器可以共享資源,虛擬機器都是獨享資源。
(3)體積小
容器只要包含用到的元件即可,而虛擬機器是整個作業系統的打包,所以容器檔案比虛擬機器檔案要小很多。
總之,容器有點像輕量級的虛擬機器,能夠提供虛擬化的環境,但是成本開銷小得多。