Docker入門知識
Docker是什麼?
在計算機技術日新月異的今天,
Docker
在國內發展的如火如荼,特別是在一線網際網路公司,
Docker
的使用是十分普遍的,甚至成為了一些企業面試的加分項,不信的話看看下面這張圖。
這是我在某招聘網站上看到的招聘
Java開發工程師 的招聘要求,其中有一條熟悉
docker
成為了你快速入職的加分項,由此可見熟悉
docker
在網際網路公司的地位之重要。
當然對於我們
CTF選手 而言,熟悉
docker
可以快速搭建
CTF環境
,完美地還原比賽真實漏洞的場景,幫助我們快速提升自己。
市面上已經有很多優秀的教程,但是很多原理性的東西,筆者認為那些教程對初學者而言還是很難理解,感覺沒有說清楚(筆者自己都覺得挺懵逼的),為了讓初學者少走彎路,我將以我的學習經歷以及作為一個
CTF選手 的角度,編寫此套教程,來帶大家去了解並熟練運用
docker
,祝願各位讀者朋友們學完此套教程後,在未來企業面試中能夠多一項加分的籌碼,能夠幫助到大家,我覺得就很值了。
既然說了這麼多,
docker
到底是個什麼東西呢?
我們在理解
docker
之前,首先我們得先區分清楚兩個概念,
容器和
虛擬機器。
可能很多讀者朋友都用過虛擬機器,而對容器這個概念比較的陌生。
我們用的傳統虛擬機器如
VMware
,
VisualBox
之類的需要模擬整臺機器包括硬體,每臺虛擬機器都需要有自己的作業系統,虛擬機器一旦被開啟,預分配給它的資源將全部被佔用。每一臺虛擬機器包括應用,必要的二進位制和庫,以及一個完整的使用者作業系統。
而容器技術是和我們的宿主機共享硬體資源及作業系統,可以實現資源的動態分配。容器包含應用和其所有的依賴包,但是與其他容器共享核心。容器在宿主機作業系統中,在使用者空間以分離的程式執行。
容器技術是實現作業系統虛擬化的一種途徑,可以讓您在資源受到隔離的程式中執行應用程式及其依賴關係。通過使用容器,我們可以輕鬆打包應用程式的程式碼、配置和依賴關係,將其變成容易使用的構建塊,從而實現環境一致性、運營效率、開發人員生產力和版本控制等諸多目標。容器可以幫助保證應用程式快速、可靠、一致地部署,其間不受部署環境的影響。容器還賦予我們對資源更多的精細化控制能力,讓我們的基礎設施效率更高。通過下面這幅圖我們可以很直觀的反映出這兩者的區別所在。
Docker 屬於 Linux 容器的一種封裝,提供簡單易用的容器使用介面。它是目前最流行的
Linux
容器解決方案。
而
Linux
容器是
Linux
發展出了另一種虛擬化技術,簡單來講,
Linux
容器不是模擬一個完整的作業系統,而是對程式進行隔離,相當於是在正常程式的外面套了一個保護層。對於容器裡面的程式來說,它接觸到的各種資源都是虛擬的,從而實現與底層系統的隔離。
Docker
將應用程式與該程式的依賴,打包在一個檔案裡面。執行這個檔案,就會生成一個虛擬容器。程式在這個虛擬容器裡執行,就好像在真實的物理機上執行一樣。有了
Docker
,就不用擔心環境問題。
總體來說,
Docker
的介面相當簡單,使用者可以方便地建立和使用容器,把自己的應用放入容器。容器還可以進行版本管理、複製、分享、修改,就像管理普通的程式碼一樣。
Docker的優勢
Docker相比於傳統虛擬化方式具有更多的優勢:
-
docker
啟動快速屬於秒級別。虛擬機器通常需要幾分鐘去啟動 -
docker
需要的資源更少,docker
在作業系統級別進行虛擬化,docker
容器和核心互動,幾乎沒有效能損耗,效能優於通過Hypervisor
層與核心層的虛擬化 -
docker
更輕量,docker
的架構可以共用一個核心與共享應用程式庫,所佔記憶體極小。同樣的硬體環境,Docker
執行的映象數遠多於虛擬機器數量,對系統的利用率非常高 - 與虛擬機器相比,
docker
隔離性更弱,docker
屬於程式之間的隔離,虛擬機器可實現系統級別隔離 - 安全性:
docker
的安全性也更弱。Docker
的租戶root
和宿主機root
等同,一旦容器內的使用者從普通使用者許可權提升為root許可權,它就直接具備了宿主機的root許可權,進而可進行無限制的操作。虛擬機器租戶root
許可權和宿主機的root
虛擬機器許可權是分離的,並且虛擬機器利用如Intel
的VT-d
和VT-x
的ring-1
硬體隔離技術,這種隔離技術可以防止虛擬機器突破和彼此互動,而容器至今還沒有任何形式的硬體隔離,這使得容器容易受到攻擊 - 可管理性:
docker
的集中化管理工具還不算成熟。各種虛擬化技術都有成熟的管理工具,例如VMware vCenter
提供完備的虛擬機器管理能力 - 高可用和可恢復性:
docker
對業務的高可用支援是通過快速重新部署實現的。虛擬化具備負載均衡,高可用,容錯,遷移和資料保護等經過生產實踐檢驗的成熟保障機制,VMware
可承諾虛擬機器99.999%
高可用,保證業務連續性 - 快速建立、刪除:虛擬化建立是分鐘級別的,
Docker
容器建立是秒級別的,Docker
的快速迭代性,決定了無論是開發、測試、部署都可以節約大量時間 - 交付、部署:虛擬機器可以通過映象實現環境交付的一致性,但映象分發無法體系化。
Docker
在Dockerfile
中記錄了容器構建過程,可在叢集中實現快速分發和快速部署
我們可以從下面這張表格很清楚地看到容器相比於傳統虛擬機器的特性的優勢所在:
特性 | 容器 | 虛擬機器 |
---|---|---|
啟動 | 秒級 | 分鐘級 |
硬碟使用 | 一般為MB | 一般為GB |
效能 | 接近原生 | 弱於 |
系統支援量 | 單機支援上千個容器 | 一般是幾十個 |
Docker的三個基本概念
從上圖我們可以看到,
Docker
中包括三個基本的概念:
-
Image
(映象) -
Container
(容器) -
Repository
(倉庫)
映象是
Docker
執行容器的前提,倉庫是存放映象的場所,可見映象更是
Docker
的核心。
Image (映象)
那麼映象到底是什麼呢?
Docker
映象可以看作是一個特殊的檔案系統,除了提供容器執行時所需的程式、庫、資源、配置等檔案外,還包含了一些為執行時準備的一些配置引數(如匿名卷、環境變數、使用者等)。映象不包含任何動態資料,其內容在構建之後也不會被改變。
映象
(Image)
就是一堆只讀層
(read-only layer)
的統一視角,也許這個定義有些難以理解,下面的這張圖能夠幫助讀者理解映象的定義。
從左邊我們看到了多個只讀層,它們重疊在一起。除了最下面一層,其它層都會有一個指標指向下一層。這些層是
Docker
內部的實現細節,並且能夠在主機的檔案系統上訪問到。統一檔案系統
(union file system)
技術能夠將不同的層整合成一個檔案系統,為這些層提供了一個統一的視角,這樣就隱藏了多層的存在,在使用者的角度看來,只存在一個檔案系統。我們可以在圖片的右邊看到這個視角的形式。
Container (容器)
容器
(container)
的定義和映象
(image)
幾乎一模一樣,也是一堆層的統一視角,唯一區別在於容器的最上面那一層是可讀可寫的。
由於容器的定義並沒有提及是否要執行容器,所以實際上,容器 = 映象 + 讀寫層。
Repository (倉庫)
Docker
倉庫是集中存放映象檔案的場所。映象構建完成後,可以很容易的在當前宿主上執行,但是, 如果需要在其它伺服器上使用這個映象,我們就需要一個集中的儲存、分發映象的服務,
Docker Registry
(倉庫註冊伺服器)就是這樣的服務。有時候會把倉庫
(Repository)
和倉庫註冊伺服器
(Registry)
混為一談,並不嚴格區分。
Docker
倉庫的概念跟
Git
類似,註冊伺服器可以理解為
GitHub
這樣的託管服務。實際上,一個
Docker Registry
中可以包含多個倉庫
(Repository)
,每個倉庫可以包含多個標籤
(Tag)
,每個標籤對應著一個映象。所以說,映象倉庫是
Docker
用來集中存放映象檔案的地方類似於我們之前常用的程式碼倉庫。
通常,
一個倉庫會包含同一個軟體不同版本的映象,而
標籤就常用於對應該軟體的各個版本 。我們可以通過
<倉庫名>:<標籤>
的格式來指定具體是這個軟體哪個版本的映象。如果不給出標籤,將以
latest
作為預設標籤.。
倉庫又可以分為兩種形式:
-
public
(公有倉庫) -
private
(私有倉庫)
Docker Registry
公有倉庫是開放給使用者使用、允許使用者管理映象的
Registry
服務。一般這類公開服務允許使用者免費上傳、下載公開的映象,並可能提供收費服務供使用者管理私有映象。
除了使用公開服務外,使用者還可以在本地搭建私有
Docker Registry
。
Docker
官方提供了
Docker Registry
映象,可以直接使用做為私有
Registry
服務。當使用者建立了自己的映象之後就可以使用
push
命令將它上傳到公有或者私有倉庫,這樣下次在另外一臺機器上使用這個映象時候,只需要從倉庫上
pull
下來就可以了。
我們主要把
Docker
的一些常見概念如
Image
,
Container
,
Repository
做了詳細的闡述,也從傳統虛擬化方式的角度闡述了
docker
的優勢,我們從下圖可以直觀地看到
Docker
的架構:
Docker
使用
C/S
結構,即
客戶端/伺服器體系結構。
Docker
客戶端與
Docker
伺服器進行互動,Docker服務端負責構建、執行和分發
Docker
映象。
Docker
客戶端和服務端可以執行在一臺機器上,也可以通過
RESTful
、
stock
或網路介面與遠端
Docker
服務端進行通訊。
這張圖展示了
Docker
客戶端、服務端和
Docker
倉庫(即
Docker Hub
和
Docker Cloud
),預設情況下
Docker
會在
Docker
中央倉庫尋找映象檔案,這種利用倉庫管理映象的設計理念類似於
Git
,當然這個倉庫是可以通過修改配置來指定的,甚至我們可以建立我們自己的私有倉庫。
Docker的安裝和使用
Docker
的安裝和使用有一些前提條件,主要體現在體系架構和核心的支援上。對於體系架構,除了
Docker
一開始就支援的
X86-64
,其他體系架構的支援則一直在不斷地完善和推進中。
Docker
分為
CE
和
EE
兩大版本。
CE
即社群版(免費,支援週期
7
個月),
EE
即企業版,強調安全,付費使用,支援週期
24
個月。
我們在安裝前可以參看官方文件獲取最新的
Docker
支援情況,官方文件在這裡:
https://docs.docker.com/install/
Docker
對於核心支援的功能,即核心的配置選項也有一定的要求(比如必須開啟
Cgroup
和
Namespace
相關選項,以及其他的網路和儲存驅動等),
Docker
原始碼中提供了一個檢測指令碼來檢測和指導核心的配置,指令碼連結在這裡:
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
發行版:https://docs.docker.com/install/linux/docker-ce/binaries/
這裡我們以
CentOS7
作為本文的演示。
環境準備
- 阿里雲伺服器(1核2G,1M頻寬)
- CentOS 7.4 64位
由於
Docker-CE
支援
64
位版本的
CentOS7
,並且要求核心版本不低於
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
我們執行以下安裝命令去安裝依賴包:
$ sudo yum install -y yum-utils \device-mapper-persistent-data \lvm2
這裡我事先已經安裝過了,所以提示我已經安裝了最新版本
安裝Docker
Docker
軟體包已經包括在預設的
CentOS-Extras
軟體源裡。因此想要安裝
docker
,只需要執行下面的
yum
命令
$ sudo yum install docker
當然在測試或開發環境中
Docker
官方為了簡化安裝流程,提供了一套便捷的安裝指令碼,
CentOS
系統上可以使用這套指令碼安裝:
curl -fsSL get.docker.com -o get-docker.shsh get-docker.sh
具體可以參看
docker-install
的指令碼:
https://github.com/docker/docker-install
執行這個命令後,指令碼就會自動的將一切準備工作做好,並且把
Docker CE
的
Edge
版本安裝在系統中。
安裝完成後,執行下面的命令,驗證是否安裝成功:
docker versionordocker info
返回docker的版本相關資訊,證明
docker
安裝成功
啟動Docker-CE
$ sudo systemctl enable docker$ sudo systemctl start docker
Docker的簡單運用---Hello World
由於伺服器日常崩潰了,
docker
出了點問題,所以以下案例的演示是基於
Kali Linux
環境下進行的。
我們通過最簡單的
image
檔案
hello world
,感受一下
Docker
的魅力吧!
我們直接執行下面的命令,將名為
hello-world
的
image
檔案從倉庫抓取到本地。
docker pull library/hello-world
docker pull images
是抓取
image
檔案,
library/hello-world
是
image
檔案在倉庫裡面的位置,其中
library
是
image
檔案所在的組,
hello-world
是
image
檔案的名字。
抓取成功以後,就可以在本機看到這個
image
檔案了。
docker images
我們可以看到如下結果:
現在,我們可以執行
hello-world
這個
image
檔案
docker run hello-world
我們可以看到如下結果:
輸出這段提示以後,
hello world
就會停止執行,容器自動終止。有些容器不會自動終止,因為提供的是服務,比如Mysql映象等。
是不是很
easy
呢?我們從上面可以看出,
docker
的功能是十分強大的,除此之外,我們還可以拉去一些
Ubuntu
,
Apache
等映象,在未來的教程中我們將會一一提到。
Docker
提供了一套簡單實用的命令來建立和更新映象,我們可以通過網路直接下載一個已經建立好了的應用映象,並通過
Docker RUN
命令就可以直接使用。當映象通過
RUN
命令執行成功後,這個執行的映象就是一個
Docker
容器啦,容器可以理解為一個輕量級的沙箱,
Docker
利用容器來執行和隔離應用,容器是可以被啟動、停止、刪除的,這並不會影響
Docker
映象。
我們可以看看下面這幅圖:
Docker
客戶端是
Docker
使用者與
Docker
互動的主要方式。當您使用
docker
命令列執行命令時,
Docker
客戶端將這些命令傳送給伺服器端,服務端將執行這些命令。
docker
命令使用
docker API
。
Docker
客戶端可以與多個服務端進行通訊。
我們將剖析一下
Docker
容器是如何工作的,學習好Docker容器工作的原理,我們就可以自己去管理我們的容器了。
Docker架構
在上面的學習中,我們簡單地講解了Docker的基本架構。瞭解到了
Docker
使用的是
C/S
結構,即
客戶端/伺服器體系結構。明白了
Docker
客戶端與
Docker
伺服器進行互動時,
Docker
服務端負責構建、執行和分發
Docker
映象。 也知道了
Docker
客戶端和服務端可以執行在一臺機器上,可以通過
RESTful
、
stock
或網路介面與遠端
Docker
服務端進行通訊。
我們從下圖可以很直觀的瞭解到Docker的架構:
Docker
的核心元件包括:
- Docker Client
- Docker daemon
- Docker Image
- Docker Registry
- Docker Container
Docker
採用的是
Client/Server
架構。客戶端向伺服器傳送請求,伺服器負責構建、執行和分發容器。客戶端和伺服器可以執行在同一個
Host
上,客戶端也可以通過
socket
或
REST API
與遠端的伺服器通訊。可能很多朋友暫時不太理解一些東西,比如
REST API
是什麼東西等,不過沒關係,在後面的文章中會一一給大家講解清楚。
Docker Client
Docker Client
,也稱
Docker
客戶端。它其實就是
Docker
提供命令列介面
(CLI)
工具,是許多
Docker
使用者與
Docker
進行互動的主要方式。客戶端可以構建,執行和停止應用程式,還可以遠端與
Docker_Host
進行互動。最常用的
Docker
客戶端就是
docker
命令,我們可以通過
docker
命令很方便地在
host
上構建和執行
docker
容器。
Docker daemon
Docker daemon
是伺服器元件,以
Linux
後臺服務的方式執行,是
Docker
最核心的後臺程式,我們也把它稱為守護程式。它負責響應來自
Docker Client
的請求,然後將這些請求翻譯成系統呼叫完成容器管理操作。該程式會在後臺啟動一個
API Server
,負責接收由
Docker Client
傳送的請求,接收到的請求將通過
Docker daemon
內部的一個路由分發排程,由具體的函式來執行請求。
我們大致可以將其分為以下三部分:
- Docker Server
- Engine
- Job
Docker Daemon的架構如下所示:
Docker Daemon
可以認為是通過
Docker Server
模組接受
Docker Client
的請求,並在
Engine
中處理請求,然後根據請求型別,建立出指定的
Job
並執行。
Docker Daemon
執行在
Docker host
上,負責建立、執行、監控容器,構建、儲存映象。
執行過程的作用有以下幾種可能:
- 向
Docker Registry
獲取映象 - 通過
graphdriver
執行容器映象的本地化操作 - 通過
networkdriver
執行容器網路環境的配置 - 通過
execdriver
執行容器內部執行的執行工作
由於
Docker Daemon
和
Docker Client
的啟動都是通過可執行檔案
docker
來完成的,因此兩者的啟動流程非常相似。
Docker
可執行檔案執行時,執行程式碼通過不同的命令列
flag
引數,區分兩者,並最終執行兩者各自相應的部分。
啟動
Docker Daemon
時,一般可以使用以下命令來完成
docker --daemon = truedocker –ddocker –d = true
再由
docker
的
main()
函式來解析以上命令的相應
flag
引數,並最終完成
Docker Daemon
的啟動。
下圖可以很直觀地看到
Docker Daemon
的啟動流程:
預設配置下,
Docker daemon
只能響應來自本地
Host
的客戶端請求。如果要允許遠端客戶端請求,需要在配置檔案中開啟
TCP
監聽。我們可以照著如下步驟進行配置:
1、編輯配置檔案
/etc/systemd/system/multi-user.target.wants/docker.service
,在環境變數
ExecStart
後面新增
-H tcp://0.0.0.0
,允許來自任意 IP 的客戶端連線。
2、重啟
Docker daemon
systemctl daemon-reloadsystemctl restart docker.service
3、我們通過以下命令即可實現與遠端伺服器通訊
docker -H 伺服器IP地址 info
-H
是用來指定伺服器主機,
info
子命令用於檢視
Docker
伺服器的資訊
Docker Image
Docker
映象可以看作是一個特殊的檔案系統,除了提供容器執行時所需的程式、庫、資源、配置等檔案外,還包含了一些為執行時準備的一些配置引數(如匿名卷、環境變數、使用者等)。映象不包含任何動態資料,其內容在構建之後也不會被改變。我們可將
Docker
映象看成只讀模板,通過它可以建立
Docker
容器。
映象有多種生成方法:
- 從無到有開始建立映象
- 下載並使用別人建立好的現成的映象
- 在現有映象上建立新的映象
我們可以將映象的內容和建立步驟描述在一個文字檔案中,這個檔案被稱作
Dockerfile
,通過執行
docker build <docker-file>
命令可以構建出 Docker 映象,在後續的教程中,我們會用一篇專門討論這個問題。
Docker Registry
Docker registry
是儲存
docker image
的倉庫,它在
docker
生態環境中的位置如下圖所示:
執行
docker push
、
docker pull
、
docker search
時,實際上是通過
docker daemon
與
docker registry
通訊。
Docker Container
Docker
容器就是
Docker
映象的執行例項,是真正執行專案程式、消耗系統資源、提供服務的地方。
Docker Container
提供了系統硬體環境,我們可以使用
Docker Images
這些製作好的系統盤,再加上我們所編寫好的專案程式碼,
run
一下就可以提供服務啦。
Docker元件是如何協作執行容器
看到這裡,我相信各位讀者朋友們應該已經對Docker基礎架構已經熟悉的差不多了,我們還記得執行的第一個容器嗎?現在我們再通過hello-world這個例子來體會一下
Docker
各個元件是如何協作的。
容器啟動過程如下:
-
Docker
客戶端執行docker run
命令 -
Docker daemon
發現本地沒有hello-world
映象 -
daemon
從Docker Hub
下載映象 - 下載完成,映象
hello-world
被儲存到本地 -
Docker daemon
啟動容器
具體過程可以看如下這幅演示圖:
我們可以通過
docker images
可以檢視到
hello-world
已經下載到本地
我們可以通過
docker ps
或者
docker container ls
顯示正在執行的容器,我們可以看到,
hello-world
在輸出提示資訊以後就會停止執行,容器自動終止,所以我們在檢視的時候沒有發現有容器在執行。
我們把
Docker
容器的工作流程剖析的十分清楚了,我們大體可以知道
Docker
元件協作執行容器可以分為以下幾個過程:
-
Docker
客戶端執行docker run
命令 -
Docker daemon
發現本地沒有我們需要的映象 -
daemon
從Docker Hub
下載映象 - 下載完成後,映象被儲存到本地
-
Docker daemon
啟動容器
瞭解了這些過程以後,我們再來理解這些命令就不會覺得很突兀了,下面我來給大家講講
Docker
常用的一些命令操作吧。
Docker常用命令
我們可以通過
docker -h
去檢視命令的詳細的幫助文件。在這裡我只會講一些平常日常比賽或者生活中我們可能會用的比較多的一些命令。
例如,我們需要拉取一個
docker
映象,我們可以用如下命令:
docker pull image_name
image_name
為映象的名稱,而如果我們想從
Docker Hub
上去下載某個映象,我們可以使用以下命令:
docker pull centos:latest
centos:lastest
是映象的名稱,
Docker daemon
發現本地沒有我們需要的映象,會自動去
Docker Hub
上去下載映象,下載完成後,該映象被預設儲存到
/var/lib/docker
目錄下。
接著我們如果想檢視下主機下存在多少映象,我們可以用如下命令:
docker images
我們要想知道當前有哪些容器在執行,我們可以用如下命令:
docker ps -a
-a
是檢視當前所有的容器,包括未執行的
我們該如何去對一個容器進行啟動,重啟和停止呢?我們可以用如下命令:
docker start container_name/container_iddocker restart container_name/container_iddocker stop container_name/container_id
這個時候我們如果想進入到這個容器中,我們可以使用
attach
命令:
docker attach container_name/container_id
那如果我們想執行這個容器中的映象的話,並且呼叫映象裡面的
bash
,我們可以使用如下命令:
docker run -t -i container_name/container_id /bin/bash
那如果這個時候,我們想刪除指定映象的話,由於
image
被某個
container
引用(拿來執行),如果不將這個引用的
container
銷燬(刪除),那
image
肯定是不能被刪除。我們首先得先去停止這個容器:
docker psdocker stop container_name/container_id
然後我們用如下命令去刪除這個容器:
docker rm container_name/container_id
然後這個時候我們再去刪除這個映象:
docker rmi image_name
此時,常用的
Docker
相關的命令就講到這裡為止了,我們在後續的文章中還會反覆地提到這些命令。
Dockerfile是什麼
前面我們已經提到了
Docker
的一些基本概念。以
CTF
選手的角度來看,我們可以去使用
Dockerfile
定義映象,依賴映象來執行容器,可以去模擬出一個真實的漏洞場景。因此毫無疑問的說,
Dockerfile
是映象和容器的關鍵,並且
Dockerfile
還可以很輕易的去定義映象內容,說了這麼多,那麼
Dockerfile
到底是個什麼東西呢?
Dockerfile
是自動構建
docker
映象的配置檔案, 使用者可以使用
Dockerfile
快速建立自定義的映象。
Dockerfile
中的命令非常類似於
linux
下的
shell
命令。
我們可以通過下面這幅圖來直觀地感受下 Docker 映象、容器和 Dockerfile 三者之間的關係。
我們從上圖中可以看到,
Dockerfile
可以自定義映象,通過
Docker
命令去執行映象,從而達到啟動容器的目的。
Dockerfile
是由一行行命令語句組成,並且支援已
#
開頭的註釋行。
一般來說,我們可以將
Dockerfile
分為四個部分:
-
基礎映象(父映象)資訊指令
FROM
-
維護者資訊指令
MAINTAINER
-
映象操作指令
RUN
、EVN
、ADD
和WORKDIR
等 -
容器啟動指令
CMD
、ENTRYPOINT
和USER
等
下面是一段簡單的Dockerfile的例子:
FROM python:2.7MAINTAINER Angel_Kitty <angelkitty6698@gmail.com>COPY . /appWORKDIR /appRUN pip install -r requirements.txtEXPOSE 5000ENTRYPOINT ["python"]CMD ["app.py"]
我們可以分析一下上面這個過程:
- 1、從
Docker Hub
上pull
下python 2.7
的基礎映象 - 2、顯示維護者的資訊
- 3、
copy
當前目錄到容器中的/app
目錄下 複製本地主機的<src>
(Dockerfile
所在目錄的相對路徑)到容器裡<dest>
- 4、指定工作路徑為
/app
- 5、安裝依賴包
- 6、暴露
5000
埠 - 7、啟動
app
這個例子是啟動一個
python flask app
的
Dockerfile
(
flask
是
python
的一個輕量的
web
框架),相信大家從這個例子中能夠稍微理解了Dockfile的組成以及指令的編寫過程。
Dockerfile常用的指令
根據上面的例子,我們已經差不多知道了Dockerfile的組成以及指令的編寫過程,我們再來理解一下這些常用命令就會得心應手了。
由於
Dockerfile
中所有的命令都是以下格式:
INSTRUCTION argument
,指令
(INSTRUCTION)
不分大小寫,但是推薦大寫,和sql語句是不是很相似呢?下面我們正式來講解一下這些指令集吧。
FROM
FROM
是用於指定基礎的
images
,一般格式為
FROM <image>
or
FORM <image>:<tag>
,所有的
Dockerfile
都用該以
FROM
開頭,
FROM
命令指明
Dockerfile
所建立的映象檔案以什麼映象為基礎,
FROM
以後的所有指令都會在
FROM
的基礎上進行建立映象。可以在同一個
Dockerfile
中多次使用
FROM
命令用於建立多個映象。比如我們要指定
python 2.7
的基礎映象,我們可以像如下寫法一樣:
FROM python:2.7
MAINTAINER
MAINTAINER 是用於指定映象建立者和聯絡方式,一般格式為
MAINTAINER <name>
。這裡我設定成我的
ID
和郵箱:
MAINTAINER Angel_Kitty <angelkitty6698@gmail.com>
COPY
COPY
是用於複製本地主機的
<src>
(為 Dockerfile 所在目錄的相對路徑)到容器中的
<dest>
。
當使用本地目錄為源目錄時,推薦使用
COPY
。一般格式為
COPY <src><dest>
。例如我們要拷貝當前目錄到容器中的
/app
目錄下,我們可以這樣操作:
COPY . /app
WORKDIR
WORKDIR
用於配合
RUN
,
CMD
,
ENTRYPOINT
命令設定當前工作路徑。可以設定多次,如果是相對路徑,則相對前一個
WORKDIR
命令。預設路徑為
/
。一般格式為
WORKDIR /path/to/work/dir
。例如我們設定
/app
路徑,我們可以進行如下操作:
WORKDIR /app
RUN
RUN
用於容器內部執行命令。每個
RUN
命令相當於在原有的映象基礎上新增了一個改動層,原有的映象不會有變化。一般格式為
RUN <command>
。例如我們要安裝
python
依賴包,我們做法如下:
RUN pip install -r requirements.txt
EXPOSE
EXPOSE
命令用來指定對外開放的埠。一般格式為
EXPOSE <port> [<port>...]
例如上面那個例子,開放5000埠:
EXPOSE 5000
ENTRYPOINT
ENTRYPOINT
可以讓你的容器表現得像一個可執行程式一樣。一個
Dockerfile
中只能有一個
ENTRYPOINT
,如果有多個,則最後一個生效。
ENTRYPOINT
命令也有兩種格式:
-
ENTRYPOINT ["executable", "param1", "param2"]
:推薦使用的exec
形式 -
ENTRYPOINT command param1 param2
:shell
形式
例如下面這個,我們要將
python
映象變成可執行的程式,我們可以這樣去做:
ENTRYPOINT ["python"]
CMD
CMD
命令用於啟動容器時預設執行的命令,
CMD
命令可以包含可執行檔案,也可以不包含可執行檔案。不包含可執行檔案的情況下就要用
ENTRYPOINT
指定一個,然後
CMD
命令的引數就會作為
ENTRYPOINT
的引數。
CMD
命令有三種格式:
-
CMD ["executable","param1","param2"]
:推薦使用的exec
形式。 -
CMD ["param1","param2"]
:無可執行程式形式 -
CMD command param1 param2
:shell 形式。
一個
Dockerfile
中只能有一個
CMD
,如果有多個,則最後一個生效。而
CMD
的
shell
形式預設呼叫
/bin/sh -c
執行命令。
CMD
命令會被
Docker
命令列傳入的引數覆蓋:
docker run busybox /bin/echo Hello
Docker
會把
CMD
裡的命令覆蓋。
例如我們要啟動
/app
,我們可以用如下命令實現:
CMD ["app.py"]
當然還有一些其他的命令,我們在用到的時候再去一一講解一下。
構建Dockerfile
我們大體已經把Dockerfile的寫法講述完畢,我們可以自己動手寫一個例子:
mkdir static_webcd static_webtouch Dockerfile然後 vi Dockerfile 開始編輯該檔案輸入 i 開始編輯以下是我們構建的Dockerfile內容``````````FROM nginxMAINTAINER Angel_Kitty <angelkitty6698@gmail.com>RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html``````````編輯完後 按 esc 退出編輯然後 :wq 寫入 退出
我們在
Dockerfile
檔案所在目錄執行:
docker build -t angelkitty/nginx_web:v1 .
我們解釋一下,
-t
是為新映象設定倉庫和名稱,其中
angelkitty
為倉庫名,
nginx_web
為映象名,
:v1
為標籤(不新增為預設
latest
)
我們構建完成之後,使用
docker images
命令檢視所有映象,如果存在
REPOSITORY
為
nginx
和
TAG
是
v1
的資訊,就表示構建成功。
接下來使用
docker run
命令來啟動容器
docker run --name nginx_web -d -p 8080:80 angelkitty/nginx_web:v1
這條命令會用 nginx 映象啟動一個容器,命名為
nginx_web
,並且對映了 8080 埠,這樣我們可以用瀏覽器去訪問這個
nginx
伺服器:
http://localhost:8080/
或者 http://本機的IP地址:8080/,頁面返回資訊:
這樣一個簡單使用
Dockerfile
構建映象,執行容器的示例就完成了!
參考文獻
About Me
........................................................................................................................ ● 本文作者:小麥苗,部分內容整理自網路,若有侵權請聯絡小麥苗刪除 ● 本文在itpub、部落格園、CSDN和個人微 信公眾號( xiaomaimiaolhr)上有同步更新 ● 本文itpub地址: http://blog.itpub.net/26736162 ● 本文部落格園地址: http://www.cnblogs.com/lhrbest ● 本文CSDN地址: https://blog.csdn.net/lihuarongaini ● 本文pdf版、個人簡介及小麥苗雲盤地址: http://blog.itpub.net/26736162/viewspace-1624453/ ● 資料庫筆試面試題庫及解答: http://blog.itpub.net/26736162/viewspace-2134706/ ● DBA寶典今日頭條號地址: http://www.toutiao.com/c/user/6401772890/#mid=1564638659405826 ........................................................................................................................ ● QQ群號: 230161599 、618766405 ● 微 信群:可加我微 信,我拉大家進群,非誠勿擾 ● 聯絡我請加QQ好友 ( 646634621 ),註明新增緣由 ● 於 2020-03-01 06:00 ~ 2020-03-31 24:00 在西安完成 ● 最新修改時間:2020-03-01 06:00 ~ 2020-03-31 24:00 ● 文章內容來源於小麥苗的學習筆記,部分整理自網路,若有侵權或不當之處還請諒解 ● 版權所有,歡迎分享本文,轉載請保留出處 ........................................................................................................................ ● 小麥苗的微店: https://weidian.com/s/793741433?wfr=c&ifr=shopdetail ● 小麥苗出版的資料庫類叢書: http://blog.itpub.net/26736162/viewspace-2142121/ ● 小麥苗OCP、OCM、高可用網路班: http://blog.itpub.net/26736162/viewspace-2148098/ ● 小麥苗騰訊課堂主頁: https://lhr.ke.qq.com/ ........................................................................................................................ 使用 微 信客戶端掃描下面的二維碼來關注小麥苗的微 信公眾號( xiaomaimiaolhr)及QQ群(DBA寶典)、新增小麥苗微 信, 學習最實用的資料庫技術。
........................................................................................................................ |
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26736162/viewspace-2679884/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- docker入門知識總結Docker
- HTTP入門知識HTTP
- 知識圖譜入門——知識表示與知識建模
- python入門基本知識Python
- Hibernate的入門知識
- linux路由知識入門Linux路由
- Blender入門知識整理
- Python入門必知的知識點!Python基礎入門Python
- JavaScript 基礎知識入門JavaScript
- HTTP協議_入門知識HTTP協議
- React入門知識點整理React
- 知識圖譜入門2
- Flutter2 入門知識Flutter
- 南京某大學入門知識
- docker 入門到實戰 1.初識 dockerDocker
- sql入門基礎知識分享SQL
- git 入門教程之知識速查Git
- Java入門基礎知識點Java
- Python基礎知識入門(二)Python
- Python入門基礎知識(二)Python
- Python入門知識點彙總Python
- 急速入門前端編碼知識前端
- Java基礎知識入門-JDKJavaJDK
- Dubbo基礎入門知識點
- Java入門知識_Java初學者須知Java
- Docker從入門到精通(一)——初識Docker
- gitbook 入門教程之前置知識Git
- Python入門基礎知識例項,Python
- python入門知識思維導圖Python
- Python入門之基礎知識(一)Python
- 【知識點】圖與圖論入門圖論
- 如何快速掌握Javascript入門小知識JavaScript
- Spring入門系列:淺析知識點Spring
- JavaScript入門①-基礎知識築基JavaScript
- 區塊鏈入門知識介紹!區塊鏈
- Docker 基礎知識 - Docker 概述Docker
- Docker筆記1——入門(初識+搭建+使用)Docker筆記
- Docker容器從一知半解到入門Docker