Docker | 第五章:構建自定義鏡像

前言

上一章節,主要是介紹了下Dockerfile的一些經常使用命令的說明。咱們知道,利用Dockerfile能夠構建一個新的鏡像,好比運行Java環境,就須要一個JDK環境的鏡像,但直接使用公共的鏡像時,通常上大小都比較大。因此本章節就主要結合Dockerfile文件及commit方式,構建屬於本身的鏡像,同時對鏡像進行壓縮和優化,同時也是對Dockerfile知識的一個實踐。html

利用Dockerfile構建自定義鏡像

做爲一個java後端開發,這裏就直接以構建一個Oracle官方jre環境來示例。java

選定基礎鏡像

因爲在Linux中,JVM主要是調用系統的C語言庫,Oracle的官方JRE,使用的是libc,也就是glibc,這意味着你要運行任何Java程序,都須要先裝好glibc。因此咱們直接去https://hub.docker.com找一個基於glibc的基礎鏡像(固然了,你們也可直接選定好比CensOS這些Linux的發行版本了)。linux

glibc

咱們之類直接選擇默認排在第一個的alpine-glibc做爲咱們的基礎鏡像,比較這個大小也才12M左右呀!spring

題外話:你們做爲實驗性質時,爲了獲取更小的基礎鏡像,能夠選擇alpine這個基礎鏡像,比較這個只有5M大小,夠精簡了!docker

alpine

準備JRE版本

這裏咱們直接去Oracle官網選擇jre版本,這裏選擇的是jre-8u181-linux-x64版本(因爲對linux命令不是很熟悉,爲了避免必要的時間浪費,這裏直接下載了鏡像了,熟悉的各位能夠直接使用wget進行下載的)。後端

jre版本

編寫Dockerfile

# 基礎鏡像
 FROM frolvlad/alpine-glibc
 LABEL MAINTAINER oKong <499452441@qq.com>
 
 # 將JRE添加至鏡像中,add 命令在源文件爲壓縮文件時,會自動解壓的
 ADD jre-8u181-linux-x64.tar.gz /opt/docker/java/jre8

# 設置JAVA環境變量
# 這裏須要注意下,解壓後有個目錄的,爲jre1.8.0_181,一開始沒注意,啓動時報了:exec: "java": executable file not found in $PATH: unknown 後才發現。
ENV JAVA_HOME /opt/docker/java/jre8/jre1.8.0_181
ENV CLASSPATH=$JAVA_HOME/bin
ENV PATH=.:$JAVA_HOME/bin:$PATH

# 這裏無實際意義,只是在容器啓動時,輸出jre版本信息,驗證是否安裝成功
CMD ["java","-version"]

利用build命令,構建鏡像,同時指定tagtomcat

docker build -t lqdev.cn/jre8:0.1 .

注意:後面有個.的。springboot

Sending build context to Docker daemon  81.19MB
Step 1/7 : FROM frolvlad/alpine-glibc
 ---> d3bc626306a1
Step 2/7 : LABEL MAINTAINER oKong <499452441@qq.com>
 ---> Running in e788d29cd1e1
Removing intermediate container e788d29cd1e1
 ---> 5d95db4ae169
Step 3/7 : ADD jre-8u181-linux-x64.tar.gz /opt/docker/java/jre8
 ---> 0f4bb83df722
Step 4/7 : ENV JAVA_HOME /opt/docker/java/jre8/jre1.8.0_181
 ---> Running in 57a1e1ef00ed
Removing intermediate container 57a1e1ef00ed
 ---> 6f2b543a91b7
Step 5/7 : ENV PATH ${PATH}:${JAVA_HOME}/bin
 ---> Running in 2d75c88f97fb
Removing intermediate container 2d75c88f97fb
 ---> 92a7a0f9926c
Step 6/7 : WORKDIR /opt/docker/java/jre8/jre1.8.0_181
 ---> Running in 7b9a69efc980
Removing intermediate container 7b9a69efc980
 ---> 158c08c995c3
Step 7/7 : CMD ["java","-version"]
 ---> Running in 9ab517f8292a
Removing intermediate container 9ab517f8292a
 ---> 9c8606ac315a
Successfully built 9c8606ac315a
Successfully tagged lqdev.cn/jre8:0.1

而後查看下鏡像列表,bash

docker images

images

說明已經構建成功了,咱們來運行下:app

docker run -it -d --name myfirstjre  lqdev.cn/jre8:0.1

查看下容器列表:

docker ps -a

容器列表

因爲Dockerfile中使用CMD命令覆蓋了本來的/bin/sh,容器已啓動就中止了。因此咱們看下日誌,就知道是否jre安裝成功。

docker logs -f c6873a97ff49

logs

輸出了版本信息了,說明已經安裝成功了。

實踐:運行SpringBoot的jar包

如今咱們就能夠基於這個jre鏡像進行實際的jar包部署了。

Dockerfile文件方式:

# 基於咱們自定義構建的鏡像
FROM lqdev.cn/jre8:0.1

VOLUME /opt/tmp
# 這是jar 可自行選擇,這裏直接使用了原先講解springboot十四章節:基於Docker部署時的jar包
ADD chapter-14-0.0.1-SNAPSHOT.jar app.jar

# -Djava.security.egd=file:/dev/./urandom 可解決tomcat可能啓動慢的問題
# 具體可查看:https://www.cnblogs.com/mightyvincent/p/7685310.html
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

# 對外端口
EXPOSE 8080

而後構建新鏡像,並運行,同時查看日誌輸出

docker run -it -d --name springboot  lqdev.cn/springboot:0.1

日誌控制檯:

控制檯

運行的容器列表:

容器列表

說明咱們已經成功了,jar也啓動了。如今訪問下部署的jar服務:

利用commit命令構建自定義鏡像

第三章講解Docker經常使用命令時,有說到,利用commit可從容器中構建一個新的鏡像。因此這裏簡單講解下利用此命令進行自動鏡像的構建過程。

構建思路:咱們啓動一個基礎鏡像,同時運行,而後咱們進入容器,下載所須要的jre版本,並配置其環境變量。以後退出容器進行保存操做。這裏就不直接下載了,咱們直接拷貝jre到容器裏

啓動基礎鏡像:

docker run -it -d --name commitImages  frolvlad/alpine-glibc

拷貝jre到容器中。

docker cp /opt/docker/java/jre-8u181-linux-x64.tar.gz b0d354b9453a:/opt/docker/java/jre8

這裏會提示,說目錄不存在,可利用exec命令,進入容器建立目錄下,這裏就不演示了。

No such container:path: b0d354b9453a:/opt/docker/java

如今咱們進入容器:

docker exec -it b0d354b9453a /bin/sh

進入,/opt/docker/java/jre8目錄,進行常規linux下的jre安裝:

cd /opt/docker/java/jre8
  # 解壓
  tar -xzvf jre-8u181-linux-x64.tar.gz
  # 配置環境變量,vi /etc/profile 末尾加入
  export JAVA_HOME=/opt/docker/java/jre8/jre1.8.0_181
  export CLASSPATH=$JAVA_HOME/bin
  export PATH=.:$JAVA_HOME/bin:$PATH
  # 生效配置
  source /etc/profile
  # 驗證是否成功
  java -version
  輸出:
  java version "1.8.0_181"
  Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
  Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
  # 這裏有個坑,生效配置後退出容器後又失效了,搜索了後,把環境變量放在### ~/.bashrc 或者在~/.bashrc裏面加一句source /etc/profile 可是仍是未生效。。。。我放棄了。。 直接寫個sh腳本啓動 時加入吧。。

而後咱們退出容器,利用commit命令進行構建新鏡像:

docker commit b0d354b9453a lqdev.cn/jre8:0.2

而後查看:

運行jar,驗證下是否正常,這裏直接在啓動的時候拷貝jar到鏡像。

docker run -it -d -p 1234:8080 -v /opt/docker/java:/opt/docker/java/app.jar --name springboot2 lqdev.cn/jre8:0.2

而後進入容器運行下java 命令

# 進入容器
docker exec -it 583d0f387555 /bin/sh
# 生效配置
source etc/profile
# 運行jar
nohup java  -Djava.security.egd=file:/dev/./urandom -jar /opt/docker/java/app.jar >log.txt &

退出後,訪問宿主的1234端口服務,就能看見部署成功了:

新服務

其實比較好的作法是:建立一個sh腳本,腳本里設置了環境生效命令及java命令便可,你們可自行嘗試下,這裏就不演示了。

鏡像文件壓縮技巧

上一章節,咱們利用Dockerfilecommit的方式生成鏡像。如今咱們看下,鏡像文件大小:

兩種方式,commit還多了80M多。這裏咱們本着精簡的原則,對鏡像大小進行優化下。

首先,鏡像文件是按鏡像層(Layers)進行疊加的。總的來講就是:每一條指令都會建立一個鏡像層,繼而會增長總體鏡像的大小。

選擇一個精簡的基礎鏡像

一個基礎鏡像的大小直接決定了新鏡像的大小,因此能夠選擇儘可能小的精簡的鏡像。本文就使用了alpine-glibc做爲基礎鏡像,大小12.8M。

串聯RUN命令

多個RUN時,可經過 && 和 / 支持將命令串聯在一塊兒

# 舉例
RUN yum -y install java-1.7.0-openjdk-devel && yum clean all

不少鏡像大部分都是經過此方式進行RUN方式編寫的。官網:https://hub.docker.com/裏面的大部分鏡像都是以下寫法

刪除多餘文件及命令安裝包等

好比jre包中就有不少的文檔及說明文件是非必要的,這些就能夠刪除了。如下只是個參考,你們能夠自行刪減,能夠在Dockerfile編寫時,解壓後,使用RUN命令進行操做也能夠直接把壓縮包裏刪除後在拷貝:

rm -rf COPYRIGHT LICENSE README release THIRDPARTYLICENSEREADME-JAVAFX.txtTHIRDPARTYLICENSEREADME.txt Welcome.html
#刪除其餘無用文件
rm -rf     lib/plugin.jar \
           lib/ext/jfxrt.jar \
           bin/javaws \
           lib/javaws.jar \
           lib/desktop \
           plugin \
           lib/deploy* \
           lib/*javafx* \
           lib/*jfx* \
           lib/amd64/libdecora_sse.so \
           lib/amd64/libprism_*.so \
           lib/amd64/libfxplugins.so \
           lib/amd64/libglass.so \
           lib/amd64/libgstreamer-lite.so \
           lib/amd64/libjavafx*.so \
           lib/amd64/libjfx*.so

對比下,確實少了不少了。

固然對於大小不關心的,也就無需理會了,畢竟如今存儲空間都很大的,也就可能傳輸的時候慢點,哈哈~

參考資料

鏡像優化的你們可看看如下幾篇文章或者自行搜索下相關資料:

  1. https://blog.csdn.net/qq_36763896/article/details/53293088
  2. https://my.oschina.net/shyloveliyi/blog/1627020
  3. https://blog.csdn.net/chenyufeng1991/article/details/78766123

總結

本章節主要是介紹如何利用Dockerfile或者commit方式構建自定義鏡像。經過這兩種方式,咱們就能根據本身的實際業務須要進行個性化改造、優化,最終構建一個通用鏡像。在構建本身的鏡像時,儘可能仍是選擇本身熟悉的、穩定的基礎環境鏡像進行構建,畢竟出了問題找起來也熟門熟路點。一般,運維部門或者實施部門,制定的鏡像屬於資產,通常不會上送至Docker遠程倉庫的,有了鏡像,咱們就須要有個地方去存儲。下一章節,就重點講解下如何構建私有倉庫,管理本身的鏡像文件!

最後

若文中有錯誤或者遺漏之處,還望指出,共同進步!

老生常談

  • 我的QQ:499452441
  • 公衆號:lqdevOps

公衆號

我的博客:http://blog.lqdev.cn

原文地址:http://blog.lqdev.cn/2018/08/04/docker/docker-five/

相關文章
相關標籤/搜索