初探Docker

這是我在某招聘網(wǎng)站上看到的招聘 Java開(kāi)發(fā)工程師 的招聘要求歇竟,其中有一條熟悉 docker 成為了你快速入職的加分項(xiàng),由此可見(jiàn)熟悉 docker 在互聯(lián)網(wǎng)公司的地位之重要滔吠。

當(dāng)然對(duì)于我們 CTF選手 而言纲菌,熟悉 docker 可以快速搭建 CTF環(huán)境 ,完美地還原比賽真實(shí)漏洞的場(chǎng)景疮绷,幫助我們快速提升自己翰舌。

市面上已經(jīng)有很多優(yōu)秀的教程,但是很多原理性的東西冬骚,筆者認(rèn)為那些教程對(duì)初學(xué)者而言還是很難理解椅贱,感覺(jué)沒(méi)有說(shuō)清楚(筆者自己都覺(jué)得挺懵逼的)懂算,為了讓初學(xué)者少走彎路,我將以我的學(xué)習(xí)經(jīng)歷以及作為一個(gè) CTF選手 的角度庇麦,編寫(xiě)此套教程计技,來(lái)帶大家去了解并熟練運(yùn)用 docker ,祝愿各位讀者朋友們學(xué)完此套教程后山橄,在未來(lái)企業(yè)面試中能夠多一項(xiàng)加分的籌碼垮媒,能夠幫助到大家,我覺(jué)得就很值了航棱。

既然說(shuō)了這么多睡雇, docker 到底是個(gè)什么東西呢?

我們?cè)诶斫?docker 之前饮醇,首先我們得先區(qū)分清楚兩個(gè)概念它抱,容器虛擬機(jī)

可能很多讀者朋友都用過(guò)虛擬機(jī)驳阎,而對(duì)容器這個(gè)概念比較的陌生抗愁。

我們用的傳統(tǒng)虛擬機(jī)如 VMware 馁蒂, VisualBox 之類的需要模擬整臺(tái)機(jī)器包括硬件呵晚,每臺(tái)虛擬機(jī)都需要有自己的操作系統(tǒng),虛擬機(jī)一旦被開(kāi)啟沫屡,預(yù)分配給它的資源將全部被占用饵隙。每一臺(tái)虛擬機(jī)包括應(yīng)用,必要的二進(jìn)制和庫(kù)沮脖,以及一個(gè)完整的用戶操作系統(tǒng)金矛。

而容器技術(shù)是和我們的宿主機(jī)共享硬件資源及操作系統(tǒng),可以實(shí)現(xiàn)資源的動(dòng)態(tài)分配勺届。容器包含應(yīng)用和其所有的依賴包驶俊,但是與其他容器共享內(nèi)核。容器在宿主機(jī)操作系統(tǒng)中免姿,在用戶空間以分離的進(jìn)程運(yùn)行饼酿。

容器技術(shù)是實(shí)現(xiàn)操作系統(tǒng)虛擬化的一種途徑,可以讓您在資源受到隔離的進(jìn)程中運(yùn)行應(yīng)用程序及其依賴關(guān)系胚膊。通過(guò)使用容器故俐,我們可以輕松打包應(yīng)用程序的代碼、配置和依賴關(guān)系紊婉,將其變成容易使用的構(gòu)建塊药版,從而實(shí)現(xiàn)環(huán)境一致性、運(yùn)營(yíng)效率喻犁、開(kāi)發(fā)人員生產(chǎn)力和版本控制等諸多目標(biāo)槽片。容器可以幫助保證應(yīng)用程序快速何缓、可靠、一致地部署筐乳,其間不受部署環(huán)境的影響歌殃。容器還賦予我們對(duì)資源更多的精細(xì)化控制能力,讓我們的基礎(chǔ)設(shè)施效率更高蝙云。通過(guò)下面這幅圖我們可以很直觀的反映出這兩者的區(qū)別所在氓皱。

image

Docker 屬于 Linux 容器的一種封裝,提供簡(jiǎn)單易用的容器使用接口勃刨。它是目前最流行的 Linux 容器解決方案波材。

Linux 容器是 Linux 發(fā)展出了另一種虛擬化技術(shù),簡(jiǎn)單來(lái)講身隐, Linux 容器不是模擬一個(gè)完整的操作系統(tǒng)廷区,而是對(duì)進(jìn)程進(jìn)行隔離,相當(dāng)于是在正常進(jìn)程的外面套了一個(gè)保護(hù)層贾铝。對(duì)于容器里面的進(jìn)程來(lái)說(shuō)隙轻,它接觸到的各種資源都是虛擬的,從而實(shí)現(xiàn)與底層系統(tǒng)的隔離垢揩。

Docker 將應(yīng)用程序與該程序的依賴玖绿,打包在一個(gè)文件里面。運(yùn)行這個(gè)文件叁巨,就會(huì)生成一個(gè)虛擬容器斑匪。程序在這個(gè)虛擬容器里運(yùn)行,就好像在真實(shí)的物理機(jī)上運(yùn)行一樣锋勺。有了 Docker 蚀瘸,就不用擔(dān)心環(huán)境問(wèn)題。

總體來(lái)說(shuō)庶橱, Docker 的接口相當(dāng)簡(jiǎn)單贮勃,用戶可以方便地創(chuàng)建和使用容器,把自己的應(yīng)用放入容器苏章。容器還可以進(jìn)行版本管理寂嘉、復(fù)制、分享布近、修改垫释,就像管理普通的代碼一樣。

Docker的優(yōu)勢(shì)

Docker相比于傳統(tǒng)虛擬化方式具有更多的優(yōu)勢(shì):

  • docker 啟動(dòng)快速屬于秒級(jí)別撑瞧。虛擬機(jī)通常需要幾分鐘去啟動(dòng)
  • docker 需要的資源更少棵譬, docker 在操作系統(tǒng)級(jí)別進(jìn)行虛擬化, docker 容器和內(nèi)核交互预伺,幾乎沒(méi)有性能損耗订咸,性能優(yōu)于通過(guò) Hypervisor 層與內(nèi)核層的虛擬化
  • docker 更輕量曼尊, docker 的架構(gòu)可以共用一個(gè)內(nèi)核與共享應(yīng)用程序庫(kù),所占內(nèi)存極小脏嚷。同樣的硬件環(huán)境骆撇, Docker 運(yùn)行的鏡像數(shù)遠(yuǎn)多于虛擬機(jī)數(shù)量,對(duì)系統(tǒng)的利用率非常高
  • 與虛擬機(jī)相比父叙, docker 隔離性更弱神郊, docker 屬于進(jìn)程之間的隔離,虛擬機(jī)可實(shí)現(xiàn)系統(tǒng)級(jí)別隔離
  • 安全性: docker 的安全性也更弱趾唱。 Docker 的租戶 root 和宿主機(jī) root 等同涌乳,一旦容器內(nèi)的用戶從普通用戶權(quán)限提升為root權(quán)限,它就直接具備了宿主機(jī)的root權(quán)限甜癞,進(jìn)而可進(jìn)行無(wú)限制的操作夕晓。虛擬機(jī)租戶 root 權(quán)限和宿主機(jī)的 root 虛擬機(jī)權(quán)限是分離的,并且虛擬機(jī)利用如 IntelVT-dVT-xring-1 硬件隔離技術(shù)悠咱,這種隔離技術(shù)可以防止虛擬機(jī)突破和彼此交互蒸辆,而容器至今還沒(méi)有任何形式的硬件隔離,這使得容器容易受到攻擊
  • 可管理性: docker 的集中化管理工具還不算成熟析既。各種虛擬化技術(shù)都有成熟的管理工具躬贡,例如 VMware vCenter 提供完備的虛擬機(jī)管理能力
  • 高可用和可恢復(fù)性: docker 對(duì)業(yè)務(wù)的高可用支持是通過(guò)快速重新部署實(shí)現(xiàn)的。虛擬化具備負(fù)載均衡渡贾,高可用逗宜,容錯(cuò)雄右,遷移和數(shù)據(jù)保護(hù)等經(jīng)過(guò)生產(chǎn)實(shí)踐檢驗(yàn)的成熟保障機(jī)制空骚, VMware 可承諾虛擬機(jī) 99.999% 高可用,保證業(yè)務(wù)連續(xù)性
  • 快速創(chuàng)建擂仍、刪除:虛擬化創(chuàng)建是分鐘級(jí)別的囤屹, Docker 容器創(chuàng)建是秒級(jí)別的, Docker 的快速迭代性逢渔,決定了無(wú)論是開(kāi)發(fā)肋坚、測(cè)試、部署都可以節(jié)約大量時(shí)間
  • 交付肃廓、部署:虛擬機(jī)可以通過(guò)鏡像實(shí)現(xiàn)環(huán)境交付的一致性智厌,但鏡像分發(fā)無(wú)法體系化。 DockerDockerfile 中記錄了容器構(gòu)建過(guò)程盲赊,可在集群中實(shí)現(xiàn)快速分發(fā)和快速部署

我們可以從下面這張表格很清楚地看到容器相比于傳統(tǒng)虛擬機(jī)的特性的優(yōu)勢(shì)所在:

特性 容器 虛擬機(jī)
啟動(dòng) 秒級(jí) 分鐘級(jí)
硬盤(pán)使用 一般為MB 一般為GB
性能 接近原生 弱于
系統(tǒng)支持量 單機(jī)支持上千個(gè)容器 一般是幾十個(gè)

Docker的三個(gè)基本概念

image

從上圖我們可以看到铣鹏,Docker 中包括三個(gè)基本的概念:

  • Image(鏡像)
  • Container(容器)
  • Repository(倉(cāng)庫(kù))

鏡像是 Docker 運(yùn)行容器的前提,倉(cāng)庫(kù)是存放鏡像的場(chǎng)所哀蘑,可見(jiàn)鏡像更是 Docker 的核心诚卸。

Image (鏡像)

那么鏡像到底是什么呢葵第?

Docker 鏡像可以看作是一個(gè)特殊的文件系統(tǒng),除了提供容器運(yùn)行時(shí)所需的程序合溺、庫(kù)卒密、資源、配置等文件外棠赛,還包含了一些為運(yùn)行時(shí)準(zhǔn)備的一些配置參數(shù)(如匿名卷哮奇、環(huán)境變量、用戶等)睛约。鏡像不包含任何動(dòng)態(tài)數(shù)據(jù)屏镊,其內(nèi)容在構(gòu)建之后也不會(huì)被改變。

鏡像(Image)就是一堆只讀層(read-only layer)的統(tǒng)一視角痰腮,也許這個(gè)定義有些難以理解而芥,下面的這張圖能夠幫助讀者理解鏡像的定義。

image

從左邊我們看到了多個(gè)只讀層膀值,它們重疊在一起棍丐。除了最下面一層,其它層都會(huì)有一個(gè)指針指向下一層沧踏。這些層是Docker 內(nèi)部的實(shí)現(xiàn)細(xì)節(jié)歌逢,并且能夠在主機(jī)的文件系統(tǒng)上訪問(wèn)到。統(tǒng)一文件系統(tǒng) (union file system) 技術(shù)能夠?qū)⒉煌膶诱铣梢粋€(gè)文件系統(tǒng)翘狱,為這些層提供了一個(gè)統(tǒng)一的視角秘案,這樣就隱藏了多層的存在,在用戶的角度看來(lái)潦匈,只存在一個(gè)文件系統(tǒng)阱高。我們可以在圖片的右邊看到這個(gè)視角的形式。

Container (容器)

容器 (container) 的定義和鏡像 (image) 幾乎一模一樣茬缩,也是一堆層的統(tǒng)一視角赤惊,唯一區(qū)別在于容器的最上面那一層是可讀可寫(xiě)的。

image

由于容器的定義并沒(méi)有提及是否要運(yùn)行容器凰锡,所以實(shí)際上未舟,容器 = 鏡像 + 讀寫(xiě)層。

Repository (倉(cāng)庫(kù))

Docker 倉(cāng)庫(kù)是集中存放鏡像文件的場(chǎng)所掂为。鏡像構(gòu)建完成后裕膀,可以很容易的在當(dāng)前宿主上運(yùn)行,但是勇哗, 如果需要在其它服務(wù)器上使用這個(gè)鏡像昼扛,我們就需要一個(gè)集中的存儲(chǔ)、分發(fā)鏡像的服務(wù)智绸,Docker Registry (倉(cāng)庫(kù)注冊(cè)服務(wù)器)就是這樣的服務(wù)野揪。有時(shí)候會(huì)把倉(cāng)庫(kù) (Repository) 和倉(cāng)庫(kù)注冊(cè)服務(wù)器 (Registry) 混為一談访忿,并不嚴(yán)格區(qū)分。Docker 倉(cāng)庫(kù)的概念跟 Git 類似斯稳,注冊(cè)服務(wù)器可以理解為 GitHub 這樣的托管服務(wù)海铆。實(shí)際上,一個(gè) Docker Registry 中可以包含多個(gè)倉(cāng)庫(kù) (Repository) 挣惰,每個(gè)倉(cāng)庫(kù)可以包含多個(gè)標(biāo)簽 (Tag)卧斟,每個(gè)標(biāo)簽對(duì)應(yīng)著一個(gè)鏡像。所以說(shuō)憎茂,鏡像倉(cāng)庫(kù)是 Docker 用來(lái)集中存放鏡像文件的地方類似于我們之前常用的代碼倉(cāng)庫(kù)珍语。

通常,一個(gè)倉(cāng)庫(kù)會(huì)包含同一個(gè)軟件不同版本的鏡像竖幔,而標(biāo)簽就常用于對(duì)應(yīng)該軟件的各個(gè)版本 板乙。我們可以通過(guò)<倉(cāng)庫(kù)名>:<標(biāo)簽>的格式來(lái)指定具體是這個(gè)軟件哪個(gè)版本的鏡像坐搔。如果不給出標(biāo)簽拴事,將以 latest 作為默認(rèn)標(biāo)簽.。

倉(cāng)庫(kù)又可以分為兩種形式:

  • public(公有倉(cāng)庫(kù))
  • private(私有倉(cāng)庫(kù))

Docker Registry 公有倉(cāng)庫(kù)是開(kāi)放給用戶使用驱显、允許用戶管理鏡像的 Registry 服務(wù)馋评。一般這類公開(kāi)服務(wù)允許用戶免費(fèi)上傳放接、下載公開(kāi)的鏡像,并可能提供收費(fèi)服務(wù)供用戶管理私有鏡像留特。

除了使用公開(kāi)服務(wù)外纠脾,用戶還可以在本地搭建私有 Docker RegistryDocker 官方提供了 Docker Registry鏡像蜕青,可以直接使用做為私有 Registry 服務(wù)苟蹈。當(dāng)用戶創(chuàng)建了自己的鏡像之后就可以使用 push 命令將它上傳到公有或者私有倉(cāng)庫(kù),這樣下次在另外一臺(tái)機(jī)器上使用這個(gè)鏡像時(shí)候市咆,只需要從倉(cāng)庫(kù)上 pull 下來(lái)就可以了汉操。

我們主要把 Docker 的一些常見(jiàn)概念如 Image 再来, Container 蒙兰, Repository 做了詳細(xì)的闡述,也從傳統(tǒng)虛擬化方式的角度闡述了 docker 的優(yōu)勢(shì)芒篷,我們從下圖可以直觀地看到 Docker 的架構(gòu):

framework

Docker 使用 C/S 結(jié)構(gòu)搜变,即客戶端/服務(wù)器體系結(jié)構(gòu)。 Docker 客戶端與 Docker 服務(wù)器進(jìn)行交互针炉,Docker服務(wù)端負(fù)責(zé)構(gòu)建挠他、運(yùn)行和分發(fā) Docker 鏡像。 Docker 客戶端和服務(wù)端可以運(yùn)行在一臺(tái)機(jī)器上篡帕,也可以通過(guò) RESTful 殖侵、 stock 或網(wǎng)絡(luò)接口與遠(yuǎn)程 Docker 服務(wù)端進(jìn)行通信贸呢。

docker-framework

這張圖展示了 Docker 客戶端、服務(wù)端和 Docker 倉(cāng)庫(kù)(即 Docker HubDocker Cloud )拢军,默認(rèn)情況下Docker 會(huì)在 Docker 中央倉(cāng)庫(kù)尋找鏡像文件楞陷,這種利用倉(cāng)庫(kù)管理鏡像的設(shè)計(jì)理念類似于 Git ,當(dāng)然這個(gè)倉(cāng)庫(kù)是可以通過(guò)修改配置來(lái)指定的茉唉,甚至我們可以創(chuàng)建我們自己的私有倉(cāng)庫(kù)固蛾。

Docker的安裝和使用

Docker 的安裝和使用有一些前提條件,主要體現(xiàn)在體系架構(gòu)和內(nèi)核的支持上度陆。對(duì)于體系架構(gòu)艾凯,除了 Docker 一開(kāi)始就支持的 X86-64 ,其他體系架構(gòu)的支持則一直在不斷地完善和推進(jìn)中懂傀。

Docker 分為 CEEE 兩大版本趾诗。 CE 即社區(qū)版(免費(fèi),支持周期 7 個(gè)月)蹬蚁, EE 即企業(yè)版沧竟,強(qiáng)調(diào)安全,付費(fèi)使用缚忧,支持周期 24 個(gè)月悟泵。

我們?cè)诎惭b前可以參看官方文檔獲取最新的 Docker 支持情況,官方文檔在這里:

https://docs.docker.com/install/

Docker 對(duì)于內(nèi)核支持的功能闪水,即內(nèi)核的配置選項(xiàng)也有一定的要求(比如必須開(kāi)啟 CgroupNamespace 相關(guān)選項(xiàng)糕非,以及其他的網(wǎng)絡(luò)和存儲(chǔ)驅(qū)動(dòng)等), Docker 源碼中提供了一個(gè)檢測(cè)腳本來(lái)檢測(cè)和指導(dǎo)內(nèi)核的配置球榆,腳本鏈接在這里:

https://raw.githubusercontent.com/docker/docker/master/contrib/check-config.sh

在滿足前提條件后朽肥,安裝就變得非常的簡(jiǎn)單了。

Docker CE 的安裝請(qǐng)參考官方文檔:

這里我們以 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
image

我們執(zhí)行以下安裝命令去安裝依賴包:

$ sudo yum install -y yum-utils \           device-mapper-persistent-data \           lvm2

這里我事先已經(jīng)安裝過(guò)了每强,所以提示我已經(jīng)安裝了最新版本

image

安裝Docker

Docker 軟件包已經(jīng)包括在默認(rèn)的 CentOS-Extras 軟件源里始腾。因此想要安裝 docker,只需要運(yùn)行下面的 yum 命令

$ sudo yum install docker

當(dāng)然在測(cè)試或開(kāi)發(fā)環(huán)境中 Docker 官方為了簡(jiǎn)化安裝流程空执,提供了一套便捷的安裝腳本浪箭,CentOS 系統(tǒng)上可以使用這套腳本安裝:

curl -fsSL get.docker.com -o get-docker.shsh get-docker.sh

具體可以參看 docker-install 的腳本:

https://github.com/docker/docker-install

執(zhí)行這個(gè)命令后,腳本就會(huì)自動(dòng)的將一切準(zhǔn)備工作做好辨绊,并且把 Docker CEEdge 版本安裝在系統(tǒng)中奶栖。

安裝完成后,運(yùn)行下面的命令,驗(yàn)證是否安裝成功:

docker versionordocker info

返回docker的版本相關(guān)信息宣鄙,證明 docker 安裝成功

image

啟動(dòng)Docker-CE

$ sudo systemctl enable docker$ sudo systemctl start docker

Docker的簡(jiǎn)單運(yùn)用---Hello World

由于服務(wù)器日常崩潰了袍镀, docker 出了點(diǎn)問(wèn)題,所以以下案例的演示是基于 Kali Linux 環(huán)境下進(jìn)行的冻晤。

我們通過(guò)最簡(jiǎn)單的 image 文件 hello world流椒,感受一下 Docker 的魅力吧!

我們直接運(yùn)行下面的命令明也,將名為 hello-worldimage 文件從倉(cāng)庫(kù)抓取到本地宣虾。

docker pull library/hello-world

docker pull images 是抓取 image 文件, library/hello-worldimage 文件在倉(cāng)庫(kù)里面的位置温数,其中 libraryimage 文件所在的組绣硝, hello-worldimage 文件的名字。

image

抓取成功以后撑刺,就可以在本機(jī)看到這個(gè) image 文件了鹉胖。

docker images

我們可以看到如下結(jié)果:

image

現(xiàn)在,我們可以運(yùn)行 hello-world 這個(gè) image 文件

docker run hello-world

我們可以看到如下結(jié)果:

image

輸出這段提示以后够傍,hello world 就會(huì)停止運(yùn)行甫菠,容器自動(dòng)終止。有些容器不會(huì)自動(dòng)終止冕屯,因?yàn)樘峁┑氖欠?wù)寂诱,比如Mysql鏡像等。

是不是很 easy 呢安聘?我們從上面可以看出痰洒, docker 的功能是十分強(qiáng)大的,除此之外浴韭,我們還可以拉去一些 Ubuntu 丘喻, Apache 等鏡像,在未來(lái)的教程中我們將會(huì)一一提到念颈。

Docker 提供了一套簡(jiǎn)單實(shí)用的命令來(lái)創(chuàng)建和更新鏡像泉粉,我們可以通過(guò)網(wǎng)絡(luò)直接下載一個(gè)已經(jīng)創(chuàng)建好了的應(yīng)用鏡像,并通過(guò) Docker RUN 命令就可以直接使用榴芳。當(dāng)鏡像通過(guò) RUN 命令運(yùn)行成功后嗡靡,這個(gè)運(yùn)行的鏡像就是一個(gè) Docker 容器啦,容器可以理解為一個(gè)輕量級(jí)的沙箱翠语, Docker 利用容器來(lái)運(yùn)行和隔離應(yīng)用叽躯,容器是可以被啟動(dòng)、停止肌括、刪除的,這并不會(huì)影響 Docker 鏡像。

我們可以看看下面這幅圖:

image

Docker 客戶端是 Docker 用戶與 Docker 交互的主要方式谍夭。當(dāng)您使用 docker 命令行運(yùn)行命令時(shí)黑滴, Docker 客戶端將這些命令發(fā)送給服務(wù)器端,服務(wù)端將執(zhí)行這些命令紧索。 docker 命令使用 docker API 袁辈。 Docker 客戶端可以與多個(gè)服務(wù)端進(jìn)行通信。

我們將剖析一下 Docker 容器是如何工作的珠漂,學(xué)習(xí)好Docker容器工作的原理晚缩,我們就可以自己去管理我們的容器了。

Docker架構(gòu)

在上面的學(xué)習(xí)中媳危,我們簡(jiǎn)單地講解了Docker的基本架構(gòu)荞彼。了解到了Docker 使用的是 C/S 結(jié)構(gòu),即客戶端/服務(wù)器體系結(jié)構(gòu)待笑。明白了 Docker 客戶端與 Docker 服務(wù)器進(jìn)行交互時(shí)鸣皂, Docker 服務(wù)端負(fù)責(zé)構(gòu)建、運(yùn)行和分發(fā) Docker 鏡像暮蹂。 也知道了Docker 客戶端和服務(wù)端可以運(yùn)行在一臺(tái)機(jī)器上寞缝,可以通過(guò) RESTfulstock 或網(wǎng)絡(luò)接口與遠(yuǎn)程 Docker 服務(wù)端進(jìn)行通信仰泻。

我們從下圖可以很直觀的了解到Docker的架構(gòu):

image

Docker 的核心組件包括:

  1. Docker Client
  2. Docker daemon
  3. Docker Image
  4. Docker Registry
  5. Docker Container

Docker 采用的是 Client/Server 架構(gòu)荆陆。客戶端向服務(wù)器發(fā)送請(qǐng)求集侯,服務(wù)器負(fù)責(zé)構(gòu)建慎宾、運(yùn)行和分發(fā)容器∏诚ぃ客戶端和服務(wù)器可以運(yùn)行在同一個(gè) Host 上趟据,客戶端也可以通過(guò) socketREST API 與遠(yuǎn)程的服務(wù)器通信∈踅。可能很多朋友暫時(shí)不太理解一些東西汹碱,比如 REST API 是什么東西等,不過(guò)沒(méi)關(guān)系荞估,在后面的文章中會(huì)一一給大家講解清楚咳促。

Docker Client

Docker Client ,也稱 Docker 客戶端勘伺。它其實(shí)就是 Docker 提供命令行界面 (CLI) 工具跪腹,是許多 Docker 用戶與 Docker 進(jìn)行交互的主要方式》勺恚客戶端可以構(gòu)建冲茸,運(yùn)行和停止應(yīng)用程序,還可以遠(yuǎn)程與Docker_Host進(jìn)行交互。最常用的 Docker 客戶端就是 docker 命令轴术,我們可以通過(guò) docker 命令很方便地在 host 上構(gòu)建和運(yùn)行 docker 容器难衰。

image

Docker daemon

Docker daemon 是服務(wù)器組件,以 Linux 后臺(tái)服務(wù)的方式運(yùn)行逗栽,是 Docker 最核心的后臺(tái)進(jìn)程盖袭,我們也把它稱為守護(hù)進(jìn)程。它負(fù)責(zé)響應(yīng)來(lái)自 Docker Client 的請(qǐng)求彼宠,然后將這些請(qǐng)求翻譯成系統(tǒng)調(diào)用完成容器管理操作鳄虱。該進(jìn)程會(huì)在后臺(tái)啟動(dòng)一個(gè) API Server ,負(fù)責(zé)接收由 Docker Client 發(fā)送的請(qǐng)求凭峡,接收到的請(qǐng)求將通過(guò)Docker daemon 內(nèi)部的一個(gè)路由分發(fā)調(diào)度拙已,由具體的函數(shù)來(lái)執(zhí)行請(qǐng)求。

image

我們大致可以將其分為以下三部分:

  • Docker Server
  • Engine
  • Job

Docker Daemon的架構(gòu)如下所示:

image

Docker Daemon 可以認(rèn)為是通過(guò) Docker Server 模塊接受 Docker Client 的請(qǐng)求想罕,并在 Engine 中處理請(qǐng)求悠栓,然后根據(jù)請(qǐng)求類型,創(chuàng)建出指定的 Job 并運(yùn)行按价。 Docker Daemon 運(yùn)行在 Docker host 上惭适,負(fù)責(zé)創(chuàng)建、運(yùn)行楼镐、監(jiān)控容器癞志,構(gòu)建、存儲(chǔ)鏡像框产。

運(yùn)行過(guò)程的作用有以下幾種可能:

  • Docker Registry 獲取鏡像
  • 通過(guò) graphdriver 執(zhí)行容器鏡像的本地化操作
  • 通過(guò) networkdriver 執(zhí)行容器網(wǎng)絡(luò)環(huán)境的配置
  • 通過(guò) execdriver 執(zhí)行容器內(nèi)部運(yùn)行的執(zhí)行工作

由于 Docker DaemonDocker Client 的啟動(dòng)都是通過(guò)可執(zhí)行文件 docker 來(lái)完成的凄杯,因此兩者的啟動(dòng)流程非常相似。 Docker 可執(zhí)行文件運(yùn)行時(shí)秉宿,運(yùn)行代碼通過(guò)不同的命令行 flag 參數(shù)戒突,區(qū)分兩者,并最終運(yùn)行兩者各自相應(yīng)的部分描睦。

啟動(dòng) Docker Daemon 時(shí)膊存,一般可以使用以下命令來(lái)完成

docker --daemon = truedocker –ddocker –d = true

再由 dockermain() 函數(shù)來(lái)解析以上命令的相應(yīng) flag 參數(shù),并最終完成 Docker Daemon 的啟動(dòng)忱叭。

下圖可以很直觀地看到 Docker Daemon 的啟動(dòng)流程:

image

默認(rèn)配置下隔崎, Docker daemon 只能響應(yīng)來(lái)自本地 Host 的客戶端請(qǐng)求。如果要允許遠(yuǎn)程客戶端請(qǐng)求韵丑,需要在配置文件中打開(kāi) TCP 監(jiān)聽(tīng)爵卒。我們可以照著如下步驟進(jìn)行配置:

1、編輯配置文件 /etc/systemd/system/multi-user.target.wants/docker.service 撵彻,在環(huán)境變量 ExecStart后面添加 -H tcp://0.0.0.0钓株,允許來(lái)自任意 IP 的客戶端連接实牡。

image

2、重啟 Docker daemon

systemctl daemon-reloadsystemctl restart docker.service

3享幽、我們通過(guò)以下命令即可實(shí)現(xiàn)與遠(yuǎn)程服務(wù)器通信

docker -H 服務(wù)器IP地址 info

-H 是用來(lái)指定服務(wù)器主機(jī)铲掐, info 子命令用于查看 Docker 服務(wù)器的信息

Docker Image

Docker 鏡像可以看作是一個(gè)特殊的文件系統(tǒng)拾弃,除了提供容器運(yùn)行時(shí)所需的程序值桩、庫(kù)、資源豪椿、配置等文件外奔坟,還包含了一些為運(yùn)行時(shí)準(zhǔn)備的一些配置參數(shù)(如匿名卷、環(huán)境變量搭盾、用戶等)咳秉。鏡像不包含任何動(dòng)態(tài)數(shù)據(jù),其內(nèi)容在構(gòu)建之后也不會(huì)被改變鸯隅。我們可將 Docker 鏡像看成只讀模板澜建,通過(guò)它可以創(chuàng)建 Docker 容器。

鏡像有多種生成方法:

  1. 從無(wú)到有開(kāi)始創(chuàng)建鏡像
  2. 下載并使用別人創(chuàng)建好的現(xiàn)成的鏡像
  3. 在現(xiàn)有鏡像上創(chuàng)建新的鏡像

我們可以將鏡像的內(nèi)容和創(chuàng)建步驟描述在一個(gè)文本文件中蝌以,這個(gè)文件被稱作 Dockerfile 炕舵,通過(guò)執(zhí)行 docker build <docker-file> 命令可以構(gòu)建出 Docker 鏡像,在后續(xù)的教程中跟畅,我們會(huì)用一篇專門(mén)討論這個(gè)問(wèn)題咽筋。

Docker Registry

Docker registry 是存儲(chǔ) docker image 的倉(cāng)庫(kù),它在 docker 生態(tài)環(huán)境中的位置如下圖所示:

image

運(yùn)行docker push徊件、docker pull奸攻、docker search時(shí),實(shí)際上是通過(guò) docker daemondocker registry 通信虱痕。

Docker Container

Docker 容器就是 Docker 鏡像的運(yùn)行實(shí)例睹耐,是真正運(yùn)行項(xiàng)目程序、消耗系統(tǒng)資源部翘、提供服務(wù)的地方硝训。 Docker Container 提供了系統(tǒng)硬件環(huán)境,我們可以使用 Docker Images 這些制作好的系統(tǒng)盤(pán)略就,再加上我們所編寫(xiě)好的項(xiàng)目代碼捎迫, run 一下就可以提供服務(wù)啦。

Docker組件是如何協(xié)作運(yùn)行容器

看到這里表牢,我相信各位讀者朋友們應(yīng)該已經(jīng)對(duì)Docker基礎(chǔ)架構(gòu)已經(jīng)熟悉的差不多了窄绒,我們還記得運(yùn)行的第一個(gè)容器嗎?現(xiàn)在我們?cè)偻ㄟ^(guò)hello-world這個(gè)例子來(lái)體會(huì)一下 Docker 各個(gè)組件是如何協(xié)作的崔兴。

容器啟動(dòng)過(guò)程如下:

  • Docker 客戶端執(zhí)行 docker run 命令
  • Docker daemon 發(fā)現(xiàn)本地沒(méi)有 hello-world 鏡像
  • daemonDocker Hub 下載鏡像
  • 下載完成彰导,鏡像 hello-world 被保存到本地
  • Docker daemon 啟動(dòng)容器

具體過(guò)程可以看如下這幅演示圖:

image

我們可以通過(guò)docker images 可以查看到 hello-world 已經(jīng)下載到本地

image

我們可以通過(guò)docker ps 或者 docker container ls 顯示正在運(yùn)行的容器蛔翅,我們可以看到, hello-world 在輸出提示信息以后就會(huì)停止運(yùn)行位谋,容器自動(dòng)終止山析,所以我們?cè)诓榭吹臅r(shí)候沒(méi)有發(fā)現(xiàn)有容器在運(yùn)行。

image

我們把 Docker 容器的工作流程剖析的十分清楚了掏父,我們大體可以知道 Docker 組件協(xié)作運(yùn)行容器可以分為以下幾個(gè)過(guò)程:

  1. Docker 客戶端執(zhí)行 docker run 命令
  2. Docker daemon 發(fā)現(xiàn)本地沒(méi)有我們需要的鏡像
  3. daemonDocker Hub 下載鏡像
  4. 下載完成后笋轨,鏡像被保存到本地
  5. Docker daemon 啟動(dòng)容器

了解了這些過(guò)程以后,我們?cè)賮?lái)理解這些命令就不會(huì)覺(jué)得很突兀了赊淑,下面我來(lái)給大家講講 Docker 常用的一些命令操作吧爵政。

Docker常用命令

我們可以通過(guò) docker -h 去查看命令的詳細(xì)的幫助文檔。在這里我只會(huì)講一些平常日常比賽或者生活中我們可能會(huì)用的比較多的一些命令陶缺。

image

例如钾挟,我們需要拉取一個(gè) docker 鏡像,我們可以用如下命令:

docker pull image_name

image_name 為鏡像的名稱饱岸,而如果我們想從 Docker Hub 上去下載某個(gè)鏡像掺出,我們可以使用以下命令:

docker pull centos:latest

centos:lastest 是鏡像的名稱, Docker daemon 發(fā)現(xiàn)本地沒(méi)有我們需要的鏡像苫费,會(huì)自動(dòng)去 Docker Hub 上去下載鏡像汤锨,下載完成后,該鏡像被默認(rèn)保存到 /var/lib/docker 目錄下黍衙。

接著我們?nèi)绻氩榭聪轮鳈C(jī)下存在多少鏡像泥畅,我們可以用如下命令:

docker images

我們要想知道當(dāng)前有哪些容器在運(yùn)行,我們可以用如下命令:

docker ps -a

-a 是查看當(dāng)前所有的容器琅翻,包括未運(yùn)行的

我們?cè)撊绾稳?duì)一個(gè)容器進(jìn)行啟動(dòng)位仁,重啟和停止呢?我們可以用如下命令:

docker start container_name/container_iddocker restart container_name/container_iddocker stop container_name/container_id

這個(gè)時(shí)候我們?nèi)绻脒M(jìn)入到這個(gè)容器中方椎,我們可以使用 attach 命令:

docker attach container_name/container_id

那如果我們想運(yùn)行這個(gè)容器中的鏡像的話聂抢,并且調(diào)用鏡像里面的 bash ,我們可以使用如下命令:

docker run -t -i container_name/container_id /bin/bash

那如果這個(gè)時(shí)候棠众,我們想刪除指定鏡像的話琳疏,由于 image 被某個(gè) container 引用(拿來(lái)運(yùn)行),如果不將這個(gè)引用的 container 銷毀(刪除)闸拿,那 image 肯定是不能被刪除空盼。我們首先得先去停止這個(gè)容器:

docker psdocker stop container_name/container_id

然后我們用如下命令去刪除這個(gè)容器:

docker rm container_name/container_id

然后這個(gè)時(shí)候我們?cè)偃h除這個(gè)鏡像:

docker rmi image_name

此時(shí),常用的 Docker 相關(guān)的命令就講到這里為止了新荤,我們?cè)诤罄m(xù)的文章中還會(huì)反復(fù)地提到這些命令揽趾。

Dockerfile是什么

前面我們已經(jīng)提到了 Docker 的一些基本概念。以 CTF 選手的角度來(lái)看苛骨,我們可以去使用 Dockerfile 定義鏡像篱瞎,依賴鏡像來(lái)運(yùn)行容器苟呐,可以去模擬出一個(gè)真實(shí)的漏洞場(chǎng)景。因此毫無(wú)疑問(wèn)的說(shuō)俐筋, Dockerfile 是鏡像和容器的關(guān)鍵牵素,并且 Dockerfile 還可以很輕易的去定義鏡像內(nèi)容,說(shuō)了這么多澄者,那么 Dockerfile 到底是個(gè)什么東西呢笆呆?

Dockerfile 是自動(dòng)構(gòu)建 docker 鏡像的配置文件, 用戶可以使用 Dockerfile 快速創(chuàng)建自定義的鏡像闷哆。Dockerfile 中的命令非常類似于 linux 下的 shell 命令腰奋。

我們可以通過(guò)下面這幅圖來(lái)直觀地感受下 Docker 鏡像单起、容器和 Dockerfile 三者之間的關(guān)系抱怔。

image

我們從上圖中可以看到, Dockerfile 可以自定義鏡像嘀倒,通過(guò) Docker 命令去運(yùn)行鏡像屈留,從而達(dá)到啟動(dòng)容器的目的。

Dockerfile 是由一行行命令語(yǔ)句組成测蘑,并且支持已 # 開(kāi)頭的注釋行灌危。

一般來(lái)說(shuō),我們可以將 Dockerfile 分為四個(gè)部分:

  • 基礎(chǔ)鏡像(父鏡像)信息指令 FROM
  • 維護(hù)者信息指令 MAINTAINER
  • 鏡像操作指令 RUN 碳胳、 EVN 勇蝙、 ADDWORKDIR
  • 容器啟動(dòng)指令 CMDENTRYPOINTUSER

下面是一段簡(jiǎn)單的Dockerfile的例子:

FROM python:2.7MAINTAINER Angel_Kitty <angelkitty6698@gmail.com>COPY . /appWORKDIR /appRUN pip install -r requirements.txtEXPOSE 5000ENTRYPOINT ["python"]CMD ["app.py"]

我們可以分析一下上面這個(gè)過(guò)程:

  • 1挨约、從 Docker Hubpullpython 2.7 的基礎(chǔ)鏡像
  • 2味混、顯示維護(hù)者的信息
  • 3、copy 當(dāng)前目錄到容器中的 /app 目錄下 復(fù)制本地主機(jī)的 <src> ( Dockerfile 所在目錄的相對(duì)路徑)到容器里 <dest>
  • 4诫惭、指定工作路徑為 /app
  • 5翁锡、安裝依賴包
  • 6、暴露 5000 端口
  • 7夕土、啟動(dòng) app

這個(gè)例子是啟動(dòng)一個(gè) python flask appDockerfile ( flaskpython 的一個(gè)輕量的 web 框架)馆衔,相信大家從這個(gè)例子中能夠稍微理解了Dockfile的組成以及指令的編寫(xiě)過(guò)程。

Dockerfile常用的指令

根據(jù)上面的例子怨绣,我們已經(jīng)差不多知道了Dockerfile的組成以及指令的編寫(xiě)過(guò)程角溃,我們?cè)賮?lái)理解一下這些常用命令就會(huì)得心應(yīng)手了。

由于 Dockerfile 中所有的命令都是以下格式:INSTRUCTION argument 篮撑,指令 (INSTRUCTION) 不分大小寫(xiě)减细,但是推薦大寫(xiě),和sql語(yǔ)句是不是很相似呢咽扇?下面我們正式來(lái)講解一下這些指令集吧邪财。

FROM

FROM 是用于指定基礎(chǔ)的 images 陕壹,一般格式為 FROM <image> or FORM <image>:<tag> ,所有的 Dockerfile 都用該以 FROM 開(kāi)頭树埠,FROM 命令指明 Dockerfile 所創(chuàng)建的鏡像文件以什么鏡像為基礎(chǔ)糠馆,FROM 以后的所有指令都會(huì)在 FROM 的基礎(chǔ)上進(jìn)行創(chuàng)建鏡像≡醣铮可以在同一個(gè) Dockerfile 中多次使用 FROM 命令用于創(chuàng)建多個(gè)鏡像又碌。比如我們要指定 python 2.7 的基礎(chǔ)鏡像,我們可以像如下寫(xiě)法一樣:

FROM python:2.7

MAINTAINER

MAINTAINER 是用于指定鏡像創(chuàng)建者和聯(lián)系方式绊袋,一般格式為 MAINTAINER <name> 毕匀。這里我設(shè)置成我的 ID 和郵箱:

MAINTAINER Angel_Kitty <angelkitty6698@gmail.com>

COPY

COPY 是用于復(fù)制本地主機(jī)的 <src> (為 Dockerfile 所在目錄的相對(duì)路徑)到容器中的 <dest>

當(dāng)使用本地目錄為源目錄時(shí)癌别,推薦使用 COPY 皂岔。一般格式為 COPY <src><dest> 。例如我們要拷貝當(dāng)前目錄到容器中的 /app 目錄下展姐,我們可以這樣操作:

COPY . /app

WORKDIR

WORKDIR 用于配合 RUN躁垛,CMDENTRYPOINT 命令設(shè)置當(dāng)前工作路徑圾笨〗坦荩可以設(shè)置多次,如果是相對(duì)路徑擂达,則相對(duì)前一個(gè) WORKDIR 命令土铺。默認(rèn)路徑為/。一般格式為 WORKDIR /path/to/work/dir 板鬓。例如我們?cè)O(shè)置/app 路徑悲敷,我們可以進(jìn)行如下操作:

WORKDIR /app

RUN

RUN 用于容器內(nèi)部執(zhí)行命令。每個(gè) RUN 命令相當(dāng)于在原有的鏡像基礎(chǔ)上添加了一個(gè)改動(dòng)層穗熬,原有的鏡像不會(huì)有變化镀迂。一般格式為 RUN <command> 。例如我們要安裝 python 依賴包唤蔗,我們做法如下:

RUN pip install -r requirements.txt

EXPOSE

EXPOSE 命令用來(lái)指定對(duì)外開(kāi)放的端口探遵。一般格式為 EXPOSE <port> [<port>...]

例如上面那個(gè)例子,開(kāi)放5000端口:

EXPOSE 5000

ENTRYPOINT

ENTRYPOINT 可以讓你的容器表現(xiàn)得像一個(gè)可執(zhí)行程序一樣妓柜。一個(gè) Dockerfile 中只能有一個(gè) ENTRYPOINT箱季,如果有多個(gè),則最后一個(gè)生效棍掐。

ENTRYPOINT 命令也有兩種格式:

  • ENTRYPOINT ["executable", "param1", "param2"] :推薦使用的 exec形式
  • ENTRYPOINT command param1 param2shell 形式

例如下面這個(gè)藏雏,我們要將 python 鏡像變成可執(zhí)行的程序,我們可以這樣去做:

ENTRYPOINT ["python"]

CMD

CMD 命令用于啟動(dòng)容器時(shí)默認(rèn)執(zhí)行的命令作煌,CMD 命令可以包含可執(zhí)行文件掘殴,也可以不包含可執(zhí)行文件赚瘦。不包含可執(zhí)行文件的情況下就要用 ENTRYPOINT 指定一個(gè),然后 CMD 命令的參數(shù)就會(huì)作為ENTRYPOINT的參數(shù)奏寨。

CMD 命令有三種格式:

  • CMD ["executable","param1","param2"]:推薦使用的 exec 形式起意。
  • CMD ["param1","param2"]:無(wú)可執(zhí)行程序形式
  • CMD command param1 param2:shell 形式。

一個(gè) Dockerfile 中只能有一個(gè)CMD病瞳,如果有多個(gè)揽咕,則最后一個(gè)生效。而 CMDshell 形式默認(rèn)調(diào)用 /bin/sh -c 執(zhí)行命令套菜。

CMD 命令會(huì)被 Docker 命令行傳入的參數(shù)覆蓋:docker run busybox /bin/echo Hello Docker 會(huì)把 CMD 里的命令覆蓋亲善。

例如我們要啟動(dòng) /app ,我們可以用如下命令實(shí)現(xiàn):

CMD ["app.py"]

當(dāng)然還有一些其他的命令逗柴,我們?cè)谟玫降臅r(shí)候再去一一講解一下蛹头。

構(gòu)建Dockerfile

我們大體已經(jīng)把Dockerfile的寫(xiě)法講述完畢,我們可以自己動(dòng)手寫(xiě)一個(gè)例子:

mkdir static_webcd static_webtouch Dockerfile然后 vi Dockerfile  開(kāi)始編輯該文件輸入 i 開(kāi)始編輯 以下是我們構(gòu)建的Dockerfile內(nèi)容``````````FROM nginxMAINTAINER Angel_Kitty <angelkitty6698@gmail.com>RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html`````````` 編輯完后 按 esc 退出編輯然后  :wq    寫(xiě)入 退出

我們?cè)?Dockerfile 文件所在目錄執(zhí)行:

docker build -t angelkitty/nginx_web:v1 .

我們解釋一下嚎于, -t 是為新鏡像設(shè)置倉(cāng)庫(kù)和名稱掘而,其中 angelkitty 為倉(cāng)庫(kù)名, nginx_web 為鏡像名于购, :v1為標(biāo)簽(不添加為默認(rèn) latest

我們構(gòu)建完成之后,使用 docker images 命令查看所有鏡像知染,如果存在 REPOSITORYnginxTAGv1 的信息肋僧,就表示構(gòu)建成功。

image

接下來(lái)使用 docker run 命令來(lái)啟動(dòng)容器

docker run --name nginx_web -d -p 8080:80   angelkitty/nginx_web:v1

這條命令會(huì)用 nginx 鏡像啟動(dòng)一個(gè)容器控淡,命名為 nginx_web 嫌吠,并且映射了 8080 端口,這樣我們可以用瀏覽器去訪問(wèn)這個(gè) nginx 服務(wù)器:http://localhost:8080/ 或者 http://本機(jī)的IP地址:8080/掺炭,頁(yè)面返回信息:

hello-docker

這樣一個(gè)簡(jiǎn)單使用 Dockerfile 構(gòu)建鏡像辫诅,運(yùn)行容器的示例就完成了!

參考文獻(xiàn)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末涧狮,一起剝皮案震驚了整個(gè)濱河市炕矮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌者冤,老刑警劉巖肤视,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異涉枫,居然都是意外死亡邢滑,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)愿汰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)困后,“玉大人乐纸,你說(shuō)我怎么就攤上這事∫∮瑁” “怎么了锯仪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)趾盐。 經(jīng)常有香客問(wèn)我庶喜,道長(zhǎng),這世上最難降的妖魔是什么救鲤? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任久窟,我火速辦了婚禮,結(jié)果婚禮上本缠,老公的妹妹穿的比我還像新娘斥扛。我一直安慰自己,他們只是感情好丹锹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布稀颁。 她就那樣靜靜地躺著,像睡著了一般楣黍。 火紅的嫁衣襯著肌膚如雪匾灶。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天租漂,我揣著相機(jī)與錄音阶女,去河邊找鬼。 笑死哩治,一個(gè)胖子當(dāng)著我的面吹牛秃踩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播业筏,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼憔杨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蒜胖?” 一聲冷哼從身側(cè)響起消别,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎翠勉,沒(méi)想到半個(gè)月后妖啥,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡对碌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年荆虱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡怀读,死狀恐怖诉位,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情菜枷,我是刑警寧澤苍糠,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站啤誊,受9級(jí)特大地震影響岳瞭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蚊锹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一瞳筏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧牡昆,春花似錦姚炕、人聲如沸歧焦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)妻往。三九已至,卻和暖如春震檩,著一層夾襖步出監(jiān)牢的瞬間摄闸,已是汗流浹背禁漓。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工狐史, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留痒给,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓骏全,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親尼斧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子姜贡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容