一个简单的Java EE&Docker示例


【编者的话】学习Docker的最好办法就是迅速在工作中应用它,本文作者使用Docker部署了一个Java EE应用,非常简单和方便。需要注意的是,由于作者写作时本地网络有问题,所以Dockerfile中很多的资源都没有从网络下载,你再实践时,可以尝试修改。学习快乐 :)

本文中,我们将会把Java EE和Docker结合,具体内容如下:
  • 创建、构建并运行一个Docker镜像;
  • 通过镜像启动一个Wildfly服务器,并部署了一个JavaEE示例应用;
  • 展示一些常用的Docker命令;
  • 启动多个容器,并让同一应用运行于不同端口。


引言

在这里我不再介绍Docker,因为已经有太多的介绍性的文章。写本文之前,我阅读了如下教程:


前提条件

要完成本教程,你需要:

  • 有一个运行于宿主机上的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),在这里我使用本机资源创建了一个镜像。因此,这个镜像只有在包含如下文件的目录下构建才能使用:
1.png

  • wildfly-8.2.0.Final:应用服务器
  • car-service.war:要部署的应用
  • Dockerfile:描述容器的文件
  • jdk-8u25-linux-x64.tar.gz:要在容器里安装的java版本



注意:不推荐在Docker容器中使用本地资源,因为只有当所有文件都存在时镜像才可以正常构建。最好的办法是从头安装所有东西并下载必要的文件。
这是Dockerfile的内容:
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命令。上述命令的输出如下:
2.png

然后我们可以通过列出镜像命令(译者注:docker images命令)来确认刚创建的镜像:docker -H tcp://127.0.0.1:2375 images
3.png

启动容器

使用这一命令启动容器:
docker -H tcp://127.0.0.1:2375 run -p 8180:8080 javaee_sample

  • -p指定容器端口到主机端口的映射;
  • run是命令本身;
  • javaee_sample是镜像名。


容器启动过程中会输出Wildfly启动日志,这是因为我们将其设置为初始命令(CMD Dockerfile命令):
4.png

运行多个容器

我们可以实例化多个容器,因为它们的端口在宿主上不会发生冲突。我将再启动两个容器并将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

现在我们可以在浏览器中同时访问这三个应用:
5.png

你可以通过容器的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"]
admln

admln 回复 admln

我明白了
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成启动,但是无法加载部署的应用

要回复文章请先登录注册