Docker 使用鏡像 - 二

使用commit理解鏡像構(gòu)成

docker commit 命令除了學(xué)習(xí)之外婉商,還有一些特殊的場(chǎng)合適合使用,比如被入侵后保存現(xiàn)場(chǎng)等。
定制鏡像,應(yīng)該使用 Dockerfile 來完成碗旅,不要使用 docker commit 定制鏡像。

鏡像是容器的基礎(chǔ)镜悉,每次執(zhí)行 docker run 的時(shí)候都會(huì)指定哪個(gè)鏡像作為容器運(yùn)行的基礎(chǔ)祟辟。
直接使用鏡像可以滿足一定的需求,當(dāng)鏡像無法直接滿足的時(shí)候侣肄,就需要定制鏡像旧困。

定制一個(gè) web 應(yīng)用服務(wù)器

[root@ip-10-1-0-142 ~]# docker run --name webserver -itd -p 80:80 nginx:latest
e829ded69fa81c0afddcce54109898e02e15a205cf07e63d101de8c572dc7a54

直接用瀏覽器訪問

訪問最初返回

定制化web頁面,可以將文字進(jìn)行更改稼锅,使用docker exec 命令進(jìn)入到容器吼具,再進(jìn)行內(nèi)容修改

[root@ip-10-1-0-142 ~]# docker exec -it webserver bash
root@e829ded69fa8:/# echo '<h1>Hello, Word!</h1>' > /usr/share/nginx/html/index.html


更新后的返回

修改了容器的文件,也就是改動(dòng)了容器的存儲(chǔ)層缰贝。使用 docker diff 命令查看具體的改動(dòng)

修改之前
[root@ip-10-1-0-142 ~]# docker diff e8
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
A /var/cache/nginx/client_temp
A /var/cache/nginx/fastcgi_temp
A /var/cache/nginx/proxy_temp
C /run
A /run/nginx.pid
C /etc
C /etc/nginx
C /etc/nginx/conf.d
C /etc/nginx/conf.d/default.conf

修改之后
[root@ip-10-1-0-142 ~]# docker diff webserver
C /run
A /run/nginx.pid
C /usr
C /usr/share
C /usr/share/nginx
C /usr/share/nginx/html
C /usr/share/nginx/html/index.html
C /root
A /root/.bash_history
C /etc
C /etc/nginx
C /etc/nginx/conf.d
C /etc/nginx/conf.d/default.conf
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/proxy_temp
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
A /var/cache/nginx/client_temp
A /var/cache/nginx/fastcgi_temp

鏡像定制好馍悟,然后進(jìn)行鏡像保存畔濒。
我們運(yùn)行在一個(gè)容器的時(shí)候(不使用卷)剩晴,我們的任何文件修改都會(huì)被記錄于容器存儲(chǔ)層里。而Docker 提供了一個(gè)docker commit 命令侵状,可以將容器的存儲(chǔ)層保存下來成為鏡像赞弥。也就是說,在原有的鏡像基礎(chǔ)上趣兄,再疊加容器的存儲(chǔ)層绽左,構(gòu)建成新的鏡像。

docker commit 的語法格式為:

docker commit [選項(xiàng)] <容器ID或容器名> [<倉(cāng)庫(kù)名>[:<標(biāo)簽>]]
[root@ip-10-1-0-142 ~]# docker commit
--author "BigMay"
--message "modify html"
webserver
nginx:v2
sha256:a09c32d8e04de96e40148839d9fce30f8bee17c5138c2745e6e44199576b0534

  • 其中 --author 是指定修改的作者艇潭,而 --message 則是記錄本次修改的內(nèi)容拼窥。這點(diǎn)和 git 版本控制相似,不過這里這些信息可以省略留空蹋凝。

查看定制好的鏡像文件

[root@ip-10-1-0-142 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v2 a09c32d8e04d About a minute ago 133MB
nginx latest 08b152afcfae 4 days ago 133MB
httpd latest 73b8cfec1155 4 days ago 138MB
centos latest 300e315adb2f 7 months ago 209MB

還可以使用 docker history 具體查看鏡像內(nèi)的歷史記錄鲁纠,對(duì)比nginx:latest 和 nginx:v2的歷史記錄

對(duì)比

使用新的鏡像部署容器

[root@ip-10-1-0-142 ~]# docker run -it --name webservr2 -p 8080:80 nginx:v2

慎用 docker commit

使用 docker commit 可以比較直觀的理解鏡像分層存儲(chǔ)的概念,但是在實(shí)際的環(huán)境中不會(huì)這么使用鳍寂。
在修改文件的過程中改含,由于命令的執(zhí)行,可能會(huì)有多個(gè)文件被動(dòng)或添加了迄汛。不僅僅是簡(jiǎn)單的操作捍壤,如果是安裝軟件包骤视、編譯構(gòu)建,就可能會(huì)有大量的無關(guān)內(nèi)容被添加進(jìn)來鹃觉,這樣會(huì)導(dǎo)致鏡像非常臃腫专酗。
另外,使用 docker commit 就是對(duì)所有的鏡像的操作都是黑箱操作盗扇,生成的鏡像被稱為 黑箱鏡像 笼裳。也就是說,除了制作鏡像的人知道執(zhí)行了什么命令粱玲、怎么生成的鏡像躬柬,別人無法知道做過哪些操作。而且抽减,如果制作鏡像的人允青,過一段時(shí)間后無法記清具體的操作。這種黑箱鏡像的維護(hù)工作就非常痛苦卵沉。

回顧之前提及的鏡像所使用的分層存儲(chǔ)的概念颠锉,除了當(dāng)前層外,之前的每一層都是不會(huì)發(fā)生改變的史汗,任何修改的結(jié)果只是在當(dāng)前層進(jìn)行了標(biāo)記琼掠、添加、修改停撞,不會(huì)改動(dòng)上一層瓷蛙。

使用Dockerfile 定制鏡像

Dockerfile 是一個(gè)文本文件,其中包含了一條條的指令戈毒,每一條指令構(gòu)建一層艰猬,因此每一條指令的內(nèi)容,就是描述該層應(yīng)當(dāng)如何構(gòu)建埋市。
對(duì)比 docker commit冠桃,使用Dockerfile 可以吧每一層修改、安裝道宅、構(gòu)建食听、操作的命令都寫入一個(gè)腳本,利用這個(gè)腳本來構(gòu)建污茵、定制鏡像樱报。

以nginx鏡像為例,使用 Dockerfile 來定制省咨。
首先肃弟,在一個(gè)空白目錄中,建立一個(gè)文本文件,命名為 Dockerfile :

[root@ip-10-1-0-142 ~]# mkdir mynginx
[root@ip-10-1-0-142 ~]# cd mynginx/
[root@ip-10-1-0-142 mynginx]# touch Dockerfile
[root@ip-10-1-0-142 mynginx]# vim Dockerfile
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

非常簡(jiǎn)單笤受,只有兩行穷缤,只涉及到兩條指令,F(xiàn)ROM 和 RUN

FROM 指定基礎(chǔ)鏡像

定制鏡像就是以一個(gè)鏡像為基礎(chǔ)箩兽,在其上進(jìn)行定制津肛。
FROM 就是指定的 基礎(chǔ)鏡像,所以在一個(gè)Dockerfile 中 FROM的指令是必備的汗贫,并且必須是第一條指令身坐。

Docker Hub 上有非常多的高質(zhì)量的官方鏡像,有可以直接拿來使用的服務(wù)類的鏡像落包,如 nginx部蛇、redismongo咐蝇、mysql涯鲁、httpdphp有序、tomcat 等抹腿;也有一些方便開發(fā)、構(gòu)建旭寿、運(yùn)行各種語言應(yīng)用的鏡像警绩,如 nodeopenjdk盅称、python肩祥、rubygolang 等微渠〈罨茫可以在其中尋找一個(gè)最符合我們最終目標(biāo)的鏡像為基礎(chǔ)鏡像進(jìn)行定制。

如果沒有找到對(duì)應(yīng)服務(wù)的鏡像逞盆,官方鏡像中還提供了一些更為基礎(chǔ)的操作系統(tǒng)鏡像,如 ubuntu松申、debian云芦、centosfedora贸桶、alpine 等舅逸,這些操作系統(tǒng)的軟件庫(kù)為我們提供了更廣闊的擴(kuò)展空間。

除了選擇現(xiàn)有鏡像為基礎(chǔ)鏡像外皇筛,Docker 還存在一個(gè)特殊的鏡像琉历,名為 scratch。這個(gè)鏡像是虛擬的概念,并不實(shí)際存在旗笔,它表示一個(gè)空白的鏡像彪置。

FROM scratch
...

如果你以 scratch 為基礎(chǔ)鏡像的話,意味著你不以任何鏡像為基礎(chǔ)蝇恶,接下來所寫的指令將作為鏡像第一層開始存在拳魁。

不以任何系統(tǒng)為基礎(chǔ),直接將可執(zhí)行文件復(fù)制進(jìn)鏡像的做法并不罕見撮弧,對(duì)于 Linux 下靜態(tài)編譯的程序來說潘懊,并不需要有操作系統(tǒng)提供運(yùn)行時(shí)支持,所需的一切庫(kù)都已經(jīng)在可執(zhí)行文件里了贿衍,因此直接 FROM scratch 會(huì)讓鏡像體積更加小巧授舟。使用 Go 語言 開發(fā)的應(yīng)用很多會(huì)使用這種方式來制作鏡像,這也是為什么有人認(rèn)為 Go 是特別適合容器微服務(wù)架構(gòu)的語言的原因之一贸辈。

RUN 執(zhí)行命令

RUN 指令是用來執(zhí)行命令行命令的岂却。由于命令行的強(qiáng)大能力,RUN 指令在指定鏡像時(shí)是最常用的指令之一裙椭。其格式有兩種:
shell 格式:RUN <命令>躏哩,就像直接在命令行中輸入的命令一樣。剛才寫的 Dockerfile 中的 RUN 指令就是這種格式揉燃。

RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

exec 格式:RUN ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"]扫尺,這更像是函數(shù)調(diào)用中的格式。
既然 RUN 就像shell 腳本一樣可以執(zhí)行命令炊汤,那么我們是否就可以像 Shell 腳本一樣把每個(gè)命令對(duì)應(yīng)一個(gè)RUN呢正驻?比如:

FROM debian:stretch

RUN apt-get update
RUN apt-get install -y gcc libc6-dev make wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN mkdir -p /usr/src/redis
RUN tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
RUN make -C /usr/src/redis
RUN make -C /usr/src/redis install

其實(shí)這樣也是可以的,只是創(chuàng)建了7層抢腐。

Dockerfile 中每一個(gè)指令都會(huì)建立一層姑曙, RUN 也不例外。每一個(gè) RUN 的行為迈倍,都會(huì)新建立一層伤靠,在其上執(zhí)行這些命令,待執(zhí)行結(jié)束后啼染,commit 這一層的修改宴合,構(gòu)建新的鏡像。

再部署一個(gè)應(yīng)用或一個(gè)環(huán)境的時(shí)候迹鹅,把每一個(gè)步驟的執(zhí)行建立一層是沒有必要的卦洽,很多運(yùn)行時(shí)不需要的東西都單獨(dú)封裝在一層,這樣會(huì)導(dǎo)致image 非常臃腫斜棚。比如編譯環(huán)境阀蒂、更新的軟件包等等该窗。不僅讓image產(chǎn)生了臃腫和多層,而且還非常耗時(shí)蚤霞。

Union FS是有最大層數(shù)限制的酗失,比如AUFS,曾經(jīng)是最大不超過42層争便,現(xiàn)在是不超過127層

上面的Dockerfile 正確的寫法是:

FROM debian:stretch

RUN set -x; buildDeps='gcc libc6-dev make wget'
&& apt-get update
&& apt-get install -y $buildDeps
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
&& mkdir -p /usr/src/redis
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1
&& make -C /usr/src/redis
&& make -C /usr/src/redis install
&& rm -rf /var/lib/apt/lists/*
&& rm redis.tar.gz
&& rm -r /usr/src/redis
&& apt-get purge -y --auto-remove $buildDeps

首先级零,之前所有的命令只有一個(gè)目的,就是編譯安裝redis可執(zhí)行文件滞乙。只是創(chuàng)建一層的需求奏纪,只使用一個(gè) RUN 指令,并使用 && 將各個(gè)所需命令串聯(lián)起來斩启。將7個(gè) RUN 序调,簡(jiǎn)化為一個(gè) RUN,1層兔簇。
所以发绢,在撰寫 Dockerfile 的時(shí)候,要經(jīng)常提醒自己垄琐,不是在寫 shell 腳本边酒,而是在定義每一層要如何構(gòu)建。

并且狸窘,這里為了格式化海進(jìn)行了換行墩朦。Dockerfile 支持 shell 類的行尾添加 \ 的命令換行方式,以及可以使用 # 進(jìn)行注釋的格式翻擒。
良好的格式氓涣,比如換行、縮緊陋气、注釋等劳吠,會(huì)讓維護(hù)、排障更為容易巩趁,是一個(gè)比較良好的習(xí)慣痒玩。

構(gòu)建鏡像

使用定制的 nginx 鏡像的 Dockerfile來構(gòu)建鏡像。

在 Dockerfile 文件所在的目錄執(zhí)行:

[root@ip-10-1-0-142 mynginx]# docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM nginx
---> 08b152afcfae
Step 2/2 : RUN echo '<h1>Hello, Word!</h1>' > /usr/share/nginx/html/index.html
---> Running in c71a877f386f
Removing intermediate container c71a877f386f
---> 31aa55b35c46
Successfully built 31aa55b35c46
Successfully tagged nginx:v3

從命令輸出的結(jié)果晶渠,可以清晰的看到鏡像構(gòu)建的過程凰荚。
在 Step 2 中,RUN 指令啟動(dòng)了一個(gè)容器 c71a877f386f 褒脯,執(zhí)行了所要求的命令,并最后提交了這一層 31aa55b35c46 缆毁,隨后刪除了所用到的這個(gè)容器 c71a877f386f 番川。

使用 docker build 命令進(jìn)行鏡像構(gòu)建。格式為:

docker build [選項(xiàng)] <上下文路徑/URL/->

在這里我們指定了最終鏡像的名稱 -t nginx:v3,構(gòu)建成功后颁督,我們可以像之前運(yùn)行 nginx:v2 那樣來運(yùn)行這個(gè)鏡像践啄,其結(jié)果會(huì)和 nginx:v2 一樣。

鏡像構(gòu)建上下文(Context)

在運(yùn)行 docker build 命令最后有一個(gè) . 沉御。. 表示當(dāng)前目錄屿讽,而 Dockerfile 就在當(dāng)前目錄,這是指定上下文路徑吠裆。上下文是什么伐谈?

首先我們要理解 docker build 的工作原理。Docker 在運(yùn)行時(shí)分為Docker 引擎(也就是服務(wù)端守護(hù)進(jìn)程)和客戶端工具试疙。Docker 的引擎提供了一組 REST API诵棵,被稱為 Docker Remote API,如 docker 命令這樣的客戶端工具祝旷,則是通過這組API 與 Docker 引擎交互來完成各種功能履澳。
所以,看似我們是在本機(jī)執(zhí)行各種 docker 功能命令怀跛,但實(shí)際上距贷,一切都是使用的遠(yuǎn)程調(diào)用形式在服務(wù)端(Docker 引擎)完成。也因?yàn)檫@種 C/S 架構(gòu)設(shè)計(jì)吻谋,讓我們操作遠(yuǎn)程服務(wù)器的Docker 引擎變得簡(jiǎn)單忠蝗。

當(dāng)我們進(jìn)行鏡像構(gòu)建的時(shí)候,并非所有定制都會(huì)通過 RUN 指令完成滨溉,經(jīng)常會(huì)需要將一些本地文件復(fù)制到鏡像什湘,比如通過 copy 指令、add 指令等等晦攒。而docker build 命令構(gòu)建鏡像闽撤,是在服務(wù)端進(jìn)行的,不是在本地進(jìn)行的脯颜,也就是在 docker engine 中構(gòu)建的哟旗。那么,如何才能讓服務(wù)器端獲得本地的文件呢栋操?

這就引入了上下文的概念闸餐,當(dāng)構(gòu)建的時(shí)候,用戶會(huì)指定構(gòu)建鏡像上下文的路徑矾芙, docker build 命令得知這個(gè)路徑后舍沙,會(huì)將路徑下的所有內(nèi)容打包,然后上傳到 Docker 引擎剔宪。Docker 引擎收到這個(gè)上下文包后拂铡,展開就會(huì)獲得構(gòu)建鏡像所需的一切文件壹无。

如果在 Dockerfile 中這么寫:

COPY ./package.json /app/

這不是要復(fù)制執(zhí)行 docker build 命令所在目錄下的 package.json文件,也不是復(fù)制 Dockerfile 所在目錄下的 package.json感帅,而是復(fù)制 上下文(context)目錄下的 package.json 文件斗锭。

因此,COPY 這類指令中的源文件的路徑都是相對(duì)路徑失球。這也是初學(xué)者經(jīng)常會(huì)問的為什么 COPY ../package.json /app 或者 COPY /opt/xxxx /app 無法工作的原因岖是,因?yàn)檫@些路徑已經(jīng)超出了上下文的范圍,Docker 引擎無法獲得這些位置的文件实苞。如果真的需要那些文件豺撑,應(yīng)該將它們復(fù)制到上下文目錄中去。

現(xiàn)在就可以理解剛才的命令 docker build -t nginx:v3 . 中的這個(gè) .硬梁,實(shí)際上是在指定上下文的目錄前硫,docker build 命令會(huì)將該目錄下的內(nèi)容打包交給 Docker 引擎以幫助構(gòu)建鏡像。

如果觀察 docker build 輸出荧止,我們其實(shí)已經(jīng)看到了這個(gè)發(fā)送上下文的過程:

[root@ip-10-1-0-142 mynginx]# docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048kB

理解構(gòu)建上下文對(duì)于鏡像構(gòu)建是很重要的屹电,避免犯一些不應(yīng)該的錯(cuò)誤。比如有些初學(xué)者在發(fā)現(xiàn) COPY /opt/xxxx /app 不工作后跃巡,于是干脆將 Dockerfile 放到了硬盤根目錄去構(gòu)建危号,結(jié)果發(fā)現(xiàn) docker build 執(zhí)行后,在發(fā)送一個(gè)幾十 GB 的東西素邪,極為緩慢而且很容易構(gòu)建失敗外莲。那是因?yàn)檫@種做法是在讓 docker build 打包整個(gè)硬盤,這顯然是使用錯(cuò)誤兔朦。

一般來說偷线,應(yīng)該會(huì)將 Dockerfile 置于一個(gè)空目錄下,或者項(xiàng)目根目錄下沽甥。如果該目錄下沒有所需文件声邦,那么應(yīng)該把所需文件復(fù)制一份過來。如果目錄下有些東西確實(shí)不希望構(gòu)建時(shí)傳給 Docker 引擎摆舟,那么可以用 .gitignore 一樣的語法寫一個(gè) .dockerignore亥曹,該文件是用于剔除不需要作為上下文傳遞給 Docker 引擎的。

那么為什么會(huì)有人誤以為 . 是指定 Dockerfile 所在目錄呢恨诱?這是因?yàn)樵谀J(rèn)情況下媳瞪,如果不額外指定 Dockerfile 的話,會(huì)將上下文目錄下的名為 Dockerfile 的文件作為 Dockerfile照宝。

[root@ip-10-1-0-142 mynginx]# docker build -t nginx:v5 -f demo .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM nginx
---> 08b152afcfae
Step 2/2 : RUN echo '<h1>Hello, Word!</h1>' > /usr/share/nginx/html/index.html
---> Using cache
---> 31aa55b35c46
Successfully built 31aa55b35c46
Successfully tagged nginx:v5

一般情況下都會(huì)使用默認(rèn)的文件名 Dockerfile蛇受,以及會(huì)將其放置于鏡像構(gòu)建上下文目錄中。

其他 docker build 的用法

直接用 Git repo 進(jìn)行構(gòu)建

[root@ip-10-1-0-142 mynginx]# docker build --help

Usage: docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile

Options:
--add-host list Add a custom host-to-IP mapping (host:ip)
--build-arg list Set build-time variables
--cache-from strings Images to consider as cache sources
--cgroup-parent string Optional parent cgroup for the container
--compress Compress the build context using gzip
--cpu-period int Limit the CPU CFS (Completely Fair Scheduler) period
--cpu-quota int Limit the CPU CFS (Completely Fair Scheduler) quota
-c, --cpu-shares int CPU shares (relative weight)
--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
--disable-content-trust Skip image verification (default true)
-f, --file string Name of the Dockerfile (Default is 'PATH/Dockerfile')
--force-rm Always remove intermediate containers
--iidfile string Write the image ID to the file
--isolation string Container isolation technology
--label list Set metadata for an image
-m, --memory bytes Memory limit
--memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap
--network string Set the networking mode for the RUN instructions during build (default
"default")
--no-cache Do not use cache when building the image
--pull Always attempt to pull a newer version of the image
-q, --quiet Suppress the build output and print image ID on success
--rm Remove intermediate containers after a successful build (default true)
--security-opt strings Security options
--shm-size bytes Size of /dev/shm
-t, --tag list Name and optionally a tag in the 'name:tag' format
--target string Set the target build stage to build.
--ulimit ulimit Ulimit options (default [])
[root@ip-10-1-0-142 mynginx]# docker build -f nginx:v4 ./dem

docker build 還支持從 URL 構(gòu)建厕鹃,比如可以直接從 Git repo 中構(gòu)建:

[root@ip-10-1-0-142 mynginx]# !229
docker build -t hello-world https://github.com/docker-library/hello-world.git#master:amd64/hello-world
Sending build context to Docker daemon 19.46kB
Step 1/3 : FROM scratch
--->
Step 2/3 : COPY hello /
---> 73f19933b2d9
Step 3/3 : CMD ["/hello"]
---> Running in 0c6155341ab9
Removing intermediate container 0c6155341ab9
---> dd3f92cd2824
Successfully built dd3f92cd2824
Successfully tagged hello-world:latest

如果出現(xiàn)錯(cuò)誤信息龙巨,如下:

[root@ip-10-1-0-142 mynginx]# docker build -t hello-world https://github.com/docker-library/hello-world.git#master:amd64/hello-world
unable to prepare context: unable to find 'git': exec: "git": executable file not found in $PATH

先在系統(tǒng)安裝git笼呆,如 yum install -y git ,然后再進(jìn)行鏡像 build

用給定的 tar 壓縮包構(gòu)建

docker build http://<server-001>/context.tar.gz

如果所給出的 URL 不是個(gè) Git repo熊响,而是個(gè) tar 壓縮包旨别,那么 Docker 引擎會(huì)下載這個(gè)包,并自動(dòng)解壓縮汗茄,以其作為上下文秸弛,開始構(gòu)建。

從標(biāo)準(zhǔn)輸入中讀取 Dockerfile 進(jìn)行構(gòu)建

docker build -t nginx:v1 - < Dockerfile

[root@ip-10-1-0-142 mynginx]# docker build -t nginx:v1 - < demo
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM nginx
---> 08b152afcfae
Step 2/2 : RUN echo '<h1>Hello, Word!</h1>' > /usr/share/nginx/html/index.html
---> Running in 4a04eff723cd
Removing intermediate container 4a04eff723cd
---> a772a8d3759e
Successfully built a772a8d3759e
Successfully tagged nginx:v1

cat Dockerfile | docker build -

[root@ip-10-1-0-142 mynginx]# cat demo | docker build -t nginx:v2 -
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM nginx
---> 08b152afcfae
Step 2/2 : RUN echo '<h1>Hello, Word!</h1>' > /usr/share/nginx/html/index.html
---> Using cache
---> a772a8d3759e
Successfully built a772a8d3759e
Successfully tagged nginx:v2

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末洪碳,一起剝皮案震驚了整個(gè)濱河市递览,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瞳腌,老刑警劉巖绞铃,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異嫂侍,居然都是意外死亡儿捧,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門挑宠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來菲盾,“玉大人,你說我怎么就攤上這事各淀±良” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵碎浇,是天一觀的道長(zhǎng)临谱。 經(jīng)常有香客問我,道長(zhǎng)奴璃,這世上最難降的妖魔是什么悉默? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮溺健,結(jié)果婚禮上麦牺,老公的妹妹穿的比我還像新娘。我一直安慰自己鞭缭,他們只是感情好剖膳,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著岭辣,像睡著了一般吱晒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上沦童,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天仑濒,我揣著相機(jī)與錄音叹话,去河邊找鬼。 笑死墩瞳,一個(gè)胖子當(dāng)著我的面吹牛驼壶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播喉酌,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼热凹,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了泪电?” 一聲冷哼從身側(cè)響起般妙,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎相速,沒想到半個(gè)月后碟渺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡突诬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年苫拍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片攒霹。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡怯疤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出催束,到底是詐尸還是另有隱情集峦,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布抠刺,位于F島的核電站塔淤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏速妖。R本人自食惡果不足惜高蜂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望罕容。 院中可真熱鬧备恤,春花似錦、人聲如沸锦秒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旅择。三九已至惭笑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沉噩。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工捺宗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人川蒙。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓蚜厉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親派歌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弯囊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

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