如何把java 应用 制作成docker镜像

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何把java 应用 制作成docker镜像相关的知识,希望对你有一定的参考价值。

利用Dockerfile构建一个简单的java应用镜像,依赖环境比较简单,JDK,定制化的Tomcat(名为star-appserver)
1、环境准备
ubuntu:14.04
docker : 1.4
jdk:jdk-8u31-linux-x64.gz
tomcat : 7.0(star-appserver)
在/usr/local下创建目录:sms,将jdk-8u31-linux-x64.gz和star-appserver(此处为了简单,已包含应用)拷贝到此目录下,由于Docker在构建镜像时,需将Dockerfile所在目录传给Docker daemon作为构建上下文,所以此目录下应包含构建时所依赖的各种环境。
2、环境准备好后,在sms下创建Dockerfile(名字必须为Dockerfile)文件,内容如下
FROM ubuntu:latest
MAINTAINER zhangjy

#install JDK and TOMCAT
ADD jdk-8u31-linux-x64.gz /usr/local/
ADD tomcat /usr/local/ #tomcat下为star-appserver,如果直接复制star-appserver,只会复制目录里边的内容,不会复制目录本身
ADD timezone /etc/
#启动脚本,用于从镜像启动容器时调用执行,见下面的ENTRYPOINT
ADD onStart.sh /usr/local/

ENV JAVA_HOME=/usr/local/jdk1.8.0_31 CLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar PATH=$PATH:$JAVA_HOME/bin
RUN echo "JAVA_HOME=/usr/local/jdk1.8.0_31\nCALSSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar\nPATH=$PATH:$JAVA_HOME/bin" >> /etc/profile

#start tomcat
ENTRYPOINT ["/usr/local/onStart.sh"]
3、在sms下创建onStart.sh,并赋予执行权限,用于启动tomcat并输出日志(为了保证容器中有执行状态的进程,否则容器停止)
#!/bin/bash
/usr/local/star-appserver/bin/startup.sh
tail -f /usr/local/star-appserver/logs/stariboss.log
4、在sms下执行命令,创建成功
$docker build -t zhangjy/starsms:v1 .

启动时,发现应用访问数据库报错:ORA-01882: timezone region not found,原因是JVM默认使用Ubuntu的/etc/timezone里配置的时区,查看timezone时区为Etc/UTC,再查看ORACLE数据库支持的时区:select * from V$TIMEZONE_NAMES发现没有,于是又在sms目录下创建了一个timezone文件,将时区配置成Asia/Shanghai,在Dockerfile中加入到镜像/etc/目录下
Dockerfile文件配置说明:

FROM
表明基于哪个镜像创建
MAINTAINER
作者和邮箱
ADD
将目录或文件加入到镜像的某个目录,格式是ADD <源文件> <目标目录>
RUN
有两种格式:
RUN <command> (the command is run in a shell - /bin/sh -c - shell form)
RUN ["executable", "param1", "param2"] (exec form)
默认RUN后的命令是在/bin/sh下执行,像Ubuntu默认/bin/sh是指向/bin/dash,如果想使用/bin/bash,则可按如下方式
RUN ["/bin/bash","-c","source /etc/profile"]
但需注意,这种方式不能解析类似于$HOME的参数引用
ENV
设置环境变量,在镜像构建过程中和容器启动后均有效
CMD
CMD在容器运行的时候提供一些命令及参数,用法如下:
CMD ["executable","param1","param2"] (exec form, this is the preferred form) CMD ["param1","param2"] (as default parameters to ENTRYPOINT) CMD command param1 param2 (shell form)

- 第一种用法:运行一个可执行的文件并提供参数。
- 第二种用法:为ENTRYPOINT指定参数,即为ENTRYPOINT指定命令的默认参数,通过docker run命令传过来的参数会将其覆盖
- 第三种用法(shell form):是以”/bin/sh -c”的方法执行的命令。
如指定:
1. CMD [“/bin/echo”, “this is a echo test ”]

build后运行(假设镜像名为ec):
1. docker run ec

就会输出: this is a echo test
注意:如果在docker run命令后指定命令,如docker run ec echo 'test',会将CMD的命令覆盖。CMD的命令不能接收run传过来的参数,而ENTRYPOINT可以
ENTRYPOINT
有两种用法
ENTRYPOINT ["executable", "param1", "param2"] (the preferred exec form)
ENTRYPOINT command param1 param2 (shell form)
第一种可以接收docker run命令传过来的参数(即使docker run传过来的是命令,也会被当做参数处理),如果想覆盖,可使用docker run ... --entrypoint <COMMAND>
参考技术A 初次安装部署好docker后,大多数镜像可以从DockerHub提取,但是大多数人都希望自己可以完全自定义一个镜像,那么这里需要一个第三方工具febootstrap  epel6的源提供febootstrap的RPM包  yuminstalldocker-iofebootstrap-y  servicedockerstart  chkconfigdocker--level35on复制代码  制作CentOS6.6镜像目录  febootstrap-iyum-iiputils-iiproute-ibash-ivim-minimal-icoreutils-itar-inet-toolscentos6base  /centos/6.6/updates/x86_64/复制代码  -i表示镜像里面安装的RPM包(包括一些人为有必要的软件包)  centos6表示镜像的版本说明  base表示生成的镜像目录  后面之后了系统安装源和更新源为USTC  安装执行后,会开始一系列的RPM包下载安装,过程与yum类似,安装完成后当前目录会多了base目录,里面就是一个镜像的系统文件  进入base目录等于进入镜像的根目录  [root@image~]#cdbase/  [root@imagebase]#ls  binbootdevetchomeliblib64mediamntoptprocrootsbinselinuxsrvsystmpusrvar复制代码  可以像一般的系统文件一样先做一些修改配置,例如配置第三方yum源等等  把base目录把所有文件打包成二进制文件后导入docker创建为镜像  cd~/root/base/&&tar-c.|dockerimport-centos6:base复制代码  dockerimages可以查看镜像的信息  一个基本centos镜像创建完毕,下面再利用Dokcerfile制作mysql镜像  catDockerfile  FROMcentos6:base  MAINTAINERLion"lioncui@163.com"  VOLUME/var/lib/mysql  RUNyuminstallmysql-servermysql-y  RUNecho-ne"NETWORKING=yes\\nHOSTNAME=mysql">/etc/sysconfig/network  RUNecho-ne"bind-address=0.0.0.0\\ndefault-storage-engine=innodb\\ninnodb_file_per_table\\n\collation-server=utf8_general_ci\\ninit-connect='SETNAMESutf8'\\ncharacter-set-server=utf8">insert  RUNsed-i"/user=mysql/rinsert"/etc/my.cnf&&rm-finsert  RUNecho-ne"/usr/bin/mysql_install_db\\n/usr/bin/mysqld_safe">>/opt/mysql_start  RUNchmod777/opt/mysql_start  ENVPATH/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:  WORKDIR/opt  EXPOSE3306  CMD/bin/sh-cmysql_start复制代码  FROM声明以centos:base镜像为基础  MAINTAINER声明镜像的维护者信息  VOLUME挂载本地目录到容器里/var/lib/mysql目录(这是mysql默认的数据保存目录)  由于我希望数据可以持久化防止因为容器误删除而丢失,所以映射到宿主本地目录  RUN在镜像中执行安装mysql  在新镜像中写入HOSTNAME信息,因为mysql启动过程需要network文件  在my.cnf配置文件插入一些修改配置  创建启动脚本  声明环境变量  制定默认工作目录  EXPOSE声明容器需要暴露的端口号  CMD是指镜像生成容器后自动执行的命令,类似dockerexec,这里是自动启动mysql服务  根据Dockerfile创建mysql服务镜像  dockerbuild--rm=true-tmysql:frist.  查看镜像的树状关系可以发现,mysql:frist是以centos:base为父镜像

Docker Dockerfile

一、什么是 Dockerfile

比如我想制作一个镜像,这个镜像安装了 lnmp 、redis 、elk 等各种软件,制作流程会是这样:

① 先下载一个基础镜像,如 centos
② 使用这个镜像启动成一个容器
③ 在容器中安装 lnmp 、redis 、elk 等各种软件
④ 最后再把容器制作成一个镜像

什么是 Dockerfile:Dockerfile 相当于一个命令集 ( 命令的集合 ) 文件,我们可以把上面的步骤都写到这个文件,然后执行这个文件就能生成一个镜像


二、Dockerfile 常用指令

FROM          # 指定基于哪个镜像,语法:FROM <image> 或 FROM <image>:<tag>,如 FROM centos:latest
MAINTAINER    # 指定Dockerfile文件的作者信息,语法:MAINTAINER <name> <mail>,如 MAINTAINER xiaoming [email protected]
RUN           # 指定要操作的命令,语法:RUN <command>,如 RUN yum install redis,如果命令有选项必须写成 RUN ["yum", "install", "-y", "redis"]
CMD           # 指定容器启动时要执行的命令,语法:CMD <command>,如 CMD yum install redis,如果命令有选项必须写成 CMD ["yum", "install", "-y", "redis"]
EXPOSE        # 指定容器要开放的端口,以便外部能访问,如 EXPOSE 22 80 443 表示开放 22 80 443 这三个端口,但必须结合 docker -p 80:80 这种形式来使用
ENV           # 用于定义环境变量,如 ENV PATH /usr/local/bin:$PATH,也可以自定义用户变量,如 EVN MySQL_Version 5.6,定义的变量可以让 RUN 或 CMD 使用
ADD           # 用于拷贝宿主机的文件到容器的某个目录里,语法:ADD <src> <dest>,如 ADD 1.txt /data 表示拷贝宿主机的1.txt到容器的/data目录,<src>也可以是一个url
COPY          # 用法与ADD一致,不同的是,ADD可以使用url,COPY不能使用url
ENTRYPOINT    # 指定容器启动时要执行的命令,用法与CMD一致,不同的是,CMD的命令会被覆盖,比如 docker run -itd centos bash 去启动容器时,bash就是启动容器时执行的命令
              # 而如果我们写了 CMD echo 123 是不会执行的,因为被bash命令覆盖了,而我们使用ENTRYPOINT就不会被覆盖,而且会优先执行ENTRYPOINT指定的命令再执行bash命令
              # 另外一点,如果我们再Dockerfile文件中写了多条CMD指令,那么只有最后一条会执行,使用ENTRYPOINT则每一条都会执行
VOLUME        # 指定挂载目录,如 VOLUME ["/data"] 表示把宿主机的/data目录挂载到容器里,但不会指定挂载到容器里的哪个目录,需要使用 docker inspect 来查看,参考链接
USER          # 指定启动容器的用户,如 USER root 表示使用 root 用户来启动容器
WORKDIR       # 指定工作目录,对 RUN,CMD,ENTRYPOINT,COPY,ADD 生效,比如 WORKDIR /data,那么我执行 RUN echo 123 相当于执行 cd /data; echo 123


三、Dockerfile 实例:安装 Nginx

 

 

 

 

    

以上是关于如何把java 应用 制作成docker镜像的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 的项目打包成的 JAR 包,制作成 docker 镜像并运行

怎么把秒开服务器打包成镜像

怎么把docker里面已经创建的容器删除

通过IDEA制作包含Java应程序的Docker镜像

Java程序制作Docker镜像 推荐方案

Docker Dockerfile