如何創(chuàng)建一個(gè)安全的Docker基礎(chǔ)鏡像

文章轉(zhuǎn)載自https://blog.csdn.net/sisiy2015/article/details/50913829

背景
我最初使用Docker的時(shí)候饿敲,每個(gè)人都在說它用起來有多簡單方便,它內(nèi)部的機(jī)制是有多么好,它為我們節(jié)省了多少時(shí)間滋将。但是當(dāng)我一使用它就發(fā)現(xiàn),幾乎所有鏡像都是臃腫而且不安全的(沒有使用包簽名,盲目相信上游的鏡像庫以curl | sh的方式安裝),而且也沒有一個(gè)鏡像能實(shí)現(xiàn)Docker的初衷:隔離默责,單進(jìn)程,容易分發(fā)咸包,簡潔桃序。

Docker鏡像本來不是為了取代復(fù)雜的虛擬機(jī)而設(shè)計(jì)的,后者有完整的日志烂瘫、監(jiān)控媒熊、警報(bào)和資源管理模塊。而Docker則傾向于利用內(nèi)核的cgroups和namespaces特性進(jìn)行封裝組合,這就好像:

在物理機(jī)器環(huán)境下泛释,一旦內(nèi)核完成了初始化,init進(jìn)程就起來了温算。
這也是為什么當(dāng)你在Dockerfile的CMD指令啟動(dòng)的進(jìn)程PID是1怜校,這是與Unix中的進(jìn)程機(jī)制類似的。

現(xiàn)在請查看一下你的進(jìn)程列表注竿,使用top或者ps茄茁,你會(huì)看到init進(jìn)程占用的也是這個(gè)PID,這是每個(gè)類Unix系統(tǒng)的核心進(jìn)程巩割,所有進(jìn)程的父進(jìn)程裙顽,一旦你理解這個(gè)概念:在類Unix系統(tǒng)上每個(gè)進(jìn)程都是init進(jìn)程的子進(jìn)程,你會(huì)理解Docker容器里不應(yīng)該有無關(guān)的修飾文件宣谈,它應(yīng)該是剛好滿足進(jìn)程運(yùn)行需要愈犹。

如何開始
現(xiàn)在的應(yīng)用多數(shù)是大型復(fù)雜的系統(tǒng),通常都需要很多依賴庫闻丑,例如有調(diào)度漩怎,編譯和很多其他相關(guān)工具類應(yīng)用,它們的架構(gòu)通常封裝性良好嗦嗡,通過一層層的抽象和接口把底層細(xì)節(jié)隱藏了勋锤,從某種程度上說,這也算是一種容器侥祭,但是從系統(tǒng)架構(gòu)視角看叁执,我們需要一種比以往虛擬環(huán)境更簡單的方案了。

以Java為例
從零開始矮冬,思考你要構(gòu)建一個(gè)最通用的基礎(chǔ)容器谈宛,想想你的應(yīng)用本身,它運(yùn)行需要什么欢伏?

可能性有很多入挣,如果你要運(yùn)行Java應(yīng)用,它需要Java運(yùn)行時(shí)硝拧;如果運(yùn)行Rails應(yīng)用径筏,它需要Ruby解釋器,對Python應(yīng)用也一樣障陶。Go和其他一些編譯型語言有些許不同滋恬,我以下會(huì)提到。

在Java例子中抱究,下一步要想的是:JRE需要什么依賴才能運(yùn)行恢氯?因?yàn)樗亲寫?yīng)用能運(yùn)行的最重要的組件,所以很自然的下一步就是要想清楚JRE運(yùn)行依賴于什么。

而實(shí)際上JRE并沒太多依賴勋拟,它本來就是作為操作系統(tǒng)的抽象層勋磕,使代碼不依賴于宿主系統(tǒng)運(yùn)行,因此安裝好JRE就基本準(zhǔn)備就緒了敢靡。

(實(shí)際上挂滓,對操作系統(tǒng)的獨(dú)立性并不是理所當(dāng)然的事,有非常多的系統(tǒng)特有API和專有的系統(tǒng)擴(kuò)展啸胧,但是便于舉例赶站,我們把注意力放在簡單的情況下)

在Linux上,JVM主要是調(diào)用系統(tǒng)的C語言庫纺念,Oracle的官方JRE贝椿,使用的是libc,也就是glibc陷谱,這意味著你要運(yùn)行任何Java程序烙博,都需要先裝好glibc。另外你可能需要某種shell來管理環(huán)境烟逊,還有一個(gè)與外部通訊的接口习勤,例如網(wǎng)絡(luò)和資源的接口。

我們總結(jié)一下Java應(yīng)用示例需要的最低配置是:

  • JRE焙格,在例子中我們使用Oracle JRE
  • glibc图毕,JRE的依賴
  • 一個(gè)基礎(chǔ)環(huán)境(包含網(wǎng)絡(luò)、內(nèi)存眷唉、文件系統(tǒng)等資源管理工具)

走進(jìn)Alpine Linux
Alpine Linux最近得到很多關(guān)注予颤,主要是因?yàn)樗虬艘幌盗械慕?jīng)過驗(yàn)簽的可信任的依賴,并且還保持體積在2MB冬阳!而在本文發(fā)布時(shí)蛤虐,其他的一些鏡像分發(fā)版如下:

ubuntu:latest: 66MB (已經(jīng)瘦身了非常多了,以前有些版本超過600MB)
debian:latest: 55MB (同上肝陪,一開始是200MB以上的)
arch:latest: 145MB
busybox:latest: 676KB (是的驳庭!KB,我稍后會(huì)討論它)
alpine:latest: 2MB (2MB氯窍,包含一個(gè)包管理工具的Linux系統(tǒng))

Busybox是最小的競爭者饲常?
從上邊的對比中你可以看到,在體積上唯一能打敗Alpine Linux的是Busybox狼讨,所以現(xiàn)在幾乎所有嵌入式系統(tǒng)都是使用它贝淤,它被應(yīng)用在路由器,交換機(jī)政供,ATM播聪,或者你的吐司機(jī)上朽基。它作為一個(gè)最最基礎(chǔ)的環(huán)境,但是又提供了足夠容易維護(hù)的shell接口离陶。

在網(wǎng)上有很多文章解釋了為什么人們會(huì)選擇Alpine Linux而不是Busybox稼虎,我在這總結(jié)一下:

  • 開放活躍的軟件包倉庫:Alpine Linux使用apk包管理工具,它集成在Docker鏡像中招刨,而Busybox你需要另外安裝一個(gè)包管理器渡蜻,例如opkg,更甚者计济,你需要尋找一個(gè)穩(wěn)定的包倉庫源(這幾乎沒有),Alpine的包倉庫中提供了大量常用的依賴包排苍,例如沦寂,如果你仍然需要在容器中編譯NodeJS或Ruby之類的代碼,你可以直接運(yùn)行apk來添加nodejs和ruby淘衙,這在幾秒內(nèi)便可以完成传藏。
  • 體積確實(shí)重要,但是當(dāng)你在功能性彤守,靈活性毯侦,易用性和1.5MB之間衡量,體積就不那么重要了具垫,Alpine上添加的包使這些方面都大大增強(qiáng)了侈离。
  • 廣泛的支持:Docker公司已經(jīng)聘請了Alpine Linux的作者來維護(hù)它,所有官方鏡像筝蚕,在以后都將基于Alpine Linux來構(gòu)建卦碾。沒有比這個(gè)更有說服力的理由去讓你在自己的容器中使用它了吧。

構(gòu)建一個(gè)Java環(huán)境基鏡像
正如我剛解釋的起宽,Alpine Linux是一個(gè)構(gòu)建自有鏡像時(shí)不錯(cuò)的選擇洲胖,因此,我們在此將使用它來構(gòu)建簡潔高效的Docker鏡像坯沪,我們開始吧!

組合:Alpine + bash
每個(gè)Dockerfile第一個(gè)指令都是指定它的父級容器绿映,通常是用于繼承,在我們的例子中是alpine:latest:

FROM alpine:latest
MAINTAINER cSphere <docker@csphere.cn>
RUN apk add --no-cache --update-cache bash
CMD ["/bin/bash"]

好了腐晾,現(xiàn)在我們構(gòu)建容器:

$ docker build -t my-java-base-image .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM alpine:latest
 ---> 2314ad3eeb90
Step 2 : MAINTAINER cSphere <docker@csphere.cn>
 ---> Running in 63433312d77e
 ---> bfe94713797a
Removing intermediate container 63433312d77e
... 
Step 4 : CMD /bin/bash
 ---> Running in d2291684b797
 ---> ecc443d68f27
Removing intermediate container d2291684b797
Successfully built ecc443d68f27

并且運(yùn)行它:

$ docker run --rm -ti my-java-base-image
bash-4.3#

成功了叉弦!我們有了一個(gè)運(yùn)行著bash的Alpine Linux。

glibc and friends
前邊提到藻糖,Oracle的JRE依賴于glibc卸奉,Alpine Linux上并沒有g(shù)libc,它使用一個(gè)更小體積的替代版,叫musl libc颖御。glibc發(fā)展了這么多年榄棵,幾乎包含了所有C語言中需要的依賴包凝颇,顯然這樣會(huì)很不靈活,一個(gè)glibc庫被編譯進(jìn)Alpine Linux疹鳄,勉強(qiáng)能維持在5MB的體積拧略,而它的替代者musl-libc是一個(gè)二進(jìn)制文件,只有897KB瘪弓,并且支持了所有Linux架構(gòu)上的C依賴垫蛆。

對Oracle的JRE,沒有辦法不把glibc加上腺怯,幸運(yùn)的是袱饭,Andy Shinn已經(jīng)做過了這些,他提供了一個(gè)預(yù)編譯的glibc鏡像給Alpine Linux呛占,在Github上的alpine-pkg-glibc虑乖,最新版是2.23-r1。

這樣把這相關(guān)依賴加到Dockerfile中晾虑,現(xiàn)在我們的Dockerfile看起來是這樣:

FROM alpine:latest
MAINTAINER cSphere <docker@csphere.cn>

ENV GLIBC_PKG_VERSION=2.23-r1

RUN apk add --no-cache --update-cache curl ca-certificates bash && \
  curl -Lo /etc/apk/keys/andyshinn.rsa.pub "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/andyshinn.rsa.pub" && \
  curl -Lo glibc-${GLIBC_PKG_VERSION}.apk "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-${GLIBC_PKG_VERSION}.apk" && \
  curl -Lo glibc-bin-${GLIBC_PKG_VERSION}.apk "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-bin-${GLIBC_PKG_VERSION}.apk" && \
  curl -Lo glibc-i18n-${GLIBC_PKG_VERSION}.apk "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-i18n-${GLIBC_PKG_VERSION}.apk" && \
  apk add glibc-${GLIBC_PKG_VERSION}.apk glibc-bin-${GLIBC_PKG_VERSION}.apk glibc-i18n-${GLIBC_PKG_VERSION}.apk

CMD ["/bin/bash"]

我們一句句解釋一下這些指令:

ENV GLIBC_PKG_VERSION=2.23-r1

我們通過變量指定GitHub上的glibc版本疹味,所以每當(dāng)一個(gè)新版本發(fā)布,都不需要更改URL帜篇,而直接更改這個(gè)變量即可糙捺。

RUN apk add --update-cache curl ca-certificates bash && \

這個(gè)指令會(huì)使用apk命令安裝我們需要的包,包括curl和ca-certificates(以便使用TLS的頁面)笙隙,最后的bash是我們Dockerfile上個(gè)版本已經(jīng)有的了洪灯。

curl -Lo /etc/apk/keys/andyshinn.rsa.pub "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/andyshinn.rsa.pub" && \
  curl -Lo glibc-${GLIBC_PKG_VERSION}.apk "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-${GLIBC_PKG_VERSION}.apk" && \
  curl -Lo glibc-bin-${GLIBC_PKG_VERSION}.apk "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-bin-${GLIBC_PKG_VERSION}.apk" && \
  curl -Lo glibc-i18n-${GLIBC_PKG_VERSION}.apk "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-i18n-${GLIBC_PKG_VERSION}.apk" && \

這些命令會(huì)接著剛剛的RUN指令,它們會(huì)從GitHub下載相關(guān)公鑰和依賴包竟痰。

apk add glibc-${GLIBC_PKG_VERSION}.apk glibc-bin-${GLIBC_PKG_VERSION}.apk glibc-i18n-${GLIBC_PKG_VERSION}.apk

所有包下載完成后婴渡,我們會(huì)用這一行命令安裝全部,由于我們之前添加了公鑰凯亮,所以它們的簽名會(huì)被驗(yàn)證边臼。

好了!我們現(xiàn)在有了一個(gè)能運(yùn)行幾乎全部依賴于glibc包的環(huán)境假消。

Java運(yùn)行環(huán)境
一般來說柠并,Oracle不提供軟件倉庫的形式讓人們下載,但是人們總是會(huì)找到一些方法繞過它富拗,你可以使用以下命令把JRE添加到Docker鏡像中:

ENV JAVA_VERSION_MAJOR=8 \
    JAVA_VERSION_MINOR=73 \
    JAVA_VERSION_BUILD=02 \
    JAVA_PACKAGE=server-jre

WORKDIR /tmp

RUN curl -jksSLH "Cookie: oraclelicense=accept-securebackup-cookie" \
  "http://download.oracle.com/otn-pub/java/jdk/${JAVA_VERSION_MAJOR}u${JAVA_VERSION_MINOR}-b${JAVA_VERSION_BUILD}/${JAVA_PACKAGE}-${JAVA_VERSION_MAJOR}u${JAVA_VERSION_MINOR}-linux-x64.tar.gz" | gunzip -c - | tar -xf - && \
  apk del curl ca-certificates && \
  mv jdk1.${JAVA_VERSION_MAJOR}.0_${JAVA_VERSION_MINOR}/jre /jre && \
  rm /jre/bin/jjs && \
  rm /jre/bin/keytool && \
  rm /jre/bin/orbd && \
  rm /jre/bin/pack200 && \
  rm /jre/bin/policytool && \
  rm /jre/bin/rmid && \
  rm /jre/bin/rmiregistry && \
  rm /jre/bin/servertool && \
  rm /jre/bin/tnameserv && \
  rm /jre/bin/unpack200 && \
  rm /jre/lib/ext/nashorn.jar && \
  rm /jre/lib/jfr.jar && \
  rm -rf /jre/lib/jfr && \
  rm -rf /jre/lib/oblique-fonts && \
  rm -rf /tmp/* /var/cache/apk/* && \
  echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf

ENV JAVA_HOME /jre
ENV PATH ${PATH}:${JAVA_HOME}/bin

這堆命令究竟做了什么臼予,我們還是一句句來看一下吧:

ENV JAVA_VERSION_MAJOR=8 \
    JAVA_VERSION_MINOR=73 \
    JAVA_VERSION_BUILD=02 
    JAVA_PACKAGE=server-jre

WORKDIR /tmp

這句非常簡單,它定義了我們要從Oracle服務(wù)器上要下載的軟件版本啃沪,本文編寫時(shí)粘拾,上邊的版本號是最新的,以后可能會(huì)變化创千,你可以從Oracle官網(wǎng)上查看缰雇。它同時(shí)也指定了WORKDIR工作目錄入偷,我們需要從一個(gè)臨時(shí)目錄開始運(yùn)行,所以這里設(shè)置了/tmp械哟。

RUN curl -jksSLH "Cookie: oraclelicense=accept-securebackup-cookie" \
  "http://download.oracle.com/otn-pub/java/jdk/${JAVA_VERSION_MAJOR}u${JAVA_VERSION_MINOR}-b${JAVA_VERSION_BUILD}/${JAVA_PACKAGE}-${JAVA_VERSION_MAJOR}u${JAVA_VERSION_MINOR}-linux-x64.tar.gz" | gunzip -c - | tar -xf - && \

這句稍微有點(diǎn)復(fù)雜疏之,它使用curl傳了一個(gè)指定的頭信息(“Cookie: oraclelicense=accept-securebackup-cookie”),以從Oracle上獲取真正的下載包暇咆,這是必須的锋爪,不然會(huì)返回一個(gè)錯(cuò)誤頁。然后它會(huì)把下載好的包通過管道傳給gunzip和tar 爸业,換言之其骄,它并不會(huì)保存下載回來的tar包,而是直接解壓出來到磁盤上扯旷。

apk del curl ca-certificates && \

這時(shí)curl和ca-certificates兩個(gè)包都完成了它們的使命拯爽,可以刪除了它們以節(jié)省空間。

rm /jre/bin/jjs && \
  rm /jre/bin/keytool && \
  rm /jre/bin/orbd && \
  rm /jre/bin/pack200 && \
  rm /jre/bin/policytool && \
  rm /jre/bin/rmid && \
  rm /jre/bin/rmiregistry && \
  rm /jre/bin/servertool && \
  rm /jre/bin/tnameserv && \
  rm /jre/bin/unpack200 && \
  rm /jre/lib/ext/nashorn.jar && \
  rm /jre/lib/jfr.jar && \
  rm -rf /jre/lib/jfr && \
  rm -rf /jre/lib/oblique-fonts && \
  rm -rf /tmp/* /var/cache/apk/* && \

JRE自帶了一些工具包薄霜,可能永遠(yuǎn)都不會(huì)用到的,我們也將它們刪掉纸兔。 最后一行惰瓜,會(huì)把全部臨時(shí)文件和apk的包緩存也清理了。

echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf

這一行中汉矿,我們修改了nsswitch.conf崎坊,以確保網(wǎng)絡(luò)正常,這會(huì)被glibc等包所用到洲拇。

最后奈揍,我們的Dockerfile會(huì)是下邊這樣:

FROM alpine:latest
MAINTAINER cSphere <docker@csphere.cn>

ENV JAVA_VERSION_MAJOR=8 \
    JAVA_VERSION_MINOR=73 \
    JAVA_VERSION_BUILD=02 \
    JAVA_PACKAGE=server-jre \
    GLIBC_PKG_VERSION=2.23-r1 \
    LANG=en_US.UTF8

WORKDIR /tmp

RUN apk add --no-cache --update-cache curl ca-certificates bash && \
  curl -Lo /etc/apk/keys/andyshinn.rsa.pub "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/andyshinn.rsa.pub" && \
  curl -Lo glibc-${GLIBC_PKG_VERSION}.apk "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-${GLIBC_PKG_VERSION}.apk" && \
  curl -Lo glibc-bin-${GLIBC_PKG_VERSION}.apk "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-bin-${GLIBC_PKG_VERSION}.apk" && \
  curl -Lo glibc-i18n-${GLIBC_PKG_VERSION}.apk "https://github.com/andyshinn/alpine-pkg-glibc/releases/download/${GLIBC_PKG_VERSION}/glibc-i18n-${GLIBC_PKG_VERSION}.apk" && \
  apk add glibc-${GLIBC_PKG_VERSION}.apk glibc-bin-${GLIBC_PKG_VERSION}.apk glibc-i18n-${GLIBC_PKG_VERSION}.apk && \
  curl -jksSLH "Cookie: oraclelicense=accept-securebackup-cookie" \
  "http://download.oracle.com/otn-pub/java/jdk/${JAVA_VERSION_MAJOR}u${JAVA_VERSION_MINOR}-b${JAVA_VERSION_BUILD}/${JAVA_PACKAGE}-${JAVA_VERSION_MAJOR}u${JAVA_VERSION_MINOR}-linux-x64.tar.gz" | gunzip -c - | tar -xf - && \
  apk del curl ca-certificates && \
  mv jdk1.${JAVA_VERSION_MAJOR}.0_${JAVA_VERSION_MINOR}/jre /jre && \
  rm /jre/bin/jjs && \
  rm /jre/bin/keytool && \
  rm /jre/bin/orbd && \
  rm /jre/bin/pack200 && \
  rm /jre/bin/policytool && \
  rm /jre/bin/rmid && \
  rm /jre/bin/rmiregistry && \
  rm /jre/bin/servertool && \
  rm /jre/bin/tnameserv && \
  rm /jre/bin/unpack200 && \
  rm /jre/lib/ext/nashorn.jar && \
  rm /jre/lib/jfr.jar && \
  rm -rf /jre/lib/jfr && \
  rm -rf /jre/lib/oblique-fonts && \
  rm -rf /tmp/* /var/cache/apk/* && \
  echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf

ENV JAVA_HOME=/jre
ENV PATH=${PATH}:${JAVA_HOME}/bin

注意這里,我整合了兩個(gè)ENV和RUN指令赋续,因?yàn)樽詈檬怯酶俚闹虚g層男翰,特別是這個(gè)容器是作為通用的構(gòu)建單元。

簡單來說纽乱,有一個(gè)規(guī)則:你需要更大的靈活性蛾绎,那你需要更多的層;如果你需要減小體積和降低復(fù)雜度鸦列,你需要更少的層租冠。這完全取決于你的需求。

在頂部我還加上了這句:

ENV LANG=en_US.UTF-8

這句是為了確保運(yùn)行在這個(gè)系統(tǒng)環(huán)境的應(yīng)用能指定語言薯嗤。你可以根據(jù)需要設(shè)定這個(gè)LANG環(huán)境變量顽爹。

另外,JAVA_HOME和PATH也要設(shè)置好骆姐,以使用剛剛裝好的JRE镜粤。
從Github上下載:https://github.com/izuolan/dockerfiles/blob/master/base/java/oracle-jdk-1.8/Dockerfile

CMD指令會(huì)怎么運(yùn)行?
我之前提到捏题,我們這是在構(gòu)建一個(gè)能提供給其他服務(wù)作為基礎(chǔ)的鏡像,它不需要帶上CMD指令繁仁,因?yàn)樗肋h(yuǎn)不會(huì)運(yùn)行涉馅,但是一旦一個(gè)服務(wù)關(guān)聯(lián)上它,就需要用到了黄虱。

不過你還是可以通過其他方式啟動(dòng)這個(gè)容器稚矿,例如docker run或docker exec指令:

$ docker run --rm -ti my-java-base-image /bin/bash

構(gòu)建最終鏡像
最后,我們終于到了構(gòu)建鏡像這步了:

$ docker build -t my-java-base-image .
Sending build context to Docker daemon 60.42 kB
Step 1 : FROM alpine:latest
 ---> 2314ad3eeb90
Step 2 : MAINTAINER cSphere <docker@csphere.cn>
 ---> Using cache
 ---> 93cc2bc0bd60
Step 3 : ENV JAVA_VERSION_MAJOR 8 JAVA_VERSION_MINOR 73 JAVA_VERSION_BUILD 02 JAVA_PACKAGE server-jre GLIBC_PKG_VERSION 2.23-r1 LANG en_US.UTF8
 ---> Running in 3f0ffeaeca78
 ---> 1dcfd34b0f1a
Removing intermediate container 3f0ffeaeca78
... 省略若干行
Removing intermediate container 0a98b36a6e37
Step 7 : ENV PATH ${PATH}:${JAVA_HOME}/bin
 ---> Running in 54d0dfb04f98
 ---> 493399ac9ca6
Removing intermediate container 54d0dfb04f98
Successfully built 493399ac9ca6

它執(zhí)行成功了捻浦。我們運(yùn)行容器里的java來驗(yàn)證一下吧:

$ docker run --rm -ti my-java-base-image java -version
java version "1.8.0_73"
Java(TM) SE Runtime Environment (build 1.8.0_73-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.73-b02, mixed mode)

這正是我們要看到的結(jié)果晤揣,我們已經(jīng)有了一個(gè)獨(dú)立的Oracle JRE環(huán)境,以后我們只需要基于這個(gè)鏡像來構(gòu)建應(yīng)用鏡像即可:

FROM my-java-base-image
[...]

最終鏡像有多大朱灿?

$ docker images | grep my-java-base-image | awk '{print $7,$8}'
130.4 MB

說實(shí)話昧识,這還是挺大的,但是畢竟里邊裝的是Java嘛~

總結(jié)
我們現(xiàn)在構(gòu)建了一個(gè)安全盗扒、輕量的Docker鏡像跪楞,基本上可以運(yùn)行任何Java應(yīng)用在上面,當(dāng)然你也可以根據(jù)實(shí)際情況調(diào)整這個(gè)Dockerfile侣灶,但是主要的思想還是像上邊說的那樣甸祭,減小體積,使用安全的軟件源褥影。

一旦你明白Docker容器只是一個(gè)基礎(chǔ)的單進(jìn)程容器池户,只是一個(gè)應(yīng)用運(yùn)行的環(huán)境,它能讓你專注于應(yīng)用的構(gòu)建而不是其他雜七雜八的依賴關(guān)系校焦,你就會(huì)把Docker應(yīng)用到得心應(yīng)手。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末统倒,一起剝皮案震驚了整個(gè)濱河市寨典,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌房匆,老刑警劉巖凝赛,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異坛缕,居然都是意外死亡墓猎,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門赚楚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毙沾,“玉大人,你說我怎么就攤上這事宠页∽蟀” “怎么了寇仓?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長烤宙。 經(jīng)常有香客問我遍烦,道長,這世上最難降的妖魔是什么躺枕? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任服猪,我火速辦了婚禮,結(jié)果婚禮上拐云,老公的妹妹穿的比我還像新娘罢猪。我一直安慰自己,他們只是感情好叉瘩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布膳帕。 她就那樣靜靜地躺著,像睡著了一般薇缅。 火紅的嫁衣襯著肌膚如雪危彩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天泳桦,我揣著相機(jī)與錄音汤徽,去河邊找鬼。 笑死蓬痒,一個(gè)胖子當(dāng)著我的面吹牛泻骤,可吹牛的內(nèi)容都是我干的漆羔。 我是一名探鬼主播梧奢,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼演痒!你這毒婦竟也來了亲轨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鸟顺,失蹤者是張志新(化名)和其女友劉穎惦蚊,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體讯嫂,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蹦锋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了欧芽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片莉掂。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖千扔,靈堂內(nèi)的尸體忽然破棺而出憎妙,到底是詐尸還是另有隱情库正,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布厘唾,位于F島的核電站褥符,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏抚垃。R本人自食惡果不足惜喷楣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望讯柔。 院中可真熱鬧抡蛙,春花似錦、人聲如沸魂迄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捣炬。三九已至熊昌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間湿酸,已是汗流浹背婿屹。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留推溃,地道東北人昂利。 一個(gè)月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像铁坎,于是被迫代替她去往敵國和親蜂奸。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

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