Docker应用学习
Docker是什么?
在計算機技術(shù)日新月異的今天,?Docker?在國內(nèi)發(fā)展的如火如荼,特別是在一線互聯(lián)網(wǎng)公司,?Docker?的使用是十分普遍的,甚至成為了一些企業(yè)面試的加分項。
?
對于我們而言,熟悉?docker?可以快速搭建?CTF環(huán)境,幫助我們快速提升自己。
市面上已經(jīng)有很多優(yōu)秀的教程,但是很多原理性的東西,筆者認為那些教程對初學(xué)者而言還是很難理解,感覺沒有說清楚(筆者自己都覺得挺懵逼的),為了讓初學(xué)者少走彎路,我將以我的學(xué)習(xí)經(jīng)歷以及作為一個?CTF選手?的角度,編寫此套教程,來帶大家去了解并熟練運用?docker?,祝愿各位讀者朋友們學(xué)完此套教程后,在未來企業(yè)面試中能夠多一項加分的籌碼,能夠幫助到大家,我覺得就很值了。
既然說了這么多,?docker?到底是個什么東西呢?
我們在理解?docker?之前,首先我們得先區(qū)分清楚兩個概念,容器和虛擬機。
可能很多讀者朋友都用過虛擬機,而對容器這個概念比較的陌生。
我們用的傳統(tǒng)虛擬機如?VMware?,?VisualBox?之類的需要模擬整臺機器包括硬件,每臺虛擬機都需要有自己的操作系統(tǒng),虛擬機一旦被開啟,預(yù)分配給它的資源將全部被占用。每一臺虛擬機包括應(yīng)用,必要的二進制和庫,以及一個完整的用戶操作系統(tǒng)。
而容器技術(shù)是和我們的宿主機共享硬件資源及操作系統(tǒng),可以實現(xiàn)資源的動態(tài)分配。容器包含應(yīng)用和其所有的依賴包,但是與其他容器共享內(nèi)核。容器在宿主機操作系統(tǒng)中,在用戶空間以分離的進程運行。
容器技術(shù)是實現(xiàn)操作系統(tǒng)虛擬化的一種途徑,可以讓您在資源受到隔離的進程中運行應(yīng)用程序及其依賴關(guān)系。通過使用容器,我們可以輕松打包應(yīng)用程序的代碼、配置和依賴關(guān)系,將其變成容易使用的構(gòu)建塊,從而實現(xiàn)環(huán)境一致性、運營效率、開發(fā)人員生產(chǎn)力和版本控制等諸多目標(biāo)。容器可以幫助保證應(yīng)用程序快速、可靠、一致地部署,其間不受部署環(huán)境的影響。容器還賦予我們對資源更多的精細化控制能力,讓我們的基礎(chǔ)設(shè)施效率更高。通過下面這幅圖我們可以很直觀的反映出這兩者的區(qū)別所在。
Docker 屬于 Linux 容器的一種封裝,提供簡單易用的容器使用接口。它是目前最流行的?Linux?容器解決方案。
而?Linux?容器是?Linux?發(fā)展出了另一種虛擬化技術(shù),簡單來講,?Linux?容器不是模擬一個完整的操作系統(tǒng),而是對進程進行隔離,相當(dāng)于是在正常進程的外面套了一個保護層。對于容器里面的進程來說,它接觸到的各種資源都是虛擬的,從而實現(xiàn)與底層系統(tǒng)的隔離。
Docker?將應(yīng)用程序與該程序的依賴,打包在一個文件里面。運行這個文件,就會生成一個虛擬容器。程序在這個虛擬容器里運行,就好像在真實的物理機上運行一樣。有了?Docker?,就不用擔(dān)心環(huán)境問題。
總體來說,?Docker?的接口相當(dāng)簡單,用戶可以方便地創(chuàng)建和使用容器,把自己的應(yīng)用放入容器。容器還可以進行版本管理、復(fù)制、分享、修改,就像管理普通的代碼一樣。
Docker的優(yōu)勢
Docker相比于傳統(tǒng)虛擬化方式具有更多的優(yōu)勢:
- docker?啟動快速屬于秒級別。虛擬機通常需要幾分鐘去啟動
- docker?需要的資源更少,?docker?在操作系統(tǒng)級別進行虛擬化,?docker?容器和內(nèi)核交互,幾乎沒有性能損耗,性能優(yōu)于通過?Hypervisor?層與內(nèi)核層的虛擬化
- docker?更輕量,?docker?的架構(gòu)可以共用一個內(nèi)核與共享應(yīng)用程序庫,所占內(nèi)存極小。同樣的硬件環(huán)境,?Docker?運行的鏡像數(shù)遠多于虛擬機數(shù)量,對系統(tǒng)的利用率非常高
- 與虛擬機相比,?docker?隔離性更弱,?docker?屬于進程之間的隔離,虛擬機可實現(xiàn)系統(tǒng)級別隔離
- 安全性:?docker?的安全性也更弱。?Docker?的租戶?root?和宿主機?root?等同,一旦容器內(nèi)的用戶從普通用戶權(quán)限提升為root權(quán)限,它就直接具備了宿主機的root權(quán)限,進而可進行無限制的操作。虛擬機租戶?root?權(quán)限和宿主機的?root?虛擬機權(quán)限是分離的,并且虛擬機利用如?Intel?的?VT-d?和?VT-x?的?ring-1?硬件隔離技術(shù),這種隔離技術(shù)可以防止虛擬機突破和彼此交互,而容器至今還沒有任何形式的硬件隔離,這使得容器容易受到攻擊
- 可管理性:?docker?的集中化管理工具還不算成熟。各種虛擬化技術(shù)都有成熟的管理工具,例如?VMware vCenter?提供完備的虛擬機管理能力
- 高可用和可恢復(fù)性:?docker?對業(yè)務(wù)的高可用支持是通過快速重新部署實現(xiàn)的。虛擬化具備負載均衡,高可用,容錯,遷移和數(shù)據(jù)保護等經(jīng)過生產(chǎn)實踐檢驗的成熟保障機制,?VMware?可承諾虛擬機?99.999%?高可用,保證業(yè)務(wù)連續(xù)性
- 快速創(chuàng)建、刪除:虛擬化創(chuàng)建是分鐘級別的,?Docker?容器創(chuàng)建是秒級別的,?Docker?的快速迭代性,決定了無論是開發(fā)、測試、部署都可以節(jié)約大量時間
- 交付、部署:虛擬機可以通過鏡像實現(xiàn)環(huán)境交付的一致性,但鏡像分發(fā)無法體系化。?Docker?在?Dockerfile?中記錄了容器構(gòu)建過程,可在集群中實現(xiàn)快速分發(fā)和快速部署
我們可以從下面這張表格很清楚地看到容器相比于傳統(tǒng)虛擬機的特性的優(yōu)勢所在:
| 啟動 | 秒級 | 分鐘級 | 
| 硬盤使用 | 一般為MB | 一般為GB | 
| 性能 | 接近原生 | 弱于 | 
| 系統(tǒng)支持量 | 單機支持上千個容器 | 一般是幾十個 | 
Docker的三個基本概念
從上圖我們可以看到,Docker?中包括三個基本的概念:
- Image(鏡像)
- Container(容器)
- Repository(倉庫)
鏡像是?Docker?運行容器的前提,倉庫是存放鏡像的場所,可見鏡像更是?Docker?的核心。
Image (鏡像)
那么鏡像到底是什么呢?
Docker?鏡像可以看作是一個特殊的文件系統(tǒng),除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些為運行時準(zhǔn)備的一些配置參數(shù)(如匿名卷、環(huán)境變量、用戶等)。鏡像不包含任何動態(tài)數(shù)據(jù),其內(nèi)容在構(gòu)建之后也不會被改變。
鏡像(Image)就是一堆只讀層(read-only layer)的統(tǒng)一視角,也許這個定義有些難以理解,下面的這張圖能夠幫助讀者理解鏡像的定義。
從左邊我們看到了多個只讀層,它們重疊在一起。除了最下面一層,其它層都會有一個指針指向下一層。這些層是Docker?內(nèi)部的實現(xiàn)細節(jié),并且能夠在主機的文件系統(tǒng)上訪問到。統(tǒng)一文件系統(tǒng)?(union file system)?技術(shù)能夠?qū)⒉煌膶诱铣梢粋€文件系統(tǒng),為這些層提供了一個統(tǒng)一的視角,這樣就隱藏了多層的存在,在用戶的角度看來,只存在一個文件系統(tǒng)。我們可以在圖片的右邊看到這個視角的形式。
Container (容器)
容器?(container)?的定義和鏡像?(image)?幾乎一模一樣,也是一堆層的統(tǒng)一視角,唯一區(qū)別在于容器的最上面那一層是可讀可寫的。
由于容器的定義并沒有提及是否要運行容器,所以實際上,容器 = 鏡像 + 讀寫層。
Repository (倉庫)
Docker?倉庫是集中存放鏡像文件的場所。鏡像構(gòu)建完成后,可以很容易的在當(dāng)前宿主上運行,但是, 如果需要在其它服務(wù)器上使用這個鏡像,我們就需要一個集中的存儲、分發(fā)鏡像的服務(wù),Docker Registry?(倉庫注冊服務(wù)器)就是這樣的服務(wù)。有時候會把倉庫?(Repository)?和倉庫注冊服務(wù)器?(Registry)?混為一談,并不嚴(yán)格區(qū)分。Docker?倉庫的概念跟?Git?類似,注冊服務(wù)器可以理解為?GitHub?這樣的托管服務(wù)。實際上,一個?Docker Registry?中可以包含多個倉庫?(Repository)?,每個倉庫可以包含多個標(biāo)簽?(Tag),每個標(biāo)簽對應(yīng)著一個鏡像。所以說,鏡像倉庫是?Docker?用來集中存放鏡像文件的地方類似于我們之前常用的代碼倉庫。
通常,一個倉庫會包含同一個軟件不同版本的鏡像,而標(biāo)簽就常用于對應(yīng)該軟件的各個版本?。我們可以通過<倉庫名>:<標(biāo)簽>的格式來指定具體是這個軟件哪個版本的鏡像。如果不給出標(biāo)簽,將以?latest?作為默認標(biāo)簽.。
倉庫又可以分為兩種形式:
- public(公有倉庫)
- private(私有倉庫)
Docker Registry?公有倉庫是開放給用戶使用、允許用戶管理鏡像的?Registry?服務(wù)。一般這類公開服務(wù)允許用戶免費上傳、下載公開的鏡像,并可能提供收費服務(wù)供用戶管理私有鏡像。
除了使用公開服務(wù)外,用戶還可以在本地搭建私有?Docker Registry?。Docker?官方提供了?Docker Registry?鏡像,可以直接使用做為私有?Registry?服務(wù)。當(dāng)用戶創(chuàng)建了自己的鏡像之后就可以使用?push?命令將它上傳到公有或者私有倉庫,這樣下次在另外一臺機器上使用這個鏡像時候,只需要從倉庫上?pull?下來就可以了。
我們主要把?Docker?的一些常見概念如?Image?,?Container?,?Repository?做了詳細的闡述,也從傳統(tǒng)虛擬化方式的角度闡述了?docker?的優(yōu)勢,我們從下圖可以直觀地看到?Docker?的架構(gòu):
Docker?使用?C/S?結(jié)構(gòu),即客戶端/服務(wù)器體系結(jié)構(gòu)。?Docker?客戶端與?Docker?服務(wù)器進行交互,Docker服務(wù)端負責(zé)構(gòu)建、運行和分發(fā)?Docker?鏡像。?Docker?客戶端和服務(wù)端可以運行在一臺機器上,也可以通過?RESTful?、?stock?或網(wǎng)絡(luò)接口與遠程?Docker?服務(wù)端進行通信。
這張圖展示了?Docker?客戶端、服務(wù)端和?Docker?倉庫(即?Docker Hub?和?Docker Cloud?),默認情況下Docker?會在?Docker?中央倉庫尋找鏡像文件,這種利用倉庫管理鏡像的設(shè)計理念類似于?Git?,當(dāng)然這個倉庫是可以通過修改配置來指定的,甚至我們可以創(chuàng)建我們自己的私有倉庫。
Docker的安裝和使用
Docker?的安裝和使用有一些前提條件,主要體現(xiàn)在體系架構(gòu)和內(nèi)核的支持上。對于體系架構(gòu),除了?Docker?一開始就支持的?X86-64?,其他體系架構(gòu)的支持則一直在不斷地完善和推進中。
Docker?分為?CE?和?EE?兩大版本。?CE?即社區(qū)版(免費,支持周期?7?個月),?EE?即企業(yè)版,強調(diào)安全,付費使用,支持周期?24?個月。
我們在安裝前可以參看官方文檔獲取最新的?Docker?支持情況,官方文檔在這里:
https://docs.docker.com/install/Docker?對于內(nèi)核支持的功能,即內(nèi)核的配置選項也有一定的要求(比如必須開啟?Cgroup?和?Namespace?相關(guān)選項,以及其他的網(wǎng)絡(luò)和存儲驅(qū)動等),?Docker?源碼中提供了一個檢測腳本來檢測和指導(dǎo)內(nèi)核的配置,腳本鏈接在這里:
https://raw.githubusercontent.com/docker/docker/master/contrib/check-config.sh在滿足前提條件后,安裝就變得非常的簡單了。
Docker CE?的安裝請參考官方文檔:
- MacOS:https://docs.docker.com/docker-for-mac/install/
- Windows:https://docs.docker.com/docker-for-windows/install/
- Ubuntu:https://docs.docker.com/install/linux/docker-ce/ubuntu/
- Debian:https://docs.docker.com/install/linux/docker-ce/debian/
- CentOS:https://docs.docker.com/install/linux/docker-ce/centos/
- Fedora:https://docs.docker.com/install/linux/docker-ce/fedora/
- 其他?Linux?發(fā)行版:https://docs.docker.com/install/linux/docker-ce/binaries/
這里我們以?CentOS7?作為本文的演示。
環(huán)境準(zhǔn)備
- 阿里云服務(wù)器(1核2G,1M帶寬)
- CentOS 7.4 64位
由于?Docker-CE?支持?64?位版本的?CentOS7?,并且要求內(nèi)核版本不低于?3.10
首先我們需要卸載掉舊版本的?Docker
?$ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
我們執(zhí)行以下安裝命令去安裝依賴包:
?$ sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
這里我事先已經(jīng)安裝過了,所以提示我已經(jīng)安裝了最新版本
安裝Docker
Docker?軟件包已經(jīng)包括在默認的?CentOS-Extras?軟件源里。因此想要安裝?docker,只需要運行下面的?yum?命令
$ sudo yum install docker當(dāng)然在測試或開發(fā)環(huán)境中?Docker?官方為了簡化安裝流程,提供了一套便捷的安裝腳本,CentOS?系統(tǒng)上可以使用這套腳本安裝:
?curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh
具體可以參看?docker-install?的腳本:
https://github.com/docker/docker-install執(zhí)行這個命令后,腳本就會自動的將一切準(zhǔn)備工作做好,并且把?Docker CE?的?Edge?版本安裝在系統(tǒng)中。
安裝完成后,運行下面的命令,驗證是否安裝成功:
?docker version
or
docker info
返回docker的版本相關(guān)信息,證明?docker?安裝成功
啟動Docker-CE
?$ sudo systemctl enable docker
$ sudo systemctl start docker
Docker的簡單運用---Hello World
由于服務(wù)器日常崩潰了,?docker?出了點問題,所以以下案例的演示是基于?Kali Linux?環(huán)境下進行的。
我們通過最簡單的?image?文件?hello world,感受一下?Docker?的魅力吧!
我們直接運行下面的命令,將名為?hello-world?的?image?文件從倉庫抓取到本地。
docker pull library/hello-worlddocker pull images?是抓取?image?文件,?library/hello-world?是?image?文件在倉庫里面的位置,其中?library?是?image?文件所在的組,?hello-world?是?image?文件的名字。
抓取成功以后,就可以在本機看到這個?image?文件了。
docker images我們可以看到如下結(jié)果:
現(xiàn)在,我們可以運行?hello-world?這個?image?文件
docker run hello-world我們可以看到如下結(jié)果:
輸出這段提示以后,hello world?就會停止運行,容器自動終止。有些容器不會自動終止,因為提供的是服務(wù),比如Mysql鏡像等。
是不是很?easy?呢?我們從上面可以看出,?docker?的功能是十分強大的,除此之外,我們還可以拉去一些?Ubuntu?,?Apache等鏡像,在未來的教程中我們將會一一提到。
Docker?提供了一套簡單實用的命令來創(chuàng)建和更新鏡像,我們可以通過網(wǎng)絡(luò)直接下載一個已經(jīng)創(chuàng)建好了的應(yīng)用鏡像,并通過?Docker RUN?命令就可以直接使用。當(dāng)鏡像通過?RUN?命令運行成功后,這個運行的鏡像就是一個?Docker?容器啦,容器可以理解為一個輕量級的沙箱,?Docker?利用容器來運行和隔離應(yīng)用,容器是可以被啟動、停止、刪除的,這并不會影響?Docker?鏡像。
我們可以看看下面這幅圖:
Docker?客戶端是?Docker?用戶與?Docker?交互的主要方式。當(dāng)您使用?docker?命令行運行命令時,?Docker?客戶端將這些命令發(fā)送給服務(wù)器端,服務(wù)端將執(zhí)行這些命令。?docker?命令使用?docker API?。?Docker?客戶端可以與多個服務(wù)端進行通信。
我們將剖析一下?Docker?容器是如何工作的,學(xué)習(xí)好Docker容器工作的原理,我們就可以自己去管理我們的容器了。
Docker架構(gòu)
在上面的學(xué)習(xí)中,我們簡單地講解了Docker的基本架構(gòu)。了解到了Docker?使用的是?C/S?結(jié)構(gòu),即客戶端/服務(wù)器體系結(jié)構(gòu)。明白了?Docker?客戶端與?Docker?服務(wù)器進行交互時,?Docker?服務(wù)端負責(zé)構(gòu)建、運行和分發(fā)?Docker?鏡像。 也知道了Docker?客戶端和服務(wù)端可以運行在一臺機器上,可以通過?RESTful?、?stock?或網(wǎng)絡(luò)接口與遠程?Docker?服務(wù)端進行通信。
我們從下圖可以很直觀的了解到Docker的架構(gòu):
Docker?的核心組件包括:
Docker?采用的是?Client/Server?架構(gòu)。客戶端向服務(wù)器發(fā)送請求,服務(wù)器負責(zé)構(gòu)建、運行和分發(fā)容器。客戶端和服務(wù)器可以運行在同一個?Host?上,客戶端也可以通過?socket?或?REST API?與遠程的服務(wù)器通信。可能很多朋友暫時不太理解一些東西,比如?REST API?是什么東西等,不過沒關(guān)系,在后面的文章中會一一給大家講解清楚。
Docker Client
Docker Client?,也稱?Docker?客戶端。它其實就是?Docker?提供命令行界面?(CLI)?工具,是許多?Docker?用戶與?Docker?進行交互的主要方式。客戶端可以構(gòu)建,運行和停止應(yīng)用程序,還可以遠程與Docker_Host進行交互。最常用的?Docker客戶端就是?docker?命令,我們可以通過?docker?命令很方便地在?host?上構(gòu)建和運行?docker?容器。
Docker daemon
Docker daemon?是服務(wù)器組件,以?Linux?后臺服務(wù)的方式運行,是?Docker?最核心的后臺進程,我們也把它稱為守護進程。它負責(zé)響應(yīng)來自?Docker Client?的請求,然后將這些請求翻譯成系統(tǒng)調(diào)用完成容器管理操作。該進程會在后臺啟動一個?API Server?,負責(zé)接收由?Docker Client?發(fā)送的請求,接收到的請求將通過Docker daemon?內(nèi)部的一個路由分發(fā)調(diào)度,由具體的函數(shù)來執(zhí)行請求。
我們大致可以將其分為以下三部分:
- Docker Server
- Engine
- Job
Docker Daemon的架構(gòu)如下所示:
Docker Daemon?可以認為是通過?Docker Server?模塊接受?Docker Client?的請求,并在?Engine?中處理請求,然后根據(jù)請求類型,創(chuàng)建出指定的?Job?并運行。?Docker Daemon?運行在?Docker host?上,負責(zé)創(chuàng)建、運行、監(jiān)控容器,構(gòu)建、存儲鏡像。
運行過程的作用有以下幾種可能:
- 向?Docker Registry?獲取鏡像
- 通過?graphdriver?執(zhí)行容器鏡像的本地化操作
- 通過?networkdriver?執(zhí)行容器網(wǎng)絡(luò)環(huán)境的配置
- 通過?execdriver?執(zhí)行容器內(nèi)部運行的執(zhí)行工作
由于?Docker Daemon?和?Docker Client?的啟動都是通過可執(zhí)行文件?docker?來完成的,因此兩者的啟動流程非常相似。?Docker?可執(zhí)行文件運行時,運行代碼通過不同的命令行?flag?參數(shù),區(qū)分兩者,并最終運行兩者各自相應(yīng)的部分。
啟動?Docker Daemon?時,一般可以使用以下命令來完成
?docker --daemon = true
docker –d
docker –d = true
再由?docker?的?main()?函數(shù)來解析以上命令的相應(yīng)?flag?參數(shù),并最終完成?Docker Daemon?的啟動。
下圖可以很直觀地看到?Docker Daemon?的啟動流程:
默認配置下,?Docker daemon?只能響應(yīng)來自本地?Host?的客戶端請求。如果要允許遠程客戶端請求,需要在配置文件中打開?TCP監(jiān)聽。我們可以照著如下步驟進行配置:
1、編輯配置文件?/etc/systemd/system/multi-user.target.wants/docker.service?,在環(huán)境變量?ExecStart?后面添加?-H tcp://0.0.0.0,允許來自任意 IP 的客戶端連接。
2、重啟?Docker daemon
?systemctl daemon-reload
systemctl restart docker.service
3、我們通過以下命令即可實現(xiàn)與遠程服務(wù)器通信
docker -H 服務(wù)器IP地址 info-H?是用來指定服務(wù)器主機,?info?子命令用于查看?Docker?服務(wù)器的信息
Docker Image
Docker?鏡像可以看作是一個特殊的文件系統(tǒng),除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些為運行時準(zhǔn)備的一些配置參數(shù)(如匿名卷、環(huán)境變量、用戶等)。鏡像不包含任何動態(tài)數(shù)據(jù),其內(nèi)容在構(gòu)建之后也不會被改變。我們可將?Docker鏡像看成只讀模板,通過它可以創(chuàng)建?Docker?容器。
鏡像有多種生成方法:
我們可以將鏡像的內(nèi)容和創(chuàng)建步驟描述在一個文本文件中,這個文件被稱作?Dockerfile?,通過執(zhí)行?docker build <docker-file>?命令可以構(gòu)建出 Docker 鏡像,在后續(xù)的教程中,我們會用一篇專門討論這個問題。
Docker Registry
Docker registry?是存儲?docker image?的倉庫,它在?docker?生態(tài)環(huán)境中的位置如下圖所示:
運行docker push、docker pull、docker search時,實際上是通過?docker daemon?與?docker registry?通信。
Docker Container
Docker?容器就是?Docker?鏡像的運行實例,是真正運行項目程序、消耗系統(tǒng)資源、提供服務(wù)的地方。?Docker Container?提供了系統(tǒng)硬件環(huán)境,我們可以使用?Docker Images?這些制作好的系統(tǒng)盤,再加上我們所編寫好的項目代碼,?run?一下就可以提供服務(wù)啦。
Docker組件是如何協(xié)作運行容器
看到這里,我相信各位讀者朋友們應(yīng)該已經(jīng)對Docker基礎(chǔ)架構(gòu)已經(jīng)熟悉的差不多了,我們還記得運行的第一個容器嗎?現(xiàn)在我們再通過hello-world這個例子來體會一下?Docker?各個組件是如何協(xié)作的。
容器啟動過程如下:
- Docker?客戶端執(zhí)行?docker run?命令
- Docker daemon?發(fā)現(xiàn)本地沒有?hello-world?鏡像
- daemon?從?Docker Hub?下載鏡像
- 下載完成,鏡像?hello-world?被保存到本地
- Docker daemon?啟動容器
具體過程可以看如下這幅演示圖:
我們可以通過docker images?可以查看到?hello-world?已經(jīng)下載到本地
我們可以通過docker ps?或者?docker container ls?顯示正在運行的容器,我們可以看到,?hello-world?在輸出提示信息以后就會停止運行,容器自動終止,所以我們在查看的時候沒有發(fā)現(xiàn)有容器在運行。
我們把?Docker?容器的工作流程剖析的十分清楚了,我們大體可以知道?Docker?組件協(xié)作運行容器可以分為以下幾個過程:
了解了這些過程以后,我們再來理解這些命令就不會覺得很突兀了,下面我來給大家講講?Docker?常用的一些命令操作吧。
Docker常用命令
我們可以通過?docker -h?去查看命令的詳細的幫助文檔。在這里我只會講一些平常日常比賽或者生活中我們可能會用的比較多的一些命令。
例如,我們需要拉取一個?docker?鏡像,我們可以用如下命令:
docker pull image_nameimage_name?為鏡像的名稱,而如果我們想從?Docker Hub?上去下載某個鏡像,我們可以使用以下命令:
docker pull centos:latestcentos:lastest?是鏡像的名稱,?Docker daemon?發(fā)現(xiàn)本地沒有我們需要的鏡像,會自動去?Docker Hub?上去下載鏡像,下載完成后,該鏡像被默認保存到?/var/lib/docker?目錄下。
接著我們?nèi)绻氩榭聪轮鳈C下存在多少鏡像,我們可以用如下命令:
docker images我們要想知道當(dāng)前有哪些容器在運行,我們可以用如下命令:
docker ps -a-a?是查看當(dāng)前所有的容器,包括未運行的
我們該如何去對一個容器進行啟動,重啟和停止呢?我們可以用如下命令:
?docker start container_name/container_id
docker restart container_name/container_id
docker stop container_name/container_id
這個時候我們?nèi)绻脒M入到這個容器中,我們可以使用?attach?命令:
docker attach container_name/container_id那如果我們想運行這個容器中的鏡像的話,并且調(diào)用鏡像里面的?bash?,我們可以使用如下命令:
docker run -t -i container_name/container_id /bin/bash那如果這個時候,我們想刪除指定鏡像的話,由于?image?被某個?container?引用(拿來運行),如果不將這個引用的?container?銷毀(刪除),那?image?肯定是不能被刪除。我們首先得先去停止這個容器:
?docker ps
docker stop container_name/container_id
然后我們用如下命令去刪除這個容器:
docker rm container_name/container_id然后這個時候我們再去刪除這個鏡像:
docker rmi image_name此時,常用的?Docker?相關(guān)的命令就講到這里為止了,我們在后續(xù)的文章中還會反復(fù)地提到這些命令。
Dockerfile是什么
前面我們已經(jīng)提到了?Docker?的一些基本概念。以?CTF?選手的角度來看,我們可以去使用?Dockerfile?定義鏡像,依賴鏡像來運行容器,可以去模擬出一個真實的漏洞場景。因此毫無疑問的說,?Dockerfile?是鏡像和容器的關(guān)鍵,并且?Dockerfile?還可以很輕易的去定義鏡像內(nèi)容,說了這么多,那么?Dockerfile?到底是個什么東西呢?
Dockerfile?是自動構(gòu)建?docker?鏡像的配置文件, 用戶可以使用?Dockerfile?快速創(chuàng)建自定義的鏡像。Dockerfile?中的命令非常類似于?linux?下的?shell?命令。
我們可以通過下面這幅圖來直觀地感受下 Docker 鏡像、容器和 Dockerfile 三者之間的關(guān)系。
我們從上圖中可以看到,?Dockerfile?可以自定義鏡像,通過?Docker?命令去運行鏡像,從而達到啟動容器的目的。
Dockerfile?是由一行行命令語句組成,并且支持已?#?開頭的注釋行。
一般來說,我們可以將?Dockerfile?分為四個部分:
- 基礎(chǔ)鏡像(父鏡像)信息指令?FROM
- 維護者信息指令?MAINTAINER
- 鏡像操作指令?RUN?、?EVN?、?ADD?和?WORKDIR?等
- 容器啟動指令?CMD?、?ENTRYPOINT?和?USER?等
下面是一段簡單的Dockerfile的例子:
?FROM python:2.7
MAINTAINER Angel_Kitty <angelkitty6698@gmail.com>
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 5000
ENTRYPOINT ["python"]
CMD ["app.py"]
我們可以分析一下上面這個過程:
- 1、從?Docker Hub?上?pull?下?python 2.7?的基礎(chǔ)鏡像
- 2、顯示維護者的信息
- 3、copy?當(dāng)前目錄到容器中的?/app?目錄下 復(fù)制本地主機的?<src>?(?Dockerfile?所在目錄的相對路徑)到容器里?<dest>
- 4、指定工作路徑為?/app
- 5、安裝依賴包
- 6、暴露?5000?端口
- 7、啟動?app
這個例子是啟動一個?python flask app?的?Dockerfile?(?flask?是?python?的一個輕量的?web?框架),相信大家從這個例子中能夠稍微理解了Dockfile的組成以及指令的編寫過程。
Dockerfile常用的指令
根據(jù)上面的例子,我們已經(jīng)差不多知道了Dockerfile的組成以及指令的編寫過程,我們再來理解一下這些常用命令就會得心應(yīng)手了。
由于?Dockerfile?中所有的命令都是以下格式:INSTRUCTION argument?,指令?(INSTRUCTION)?不分大小寫,但是推薦大寫,和sql語句是不是很相似呢?下面我們正式來講解一下這些指令集吧。
FROM
FROM?是用于指定基礎(chǔ)的?images?,一般格式為?FROM <image>?or?FORM <image>:<tag>?,所有的?Dockerfile?都用該以?FROM?開頭,FROM?命令指明?Dockerfile?所創(chuàng)建的鏡像文件以什么鏡像為基礎(chǔ),FROM?以后的所有指令都會在?FROM?的基礎(chǔ)上進行創(chuàng)建鏡像。可以在同一個?Dockerfile?中多次使用?FROM?命令用于創(chuàng)建多個鏡像。比如我們要指定?python 2.7?的基礎(chǔ)鏡像,我們可以像如下寫法一樣:
FROM python:2.7MAINTAINER
MAINTAINER 是用于指定鏡像創(chuàng)建者和聯(lián)系方式,一般格式為?MAINTAINER <name>?。這里我設(shè)置成我的?ID?和郵箱:
MAINTAINER Angel_Kitty <angelkitty6698@gmail.com>COPY
COPY?是用于復(fù)制本地主機的?<src>?(為 Dockerfile 所在目錄的相對路徑)到容器中的?<dest>。
當(dāng)使用本地目錄為源目錄時,推薦使用?COPY?。一般格式為?COPY <src><dest>?。例如我們要拷貝當(dāng)前目錄到容器中的?/app?目錄下,我們可以這樣操作:
COPY . /appWORKDIR
WORKDIR?用于配合?RUN,CMD,ENTRYPOINT?命令設(shè)置當(dāng)前工作路徑。可以設(shè)置多次,如果是相對路徑,則相對前一個?WORKDIR?命令。默認路徑為/。一般格式為?WORKDIR /path/to/work/dir?。例如我們設(shè)置/app?路徑,我們可以進行如下操作:
WORKDIR /appRUN
RUN?用于容器內(nèi)部執(zhí)行命令。每個?RUN?命令相當(dāng)于在原有的鏡像基礎(chǔ)上添加了一個改動層,原有的鏡像不會有變化。一般格式為?RUN <command>?。例如我們要安裝?python?依賴包,我們做法如下:
RUN pip install -r requirements.txtEXPOSE
EXPOSE?命令用來指定對外開放的端口。一般格式為?EXPOSE <port> [<port>...]
例如上面那個例子,開放5000端口:
EXPOSE 5000ENTRYPOINT
ENTRYPOINT?可以讓你的容器表現(xiàn)得像一個可執(zhí)行程序一樣。一個?Dockerfile?中只能有一個?ENTRYPOINT,如果有多個,則最后一個生效。
ENTRYPOINT?命令也有兩種格式:
- ENTRYPOINT ["executable", "param1", "param2"]?:推薦使用的?exec形式
- ENTRYPOINT command param1 param2?:shell?形式
例如下面這個,我們要將?python?鏡像變成可執(zhí)行的程序,我們可以這樣去做:
ENTRYPOINT ["python"]CMD
CMD?命令用于啟動容器時默認執(zhí)行的命令,CMD?命令可以包含可執(zhí)行文件,也可以不包含可執(zhí)行文件。不包含可執(zhí)行文件的情況下就要用?ENTRYPOINT?指定一個,然后?CMD?命令的參數(shù)就會作為ENTRYPOINT的參數(shù)。
CMD?命令有三種格式:
- CMD ["executable","param1","param2"]:推薦使用的?exec?形式。
- CMD ["param1","param2"]:無可執(zhí)行程序形式
- CMD command param1 param2:shell 形式。
一個?Dockerfile?中只能有一個CMD,如果有多個,則最后一個生效。而?CMD?的?shell?形式默認調(diào)用?/bin/sh -c?執(zhí)行命令。
CMD?命令會被?Docker?命令行傳入的參數(shù)覆蓋:docker run busybox /bin/echo Hello?Docker?會把?CMD?里的命令覆蓋。
例如我們要啟動?/app?,我們可以用如下命令實現(xiàn):
CMD ["app.py"]當(dāng)然還有一些其他的命令,我們在用到的時候再去一一講解一下。
構(gòu)建Dockerfile
我們大體已經(jīng)把Dockerfile的寫法講述完畢,我們可以自己動手寫一個例子:
?mkdir static_web
cd static_web
touch Dockerfile
然后 vi Dockerfile 開始編輯該文件
輸入 i 開始編輯
?
以下是我們構(gòu)建的Dockerfile內(nèi)容
``````````
FROM nginx
MAINTAINER Angel_Kitty <angelkitty6698@gmail.com>
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
``````````
編輯完后 按 esc 退出編輯
然后 :wq 寫入 退出
我們在?Dockerfile?文件所在目錄執(zhí)行:
docker build -t angelkitty/nginx_web:v1 .我們解釋一下,?-t?是為新鏡像設(shè)置倉庫和名稱,其中?angelkitty?為倉庫名,?nginx_web?為鏡像名,?:v1?為標(biāo)簽(不添加為默認?latest?)
我們構(gòu)建完成之后,使用?docker images?命令查看所有鏡像,如果存在?REPOSITORY?為?nginx?和?TAG?是?v1?的信息,就表示構(gòu)建成功。
接下來使用?docker run?命令來啟動容器
docker run --name nginx_web -d -p 8080:80 angelkitty/nginx_web:v1這條命令會用 nginx 鏡像啟動一個容器,命名為?nginx_web?,并且映射了 8080 端口,這樣我們可以用瀏覽器去訪問這個?nginx?服務(wù)器:http://localhost:8080/?或者 http://本機的IP地址:8080/,頁面返回信息:
這樣一個簡單使用?Dockerfile?構(gòu)建鏡像,運行容器的示例就完成了!
本文引用轉(zhuǎn)載?https://www.cnblogs.com/ECJTUACM-873284962/p/9789130.html
總結(jié)
以上是生活随笔為你收集整理的Docker应用学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Day215.课程详细页面功能完善、Ec
- 下一篇: 调整k8s的iptable参数时启动生效
