文档章节

使用 Dockerfile定制Java Web镜像

吴伟祥
 吴伟祥
发布于 2018/11/16 09:48
字数 2563
阅读 888
收藏 13

一、前言

使用 Docker 搭建 Java Web 运行环境(利用 commit 理解镜像构成  来源:黄勇 )博文的归纳:

1、启动容器:

docker run <相关参数> <镜像 ID> <初始命令>

-i:表示以“交互模式”运行容器
-t:表示容器启动后会进入其命令行
-v:表示需要将本地哪个目录挂载到容器中,格式:-v <宿主机目录>:<容器目录>

进入容器,配置环境,exit

2、查看所有容器 : 
docker container ls -a      或者 docker ps -a

3、docker commit 的语法格式为:
docker commit [选项] <容器ID或容器名> [<仓库名>[:<标签>]]

--author "wwx<wuweixiang.alex@gmail.com>" \
--message "修改了默认网页" \

docker commit 57c312bbaad1 huangyong/javaweb:0.1

4、启动容器:
docker run <相关参数> <镜像 ID> <初始命令>

 

慎用 docker commit,利用 commit 镜像构成,意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为黑箱镜像。如果使用 docker commit 制作镜像,以及后期修改的话,每一次修改都会让镜像更加臃肿一次,所删除的上一层的东西并不会丢失,会一直如影随形的跟着这个镜像,即使根本无法访问到。这会让镜像更加臃肿。

二、使用 Dockerfile 定制Java Web镜像

Ⅰ、Dockerfile回顾

《Docker学习——创建镜像(四)》

《Docker学习——Dockerfile 指令详解(五)》

①Dockerfile简介

Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

②Dockerfile指令详解

#指定基础镜像 
FROM   

Dockerfile中必备指令,并且必须是第一条指令

FROM scratch   不以任何镜像为基础,接下来的指令将作为镜像第一层开始存在

#指定维护者信息
MAINTAINER
格式: 
MAINTAINER <name>


#执行命令行命令
RUN  
定义每一层该如何构建(不是在写 Shell 脚本)
每一个 RUN = 启动一个容器、执行命令、然后提交存储层文件变更
两行 RUN 命令的执行环境不同

格式:
1) shell 格式: RUN <命令>                                   #类似命令行输入
2) exec  格式: RUN ["可执行文件", "参数1", "参数2"]           #类似函数调用

行尾 \ 换行
行首 # 注释
&& 命令串联

#复制文件
COPY 
格式: 
1) COPY <源路径>... <目标路径> 
2) COPY ["<源路径1>",... "<目标路径>"]

<源路径> 可以是多个,甚至可以是通配符   #上下文路径的相对路径
<目标路径> 可以是容器内的绝对路径,也可以是相对于工作目录的相对路径(工作目录可以用 WORKDIR 指令来指定)

#更高级的复制文件
ADD
<源路径> 可以是一个 URL,
如果是gzip , bzip2 以及 xz 的情况下,ADD 指令将会自动解压缩这个压缩文件到 <目标路径> 去
所有的文件复制均使用COPY 指令,仅在需要自动解压缩的场合使用 ADD

#容器启动命令
CMD 
容器就是进程。 既然是进程,在启动的时候,需要指定所运行的程序及参数。
CMD 指令就是用于指定默认的容器主进程的启动命令

对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。

格式: 
1) shell 格式:  CMD <命令>
2) exec  格式:  CMD ["可执行文件", "参数1", "参数2"...]
一般推荐使用 exec 格式,这类格式在解析时会被解析为 JSON 数组,因此一定要使用双引号 " ,而不要使用单引号

CMD echo $HOME 在实际执行中,会将其变更为: CMD [ "sh", "-c", "echo $HOME" ]

#入口点
ENTRYPOINT 
和 CMD 一样,都是在指定容器启动程序及参数

实际执行时,将变为: <ENTRYPOINT> "<CMD>"   #启动时,可再对可执行文件进行传参

ENTRYPOINT ["docker-entrypoint.sh"]      #应用运行前的准备工作,指定了 ENTRYPOINT 为 docker-entrypoint.sh 脚本,并且可在镜像启动时候传入参数来服务脚本

#设置环境变量
ENV 
格式: 
1) ENV <key> <value> 
2) ENV <key1>=<value1> <key2>=<value2>...

#构建参数
ARG 
和 ENV 所不同的是, ARG 所设置的构建环境的环境变量,在将来容器运行时不会存在这些环境变量的。
格式: 
ARG <参数名>[=<默认值>]

可以在构建命令docker build 中用 --build-arg <参数名>=<值> 来覆盖

#定义匿名卷
VOLUME 

为了防止运行时用户忘记将动态文件所保存目录挂载为卷(volume),指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,应用也可以正常运行,不会向容器存储层写入大量数据

格式: 
1) VOLUME <路径>
2) VOLUME ["<路径1>", "<路径2>"...] 

VOLUME /data 
这里的 /data 目录就会在运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层

-v mydata:/data
mydata 这个命名卷挂载到了 /data 这个位置,替代了Dockerfile 中定义的匿名卷的挂载配置

#声明端口
EXPOSE 
声明运行时容器提供服务端口

#指定工作目录
WORKDIR 
改变以后各层的工作目录
格式:
WORKDIR <工作目录路径> 

相当于 cd  

...
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

则最终路径为 /a/b/c

#指定当前用户
USER 
USER 指令和 WORKDIR 相似,都是改变环境状态并影响以后的层
USER 只是帮助你切换到指定用户而已,这个用户必须是事先建立好的,否则无法切换。

#健康检查
HEALTHCHECK 
格式: 
1) HEALTHCHECK [选项] CMD <命令>          #设置检查容器健康状况的命令 
2) HEALTHCHECK NONE                      #如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令

HEALTHCHECK 支持下列选项:
--interval=<间隔> :两次健康检查的间隔,默认为 30 秒;
--timeout=<时长> :健康检查命令运行超时时间,如果超过这个时间,本次健康检查就被视为失败,默认 30 秒;
--retries=<次数> :当连续失败指定次数后,则将容器状态视为 unhealthy ,默认 3次。和 CMD , ENTRYPOINT 一样, HEALTHCHECK 只可以出现一次,如果写了多个,只有最后一个生效。

HEALTHCHECK --interval=5s --timeout=3s \ 
CMD curl -fs http://localhost/ || exit 1

#为他人做嫁衣裳
ONBUILD 
当以当前镜像为基础镜像,去构建下一级镜像的时候才会被执行
格式: 
ONBUILD <其它指令> 

做一个基础镜像,基础镜像更新,各个项目不用同步 Dockerfile 的变化,重新构建后就继承了基础镜像的更新

③构建镜像

#构建镜像 
docker build [选项] <指定上下文路径/URL/-> 

镜像并非在本地构建,而是在服务端,也就是镜像是在 Docker 引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢? 
构建候,用户会指定构建镜像上下文的路径, docker build 命令得知这个路径会将路径下的所有内容打包,然后上传给 Docker 引擎。
这样Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件 

初学者经常会问的为什么COPY ../package.json /app 或者 COPY /opt/xxxx /app 无法工作的原因,因为这些路径已经超出了上下文的范围Docker 引擎无法获得这些位置的文件。 

例如:COPY ./package.json /app/  是复制 上下文(context) 目录下的package.json   #COPY 这类指令中的源文件的路径上下文路径的相对路径 

-f ../Dockerfile.php 参数指定某个文件作为Dockerfile 
其它 docker build 的用法 
直接用 Git repo 进行构建:Docker 就会自己去 git clone 这个项目、切换到指定分支、并进入到指定目录后开始构建 
用给定的 tar 压缩包构建:Docker 引擎会下载这个包,并自动解压缩,以其作为上下文,开始构建

Ⅱ、Dockerfile的编写

1.0.0 Dockerfile

# 版本信息
FROM centos:7
MAINTAINER wuweixiang <wuweixiang.alex@gmail.com>
# 设置工作目录
WORKDIR /var/
# 添加jdk、tomcat
ADD jdk-8u191-linux-x64.tar.gz .
#ADD http://mirrors.hust.edu.cn/apache/tomcat/tomcat-8/v8.5.35/bin/apache-tomcat-8.5.35.tar.gz .
ADD apache-tomcat-8.5.35.tar.gz .

# 设置环境变量
ENV JAVA_HOME /var/jdk1.8.0_191
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
ENV TIME_ZONE Asia/Shanghai

# 更改时区
RUN set -x \
&& echo "${TIME_ZONE}" > /etc/timezone \
&& ln -sf /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime

# 开启内部服务端口
EXPOSE 8080

# 启动tomcat服务器
CMD ["/var/apache-tomcat-8.5.35/bin/catalina.sh","run"] && tail -f /var/apache-tomcat-8.5.35/logs/catalina.out

Ⅲ、构建方式(镜像已push,此步可忽略)

①linux安装git

sudo yum install git

②克隆项目源码

git clone https://gitee.com/wuweixiang/javaweb-docker.git

③构建镜像

进入到/javaweb-docker/dockerfile-java8-tomcat8目录下:

docker build -t  [<仓库名>[:<标签>]] .  #创建镜像 


仓库名:经常以 两段式路径 形式出现,比如 wuweixiang/javaweb:1.0.0,前者Docker账号用户名,后者则往往是对应的软件名。
    
标签:指定所需哪个版本的镜像,默认latest。

Ⅳ、使用方式

 1、新购买的服务器,安装docker,执行以下指令:

curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

 2、创建/var/webapps/目录,并将war包放入该目录下

 3、运行以下命令,即可实现部署。

docker run -d -p 80:8080 \
-v /var/webapps/:/var/apache-tomcat-8.5.35/webapps/ \
--name <容器名>  \
wuweixiang/javaweb:1.0.0

 注意: 

  挂载路径 /var/webapps/  为当前war上传位置

Ⅴ、使用示例

1、下载一个war包到挂载路径/var/webapps/下:

可见,war包自动完成解压。

2、即可访问http://112.74.185.172/finder-web-2.4.9

Ⅵ、总结

  该部署方式与之前的部署方式上,省去了jdk、tomcat环境的配置过程,只要上传war包即可。

© 著作权归作者所有

吴伟祥

吴伟祥

粉丝 31
博文 490
码字总数 284885
作品 0
泉州
后端工程师
私信 提问
构建Docker镜像实战之构建Tomcat9.0镜像(RPM一键安装Java环境)

构建Docker镜像实战之构建Tomcat9.0镜像(RPM一键安装Java环境) tomcat是一个免费开源的轻量级web服务器,在中小型企和并发访问量不高的场合普遍使用,是开发和调试JSP程序的首选。下面使用...

漂移的兔子
2018/08/16
0
0
Docker最全教程之使用Docker搭建Java开发环境(十七)

Docker最全教程之使用Docker搭建Java开发环境(十七) 前言 Java是一门面向对象的优秀编程语言,市场占有率极高,但是在容器化实践过程中,发现官方支持并不友好,同时与其他编程语言的基础镜...

优惠码领取
03/13
0
0
如何把遗留的Java应用托管在Service Fabric中

一、概述 众所周知,微服务化尤其对遗留系统进行微服务化一般采用“Lift and Shift”的模式进行。 Service Fabric作为一个微服务托管平台,不仅仅可以在上面跑.NET和Java的原生应用(使用SF编...

dotNET开发经验谈
2018/09/18
0
0
Docker修炼第一招: 先从Dockerfile开始

东坡有诗:日建镜像三百个,不辞长用Dockerfile。 觉得镜像构建枯燥乏味?困货,快来根Dockerfile吧! 作为一枚构建镜像的老司机,下面跟大家展示一篇Dockerfile实战。 Docker、Dockerfile、...

好雨云帮
2016/11/30
28.9K
2
Google 正式开源 Jib ,帮助 Java 应用快速容器化

Google 本周宣布开源一款新的 Java 工具 Jib ,旨在让开发者使用他们熟悉的工具更轻松地将 Java 应用程序容器化。 在7月9日发布的博客文章中,Google 软件工程师 Appu Goundan 和 Qingyang C...

王练
2018/07/11
16.3K
27

没有更多内容

加载失败,请刷新页面

加载更多

Java 8 Stream Api 中的 skip 和 limit 操作

1. 前言 Java 8 Stream API 中的skip()和limit()方法具有类似的作用。它们都是对流进行裁剪的中间方法。今天我们来探讨一下这两个方法。 2. skip() skip(lang n) 是一个跳过前 n 个元素的...

码农小胖哥
36分钟前
1
0
看中华小当家第二集片段记录

最近正好在学习做饭,看看这片子,燃烧燃烧做饭的热情 哈哈,以下是摘的一些句子和个人理解 My name is Liu Mao Xing . More commonly known as Mao. 个人理解:我的名字叫 刘昴星, (commo...

T型人才追梦者
41分钟前
3
0
Python基础-6

1、注释 # 单行注释'''多行注释'''"""多行注释"""# 中文编码声明注释 ,在文件开头加上下面这行注释# encoding=utf-8或者# -*- encoding:utf-8 -*- (-*- 只是为了美观,没有实际......

zfskkk
41分钟前
5
0
我的这半年 / 2018 七夕著

浑然不觉,竟已至七夕, 今年已经过了一半 , 突然想给自己记录点什么 , 回顾下我的2018, 我的这上半年. 2018的第一件记事得从一月份下旬的那场大雪说起 , 一觉醒来 , 窗外整个银装素裹 , 在此之...

gxLong
46分钟前
3
0
NSS支持的数据库

NSS,简写自Name Service Switch。我把它译为“名字服务中心”。 在*nix操作系统中,NSS是C语言库(Library C或者glibc)的一部分,用以寻找名字。比如说,我们运行ls -lh查看一个目录中的文...

大别阿郎
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部