一个简单的Java EE&Docker示例
【编者的话】学习Docker的最好办法就是迅速在工作中应用它,本文作者使用Docker部署了一个Java EE应用,非常简单和方便。需要注意的是,由于作者写作时本地网络有问题,所以Dockerfile中很多的资源都没有从网络下载,你再实践时,可以尝试修改。学习快乐 :)
本文中,我们将会把Java EE和Docker结合,具体内容如下:
- 创建、构建并运行一个Docker镜像;
- 通过镜像启动一个Wildfly服务器,并部署了一个JavaEE示例应用;
- 展示一些常用的Docker命令;
- 启动多个容器,并让同一应用运行于不同端口。
引言
在这里我不再介绍Docker,因为已经有太多的介绍性的文章。写本文之前,我阅读了如下教程:- Docker用户指南;
- 使用Docker镜像;
- Docker终极指南(译者注:已翻译);
- Arun Gupta的技术技巧:#39、#57、#61和#65。
前提条件
要完成本教程,你需要:
有一个运行于宿主机上的Docker后台进程
- 安装Docker后,在etc\default\docker文件中添加一行:DOCKER_OPTS="-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock
- 此后重启机器并尝试运行这个命令:
docker -H tcp://127.0.0.1:2375 –version
,输出应该类似这样的:Docker version 1.4.1, build 5bc2ff8
- 一个Wildfly 8.2.0的安装程序(解压后的);
- jdk-8u25-linux-x64.tar.gz文件;
- 在此下载 car-service.war;
- 在此下载 Dockerfile。
创建Docker镜像
Docker镜像展现/描述了容器本身。由于我的网络带宽有限(手机3G),在这里我使用本机资源创建了一个镜像。因此,这个镜像只有在包含如下文件的目录下构建才能使用:- wildfly-8.2.0.Final:应用服务器
- car-service.war:要部署的应用
- Dockerfile:描述容器的文件
- jdk-8u25-linux-x64.tar.gz:要在容器里安装的java版本
这是Dockerfile的内容:
注意:不推荐在Docker容器中使用本地资源,因为只有当所有文件都存在时镜像才可以正常构建。最好的办法是从头安装所有东西并下载必要的文件。
FROM ubuntu
MAINTAINER Rafael Pestano <rmpestano@gmail.com>
setup WildFly
COPY wildfly-8.2.0.Final /opt/wildfly
install example app on wildfy
COPY car-service.war /opt/wildfly/standalone/deployments/
setup Java
RUN mkdir /opt/java
COPY jdk-8u25-linux-x64.tar.gz /opt/java/
change dir to Java installation dir
WORKDIR /opt/java/
RUN tar -zxf jdk-8u25-linux-x64.tar.gz
setup environment variables
RUN update-alternatives --install /usr/bin/javac javac /opt/java/jdk1.8.0_25/bin/javac 100
RUN update-alternatives --install /usr/bin/java java /opt/java/jdk1.8.0_25/bin/java 100
RUN update-alternatives --display java
RUN java -version
Expose the ports we're interested in
EXPOSE 8080 9990
Set the default command to run on boot
This will boot WildFly in the standalone mode and bind to all interface
CMD ["/opt/wildfly/bin/standalone.sh", "-c", "standalone-full.xml", "-b", "0.0.0.0"]
镜像继承自Ubuntu——一个安装了Ubuntu操作系统的镜像。Docker安装教程中就安装了Ubuntu镜像。
接着,我们将服务器复制到容器的/opt/wildfly目录。COPY是Dockerfile的一个指令。我们可以在这里找到所有命令。
我们随后将应用的war包复制到服务器中:
COPY car-service.war /opt/wildfly/standalone/deployments/
。然后,我们将Java解压安装到容器的/opt/java目录并设置一些环境变量。最好的办法是使用apt-get,不过这要求有互联网接入,而我写作时不具备这个条件。我使用RUN命令来执行
java -version
,(如果Java正确安装的话)它将在镜像构建时打印版本号。之后,我使用
EXPOSE 8080 9990
来告诉Docker容器要暴露的端口号。容器其实是镜像的实例,运行镜像(docker run
)时,我们可以指定允许宿主访问的端口。最后,我们指定了默认命令:CMD ["/opt/wildfly/bin/standalone.sh", "-c", "standalone-full.xml", "-b", "0.0.0.0"]。每次容器启动时都会运行这个命令。
构建镜像
在描述完镜像之后,我们需要构建它。在包含Dockerfile的父目录运行以下命令:docker -H tcp://127.0.0.1:2375 build -t javaee_sample java_ee/
- -H参数指定了Docker后台地址(使用TCP与后台通讯);
- build是命令本身;
- -t指定了用于识别镜像的标签名称(这里是javaee_sample);
- java_ee/是包含用于描述镜像的Dockerfile的目录。
可在此找到更多Docker命令。上述命令的输出如下:
然后我们可以通过列出镜像命令(译者注:docker images命令)来确认刚创建的镜像:
docker -H tcp://127.0.0.1:2375 images
:启动容器
使用这一命令启动容器:docker -H tcp://127.0.0.1:2375 run -p 8180:8080 javaee_sample
- -p指定容器端口到主机端口的映射;
- run是命令本身;
- javaee_sample是镜像名。
容器启动过程中会输出Wildfly启动日志,这是因为我们将其设置为初始命令(CMD Dockerfile命令):
运行多个容器
我们可以实例化多个容器,因为它们的端口在宿主上不会发生冲突。我将再启动两个容器并将8080端口分别暴露为8280和8380:docker -H tcp://127.0.0.1:2375 run -p 8280:8080 javaee_sample
docker -H tcp://127.0.0.1:2375 run -p 8380:8080 javaee_sample
要列出启动的容器,我们可以使用命令:
docker -H tcp://127.0.0.1:2375 ps
,这是输出结果:rmpestano@rmpestano-ubuntu:~/docker /images$ docker -H tcp://127.0.0.1:2375 ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b9079806e69 javaee_sample:latest "/opt/wildfly/bin/st 27 seconds ago Up 27 seconds 9990/tcp, 0.0.0.0:8280->8080/tcp suspicious_lovelace
d4975e825751 javaee_sample:latest "/opt/wildfly/bin/st 28 seconds ago Up 28 seconds 9990/tcp, 0.0.0.0:8380->8080/tcp loving_hopper
96e58eb65126 javaee_sample:latest "/opt/wildfly/bin/st 42 seconds ago Up 42 seconds 9990/tcp, 0.0.0.0:8180->8080/tcp clever_cori
现在我们可以在浏览器中同时访问这三个应用:
你可以通过容器的ID或名字来停止容器:
docker -H tcp://127.0.0.1:2375 stop suspicious_lovelace
记住,在容器删除时所有数据将消失。请使用Docker卷来持久化数据。
原文:A SIMPLE JAVA EE DOCKER EXAMPLE (翻译:梁晓勇 校对:李颖杰)
4 个评论
问一个问题,为什么tomcat不可以啊?
CMD ["/usr/tomcat/apache-tomcat-7.0.57/bin/startup.sh","-c"]
CMD ["/usr/tomcat/apache-tomcat-7.0.57/bin/startup.sh","-c"]
OneAPM 可以智能探知 Java 应用之间的相互调用关系,通过串联复杂的后台组件,动态生成 J2EE 应用整体架构视图。在图中通过简单的点击钻取您可以逐级深入,查看对代码级别的诊断数据。快来官网注册试用吧~
您好,我是个新手,我按照您的例子走一边,老是出错:12:06:21,237 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-5) MSC000001: Failed to start service jboss.deployment.unit."car-service.war".STRUCTURE: org.jboss.msc.service.StartException in service jboss.deployment.unit."car-service.war".STRUCTURE: JBAS018733: Failed to process phase STRUCTURE of deployment "car-service.war"
能看到wildfly成启动,但是无法加载部署的应用
能看到wildfly成启动,但是无法加载部署的应用