docker镜像的三种创建方式

一、创建镜像的方式

创建镜像有三种方法,分别为基于已有镜像创建、基于本地模板创建以及基于Dockerfile创建。

 1、基于现有基础镜像创建

先使用基础镜像创建一个容器,然后对容器进行修改,最后使用commit命令提交为一个新的镜像

第一步,启动一个基础镜像,在容器里修改

#根据基础镜像,创建容器
docker run --name mytomcat -p 8080:8080 -d tomcat

#修改容器
docker exec -it bcd08edac78d  /bin/bash
cd webapps/ROOT
rm -f index.jsp
echo welcome to tomcat > index.html
exit

第二步,将容器里面运行的程序及运行环境打包生成新的镜像

#提交为新镜像,语法:docker commit -m="描述消息" -a="作者" 容器id或容器名 镜像名:tag

docker commit
-m="修改默认索引页" -a="小洋" bcd08edac78d itany/tomcat:v1 说明: -m:说明信息 -a:作者信息 -p:生成过程中停止容器的运行 docker images 或docker inspect 新镜像名 #查看镜像信息

第三步,测试新镜像

#使用新镜像运行容器
docker run --name tomcat_v1 -p:8080:8080 -d itany/tomcat:v1

访问默认页:
http://ip:8080/
index.html

2、基于本地模板创建

(1)使用wget命令导入镜像包

通过导入操作系统模板文件生成新的镜像
wget http://download.openvz.org/template/precreated/debian-7.0-x86-minimal.tar.gz

(2)导入镜像

cat debian-7.0-x86-minimal.tar.gz | docker import - debian:yhw
docker images

(3)把镜像导入到容器中

docker run -it --name jc2 debian:yhw bash
ls

3、基于dockerfile创建

(1)联合文件系统(UnionFS)  

  UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。AUES、OverlayES及Devicemapper都是一种UnionFS
  Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像
  特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加教会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
  我们下载的时候看到的一层层的就是联合文件系统  

(2)镜像加载原理(bootfs、rootfs)

  Docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统是UnionES
  bootfs主要包含bootloader和kernel,bootloader主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统
•  在Docker镜像的最底层是bootfs,这一层与我们典型的Linux./tTnix系统是一样的,包含boot加载器和内核。当iboot加u载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs
  rootfs,在bootfs之上。包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu, centos等等
  我们可以理解成一开始内核里什么都没有,操作一个命令下载debian,这时就会在内核上面加了一层基础镜像;再安装一个emacs,会在基础镜像上叠加一层image;接着再安装一个apache,又会在images上面再叠加一层image。最后它们看起来就像一个文件系统即容器的rootfs。在Docker的体系里把这些rootfs叫做Docker的镜像。但是,此时的每一层rootfs都是read-only的,我们此时还不能对其进行操作。当我们创建一个容器,也就是将Docker镜像进行实例化,系统会在一层或是多层read-only的rootfs之上分配一层空的read-write的rootfs  

(3)为什么Docker里的centos的大小才200M?  

因为对于精简的OS,rootfs可以很小,只需要包含最基本的命令、工具和程序库就可以了,因为底层直接用宿主机的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。 

二、Dockerfile

1.Dockerfile 简介

1.1概述

•  Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如核名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变
  镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是Dockerfile
  Dockerfile是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。有了pockerfile,当我们需要定制自己额外的需求时,只需在Dockerfile上添加或者修改指令,重新生成image即可,省去了敲命令的麻烦
  除了手动生成Docker镜像之外,可以使用dockerfile自动生成镜像。Dockerfile是由多条的指令组成的文件,其中每条指令对应Linux中的一条命令,Docker程序将读取Dockerfile中的指令生成指定镜像 

​1.2Dockerfile结构

Dockerfile结构大致分为四个部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。

Dockerfile每天支持一条指令,每条指令可携带多个参数,支持使用“#”号开头的注释 

Dockerfile是用来构建Docker镜像的文件,是由一系列命令和参数构成的脚本

​Dockerfile从FROM命令开始,紧接着各种命令、参数等,最终会生成一个新的镜像

 1.3Dockerfile镜像结构的分层

镜像不是一个单一的文件,而是有多层构成。容器其实是在镜像的最上面加了一层读写层,在运行容器里做的任何文件改动,都会写到这个读写层。
如果删除了容器,也就删除了其最上面的读写层,文件改动也就丢失了。Docker使用存储驱动管理镜像每层内容及可读写层的容器层

(1)Dockerfile中的每个指令都会创建一个新的镜像层
(2)镜像层将被缓存和复用
(3)当Dockerfile的指令修改了,复制的文件变化了,或者构建镜像时指定的变量不同了,对应的镜像层缓存就会失效
(4)某一层的镜像缓存失效,它之后的镜像层缓存都会失效
(5)镜像层是不可变的,如果在某一层中添加一个文件,然后在下一层中删除它,则镜像中依然会包含该文件,只是这个文件在Docker容器中不可见了
(6)分层结构:共享资源、便于复用(许多镜像都是从相同的Base基础镜像构建而来的,基础镜像只需要保存一份)
(7)镜像都是只读的,而由镜像生成的容器是可修改的

​ 1.4使用Dockerfile构建镜像的步骤:

  1. 编写Dockerfile文件
  2. 使用docker build构建镜像
  3. 使用docker run运行容器

2. 用法

2.1 语法规则

  • 指令必须要大写,且后面必须跟参数
  • 第一条指令必须是FROM,指定Base Image 基础镜像
  • 指令按从上往下的顺序,依次执行
  • 每条指定都会创建一个新的镜像层并提交
  • #表示注释

2.2 docker执行dockerfile的流程

  • docekr从基础镜像运行一个容器
  • 执行一条指令并对容器做出修改
  • 执行类似docker commint的操作提交一个新的镜像层
  • docker再基于刚提交的镜像运行一个新容器
  • 执行dockerfile中的下一条指令直到所有指令都执行完

2.3 常用指令

指令解释 
FROM 指定基础镜像,即当前新镜像是基于哪个镜像的
格式:

FROM <image>

FROM <image>:<tag>

FROM <image>@<digest>

描述: tag和digest可选,不指定时,则使用latest版本基础镜像,digest表示V2
版本及以上版本镜像的内容可寻址标识符。 示例: FROM centos:
7
MAINTAINER 指定镜像作者命名和邮箱地址
格式:

MAINTAINER <name>

描述: name即为维护者信息,可自定义为姓名、邮箱地址等

示例:

MAINTAINER andya

MAINTAINER andya@163.com

MAINTAINER andya <andya@163.com>
RUN 指定构建过程中要执行的命令  格式:
    # shell执行
    RUN <command>
    # exec执行
    RUN ["executable", "param1", "param2"]
描述:
    1)Dockerfile的指令每执行一次都会在docker上新建一层,所以尽量合并RUN。
    2)exec执行格式是JSON数组,必须使用双引号描述。
    3)exec格式不调用命令行shell,需要使用shell格式或者路径。
如RUN [ "echo", "$HOME" ]不生效,
需要使用RUN [ "sh", "-c", "echo $HOME" ]。 示例: RUN yum install wget \ && tar -xvf demo.tar && chmod -R 777 /shell RUN /bin/bash -c 'source $HOME/.bashrc; \ echo $HOME' RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME' RUN ["/bin/bash", "-c", "echo hello"]
ENV 用来在构建镜像过程中设置环境变量  
格式:
    ENV <key> <value>
    ENV <key>=<value> ...
描述:
    1)ENV <key> <value> 中的<key>后面内容都作为<value>的内容,
所以一次只能设置一个变量
2)ENV <key>=<value> ... 可以设置多个变量,若遇到空格等可
使用\进行转义,或""进行标识 示例: ENV addressInfo suzhou xiancheng ENV addressCity=suzhou

 

WORKDIR 指定默认的工作目录,即进入容器后默认进入的目录,一个落脚点,默认不设置即为容器根目录/  
格式:
    WROKDIR <dir>
描述:
    1)设置工作目录后,Dockerfile后的命令RUN, CMD, ENTRYPOINT, 
COPY和ADD等命令,都在该目录下运行。
2)若不存在,则自动创建。 3)在docker run时,可以通过-w或--workdir进行覆盖。 4)在Dockerfile中可以多次使用,使用相对路径时, 会基于第一个进行拼接成绝对路径。 示例: # 此时工作目录为根目录/ WROKDIR / # 此时工作目录为/c WROKDIR c
VOLUME 创建挂载点,也称容器数据卷,用于数据共享和持久化  
格式:
    VOLUME ["<dir01>", "<dir02>", ...]
    VOLUME <dir>
描述:
    指定持久化目录,卷可以存在于一个或多个容器的指定目录
示例:
    VOLUME ["/data/data01", "/data/data02"]
    VOLUME /data
CMD

指定容器启动时要运行的命令,与RUN不同的是,这些命令不是在镜像构建过程中执行的

Dockerfile中可以又多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换

 
格式:
    # exec form, this is the preferred form
    CMD ["executable","param1","param2"] 
    # shell form
    CMD command param1 param2 
    # as default parameters to ENTRYPOINT
    CMD ["param1","param2"] 
描述:
    1)Dockerfile中若有多个CMD,则只有最后一个CMD有效。
    2)当CMD为ENTRYPOINT提供默认参数时,CMD和ENTRYPOINT都需要以JSON数组格式进行声明。
    3)同ENTRYPOINT,exec格式中CMD [ "echo", "$HOME" ]无效,需要指定sh -c,
如使用CMD [ "sh", "-c", "echo $HOME" ],当然,也可以直接使用shell格式:CMD echo $HOME 4)与RUN不同,RUN是docker build构建docker镜像时执行的命令,真正运行一个命令并提交运行结果。
CMD在build时期不执行任何东西,在docker run执行docker镜像构建容器时,为镜像声明了预期的命令。
ENTRYPOINT命令一定会执行,一般用于执行脚本。 示例: # exec格式 CMD [
"/usr/bin/wc","--help"] # shell格式 CMD echo "This is a test." | wc -

 

ENTRYPOINT

指定一个容器启动时要运行的命令 ENTRYPOINT和CMD一样,都是指定容器启动程序和参数

 
格式:
    # exec格式
    ENTRYPOINT ["executable", "param1", "param2"]
    # shell格式
    ENTRYPOINT command param1 param2
描述:
    1)shell格式的将会拒绝任何CMD或者run命令行的参数,将以/bin/sh -c开头,
只有exec格式的才可以在命令行中使用--entrypoint进行覆盖。 2)Dockerfile中只有最后一个ENTRYPOINT有效。 3)同RUN,exec格式中ENTRYPOINT [ "echo", "$HOME" ]无效,
需要指定sh -c,如使用ENTRYPOINT [ "sh", "-c", "echo $HOME" ] 示例: # exec格式 ENTRYPOINT ["top", "-b"] CMD ["-c"] # shell格式 ENTRYPOINT exec top -b
COPY

类似ADD 拷贝文件和目录到镜像中,但不可以自动解压文件,且不能访问网络资源

将从构建上下文目录中<源文件>的文件/目录复制到新的一层镜像内的<目标路径>位置 COPY src dest 或COPY [“src”,“dest”]

 
格式:
    COPY [--chown=<user>:<group>] <src>... <dest>
    COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
描述:
    1)[--chown=<user>:<group>]为可选参数,改变文件的所属者和属组。
    2)目标路径不存在时,会自动创建。
    
示例:
    COPY demo.tar demo01.tar
    COPY --chown=user01:group01 demo.tar demo02.tar

 

ADD 将宿主机目录下的文件拷贝文件到镜像中,且ADD命令会自动处理URL和自动解压tar压缩包  
格式:
    ADD <sourceDir1>... <dest>
    ADD ["<sourceDir1>", ... "<targetDir>"]
描述:
    1)用[],可以支持包含空格的路径。
    2)基本功能和格式同COPY。
示例:
    ADD demo.jar /app.jar
    ADD *.sh /shell
    ADD dir01 relativeDir/
    ADD dir02 /absoluteDir

 

EXPOSE 指定对外暴露的端口  
格式:
    EXPOSE <port> [<port>/<protocol>...]
描述:
    1)默认TCP协议。
    2)EXPOSE不是真正的发布该端口,需要在docker run中使用-p进行发布,
如docker run -p 80:80/tcp -p 80:80/udp。 示例: EXPOSE 8080 EXPOSE 10001/tcp 10002/udp
ONBUILD 当构建一个被继承的dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发  

HEALTHCHECK

健康检查  

2.4RUN、ENTRYPOINT和CMD区别

  1. RUN是docker build构建docker镜像时执行的命令,真正运行一个命令并提交运行结果。
  2. CMD在docker build时期不执行任何东西,在docker run执行docker镜像构建容器时,为镜像声明了预期的命令。存在多条CMD时,只会执行最后一条,当同时存在ENTRYPOINT时,CMD命令将充当参数(exec格式提供默认值)或者被覆盖。若不存在ENTRYPOINT时,则可以动态覆盖或执行命令。
  3. ENTRYPOINT命令一定会执行,一般用于执行脚本。shell格式的ENTRYPOINT命令,都不会执行在Dockerfile中存在CMD命令还是在docker run添加的命令。exec格式的ENTRYPOINT命令,CMD命令或docker run添加的命令,会被当做ENTRYPOINT命令的参数执行。
  • CMD

    在Dockerfile中可以有多个CMD指令,但只有最后一条指令生效,所以一般只有一条CMD指令

    CMD指令在被docker run之后的参数覆盖

    vi aaa
    FROM centos
    CMD ["/bin/ls"]
    CMD ["/bin/bash"]
    docker build -f aaa -t itany/aaa . 
    docker run -it itany/aaa
    docker run -it itany/aaa /bin/pwd
  • ENTRYPOINT

    docker run之后的参数会被作为ENTRYPOINT指令的参数,组合形成新的命令

    vi bbb
    FROM centos
    ENTRYPOINT ["/bin/ls","/usr/local"]
    docker build -f bbb -t itany/bbb .
    docker run -it itany/bbb
    docker run -it itany/bbb -l  #  ls /usr/local -l

2.5案例:

FROM cenos 

RUN yum install -y curl

CMD [ "curl", "-s", "http://ip.cn" ]

命令:docker build -f Dockerfile -t myip .

FROM cenos 

RUN yum install -y curl

ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]

命令:docker build -f Dockerfile -t myip .

ONBUILD应用

 

2.6构建新镜像语法

语法:

docker build -f Dockerfile文件的路径 -t 镜像名:tag 命令执行的上下文

2.7在编写Dockerfile时,要遵循的格式

(1)第一行必须使用FROM指令指明所基于的镜像名称
(2)之后使用MAINTAINER指令说明维护该镜像的用户信息
(3)然后是镜像操作相关指令,如RUN指令。每运行一条指令,都会给基础镜像添加新的一层
(4)最后使用CMD指令指定启动容器时要运行的命令操作

三、案例

1 自定义centos镜像

# 1.编写Dockerfile文件
vi Dockerfile2
    FROM centos

    MAINTAINER tangxiaoyang@itany.com

    ENV MYPATH /usr/local/centos
    RUN mkdir -p $MYPATH
    WORKDIR $MYPATH

    RUN yum -y install vim

    RUN yum -y install wget

    # 创建挂载点,无法指定宿主机上对应的目录,是自动生成的
    VOLUME  ["/data1","/data2"]

    CMD ["/bin/bash"]
# 2.使用docker build构建镜像
docker build -f Dockerfile2 -t itany/centos:v1 . 
# 3.使用docker run运行容器
docker run -it b25b1dad795c
# 查看镜像的变更历史
docker history b25b1dad795c
# 验证挂载点:
/var/lib/docker/volumes/0b001b4cc8db1ebbbb4c537c17a5c44adb700fb0e1b941bc82cc717c4ae196f6/_data
/var/lib/docker/volumes/f020f5a5664bf68312be9f49a640f27ecfb49990b231aaf3d0eb7cb723fa0ddd/_data

2 自定义tomcat镜像

# 准备工作 

# 1.编写Dockerfile文件
vi Dockerfile
    #base images: 基础镜像
   FROM centos
#维护者信息 MAINTAINER tangxiaoyang@itany.com # 把宿主机当前上下文的c.txt拷贝到容器
/usr/local/路径下 # 拷贝文件,文件必须与Dockerfile在同一目录下 COPY teacher.txt /usr/local #把java与tomcat添加到容器中 ADD jdk-8u171-linux-x64.tar.gz /usr/local ADD apache-tomcat-8.5.30.tar.gz /usr/local # 配置java和tomcat环境变量 ENV JAVA_HOME /usr/local/jdk1.8.0_171 ENV CLASSPATH .:$JAVA_HOME/lib ENV CATALINA_HOME /usr/local/apache-tomcat-8.5.30 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin ##设置工作访问时候的WORKDIR路径,登录落脚点 ENV MYPATH /usr/local #工作目录,类似cd进入工作目录
WORKDIR $MYPATH #WORKDIR $CATALINA_HOME #执行命令 RUN yum
-y install vim #容器运行时监听的端口 EXPOSE 8080 #启动时运行tomcat
#设定容器启动时第一个运行的命令及参数 # ENTRYPOINT [
"/usr/local/apache-tomcat-9.0.8/bin/startup.sh" ] # CMD ["/usr/local/apache-tomcat-9.0.8/bin/catalina.sh","run"] #CMD /usr/local/apache-tomcat-9.0.8/bin/startup.sh && tail -F /usr/local/apache CMD ["catalina.sh", "run"]
# 2.使用docker build构建镜像
docker build -t itany/tomcat:1.0 .   #末尾有“.”代表当前目录

#
3.使用docker run新镜像运行容器 docker run \ --name mytomcat \ -p 8080:8080 \ -v /my/tomcat/webapps/spring-web.war:/usr/local/apache-tomcat-8.5.30/webapps/spring-web.war \ -d itany/tomcat:1.0

 3、DOCKERFILE构建简单的微服务镜像

3.1拉取CONTOS7镜像

docker pull centos:7

 3.2制作jdk镜像

1)新建一个空文件夹jdk1.8,将jdk-8u211-linux-x64.tar.gz、Dockerfile上传到该目录

 2)编写vi  Dockerfile

#依赖镜像名称和ID(切记,跟你宿主机上centos镜像的名称一样,不要复制我的)
FROM /centos:7
#指定镜像创建者信息(随便写)
MAINTAINER IMMORT
#切换工作目录
WORKDIR /usr
RUN mkdir /usr/local/java
#ADD 是相对路径jar,把java添加到容器中
#(切记第一个jdk... 是你jdk文件的名字。不要复制我的,根据实际情况)
ADD jdk-8u211-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_211
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH

3)使用命令制作JDK1.8镜像

docker build -t='jdk1.8' .

-t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
注意: 后面有一个点。此命令在dockerfile所在文件目录下运行。jdk1.8文件也放在此目录下。

4)制作微服务

# 依赖镜像名称和ID
FROM jdk1.8
ADD app.jar /app.jar
# 暴露的端口
EXPOSE 1300
# RUN:用于执行后面跟着的命令行命令。
RUN bash -c 'touch /app.jar'
# CMD 指令允许用户指定容器的默认执行的命令。此命令会在容器启动且 docker run 没有指定其他命令时运行。
# 那么说白了,就是容器一启动,那么会自动使用java -jar 命令启动项目。
CMD ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

上传后的目录结构如下(与上面的jdk1.8的结构一样):

 使用DOCKER命令创建镜像

docker build -t='web1.1' .

4、基于Ubuntu/centos构建Java项目

1)建一个空文件夹docker-demo:

 2)将docker-demo.jar、jdk-8u171-linux-x64.tar.gz、Dockerfile上传到该目录

3)其中Dockerfile的内容如下:

# 指定基础镜像
FROM jdk1.8

# 拷贝java项目的包
ADD conf /opt/box-manage/conf
ADD bin/ /opt/box-manage/bin
ADD logs/ /opt/box-manage/logs
ADD lib/ /opt/box-manage/lib

#执行命令
#RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
RUN chmod +x /opt/safebox-manage/bin/start.sh

# 暴露的端口
EXPOSE 8080

#指定工作目录
WORKDIR /opt/box-manage

# CMD 指令允许用户指定容器的默认执行的命令。此命令会在容器启动且 docker run 没有指定其他命令时运行。
# 那么说白了,就是容器一启动,那么会自动使用java -jar 命令启动项目。
#CMD ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/opt/box-manage/lib/app.jar"]

#带参数启动
#ENTRYPOINT java -server -Xmx512m -Xms512m -Xmn256m -Xss256k -XX:MetaspaceSize=96m -jar /opt/box-manage/lib/app.jar --spring.profiles.active=prod

#执行脚本启动
CMD ["bash","/opt/box-manage/bin/start.sh"]


# 或者这样写 配置容器启动后执行的命令 ${JAVA_OPTS}:这样写,启动容器时可以添加JVM参数 ENTRYPOINT java ${JAVA_OPTS}
-jar /app.jar  #启动时也可以加JVM参数:# --cap-add=SYS_PTRACE 这个参数是让docker能支持在容器里能执行jdk自带类似jinfo,jmap这些命令,如果不需要在容器里执行这些命令可以不加 docker run -e JAVA_OPTS='-Xms1028M -Xmx1028M -Xmn512M -Xss512K -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M' --cap-add=SYS_PTRACE -d -p 8761:8761 javaweb1.0  注意:docker-demo.jar为maven打包后的jar包jdk-8u171-linux-x64.tar.gz为JDK的Linux版本,版本号为jdk1.8.0_171注意JDK版本之间要对应

============================================

#将启动命令写入启动脚本start.sh。
RUN mkdir -p /home/admin
RUN echo 'eval exec java -jar $CATALINA_OPTS /home/admin/app/app.jar'> /home/admin/start.sh && chmod +x /home/admin/start.sh
WORKDIR $ADMIN_HOME
CMD ["/bin/bash", "/home/admin/start.sh"]

启动脚本:

vi start.sh

#!/usr/bin/env bash

baseDir=$(cd "$(dirname "$0")"; pwd)
ROOT_DIR="${baseDir}/.."

export JAVA_HOME=$JAVA_HOME
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export LOG_HOME="${ROOT_DIR}/logs"

PIDFILE="${ROOT_DIR}/bin/service.pid"
#app name
APP_NAME=`ls ${ROOT_DIR}/lib/safebox-manage-biz-*.jar`
APP_CONF="${ROOT_DIR}/conf/application.yml"
#设置需要加载的包的目录 最后加上项目主包
CLASSPATH=".:${ROOT_DIR}/lib/*:${ROOT_DIR}/conf/*"
#这里可替换为你自己的执行程序,其他代码无需更改
ENV=pord

#设置虚拟机参数
JAVA_OPTS="-server -Xmx512m -Xms512m -Xmn256m -Xss256k -XX:MetaspaceSize=96m"
JAVA_OPTS="$JAVA_OPTS -XX:+DisableExplicitGC"
JAVA_OPTS="$JAVA_OPTS -XX:+UseConcMarkSweepGC"
JAVA_OPTS="$JAVA_OPTS -XX:CMSMaxAbortablePrecleanTime=5000"
JAVA_OPTS="$JAVA_OPTS -XX:+CMSClassUnloadingEnabled "
JAVA_OPTS="$JAVA_OPTS -XX:+CMSParallelRemarkEnabled"
JAVA_OPTS="$JAVA_OPTS -XX:+UseFastAccessorMethods"
JAVA_OPTS="$JAVA_OPTS -XX:+UseCMSInitiatingOccupancyOnly"
JAVA_OPTS="$JAVA_OPTS -XX:+ExplicitGCInvokesConcurrent"
JAVA_OPTS="$JAVA_OPTS -XX:CMSInitiatingOccupancyFraction=80"
JAVA_OPTS="$JAVA_OPTS -XX:SurvivorRatio=10"
JAVA_OPTS="$JAVA_OPTS -XX:MaxDirectMemorySize=1g"
JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$LOG_HOME/java.hprof"
JAVA_OPTS="$JAVA_OPTS -Xloggc:$LOG_HOME/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
JAVA_OPTS="$JAVA_OPTS -Dlog_path=$LOG_HOME"

#PARAM="--spring.config.location=${APP_CONF} --spring.profiles.active=${ENV}"
PARAM="--spring.profiles.active=${ENV}"

#采用加载所有jar 和指定 main class 启动方式

  #该条shell命令将不会输出任何信息到控制台,也不会有任何信息输出到文件中
  >/dev/null 2>&1 &

#nohup exec java ${JAVA_OPTS} -classpath ${CLASSPATH} -jar $APP_NAME ${PARAM} >/dev/null 2>&1 &
#nohup java ${JAVA_OPTS} -classpath ${CLASSPATH} -jar $APP_NAME ${PARAM} &
exec java ${JAVA_OPTS} -classpath ${CLASSPATH} -jar $APP_NAME ${PARAM}

4)构建镜像

docker build -t javaweb:1.0 .

5、基于java8构建Java项目

构建java项目的镜像,可以在已经准备了JDK的基础镜像基础上构建。

需求:基于java:8-alpine镜像,将一个Java项目构建为镜像

1)修改Dockfile的内容如下:

# 指定基础镜像
FROM java:8-alpine

# 拷贝Java项目的包
COPY ./docker-demo.jar /opt/app.jar
ADD config /opt/config

#设置运行时工作目录
WORKDIR /opt

# 暴露端口
EXPOSE 8090

# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar

2)构建镜像

docker build -t javaweb:2.0 .

posted on 2023-03-30 14:12  uestc2007  阅读(386)  评论(0编辑  收藏  举报

导航