Run vertx in Docker - downgoon/hello-world GitHub Wiki
在Docker中运行vertx
本演示包含以下几步:
-
样例代码: 用vertx官方的docker-java样例代码 vertx-examples/docker-examples/vertx-docker-java
-
构建Docker镜像: 有了Java项目,需要编写一个Dockerfile (这里我们直接使用样例代码中自带的),以便构建Docker镜像。
-
运行Docker镜像: 构建完镜像后,可以运行它。也可以分发到其他机器上去运行。
注意
关于代码编译,可以选择在本地编译好,复制到Docker镜像中;也可以选择把代码复制到Docker容器中,然后在Dockerfile中描述编译过程。
获取样例代码
$ git clone https://github.com/vert-x3/vertx-examples.git
$ cd vertx-examples/docker-examples/vertx-docker-java
$ vertx-docker-java git:(master) ✗ ll
total 16
-rw-r--r-- 1 liwei staff 600B 11 4 14:14 Dockerfile
-rw-r--r-- 1 liwei staff 1.2K 11 4 14:14 pom.xml
drwxr-xr-x 3 liwei staff 102B 11 4 14:14 src
注意
官方样例代码我们只需要
vertx-docker-java
,如果只想通过git下载某个目录,请参考 git clone 子目录。
查看Dockerfile
###
# vert.x docker example using a Java verticle
# To build:
# docker build -t sample/vertx-java .
# To run:
# docker run -t -i -p 8080:8080 sample/vertx-java
###
# Extend vert.x image
FROM vertx/vertx3
ENV VERTICLE_NAME io.vertx.sample.hello.HelloVerticle
ENV VERTICLE_FILE target/hello-verticle-3.3.3.jar
# Set the location of the verticles
ENV VERTICLE_HOME /usr/verticles
EXPOSE 8080
# Copy your verticle to the container
COPY $VERTICLE_FILE $VERTICLE_HOME/
# Launch the verticle
WORKDIR $VERTICLE_HOME
ENTRYPOINT ["sh", "-c"]
CMD ["exec vertx run $VERTICLE_NAME -cp $VERTICLE_HOME/*"]
几点说明
- 基础镜像: 这个Dockerfile 依赖的基础镜像是
FROM vertx/vertx3
。 - 运行命令: 运行程序的命令是
vertx run io.vertx.sample.hello.HelloVerticle -cp /usr/verticles/*
,不是直接的java -jar XXX
,而是运行在vertx
自有容器上。这个容器有支持类似java的-cp
参数,只不过它更人性化,支持统配符。 - 字节码包: 上面的命令最终运行的字节码文件是
target/hello-verticle-3.3.3.jar
,从本地拷贝到Image里面的。也就是说,在docker build
之前,必须现在本地mvn package
构建出target/hello-verticle-3.3.3.jar
,因为Dockerfile文件本身没有描述mvn编译过程。
本地编译
为生成Dockerfile中需要的target/hello-verticle-3.3.3.jar
文件,在宿主机本地运行mvn package
。另外,由于vertx基于Java8,所以宿主机需要JDK8。
➜ vertx-docker-java git:(master) ✗ mvn clean package
➜ vertx-docker-java git:(master) ✗ file target/hello-verticle-3.3.3.jar
target/hello-verticle-3.3.3.jar: Zip archive data, at least v1.0 to extract
构建Docker镜像
在vertx-examples/docker-examples/vertx-docker-java
目录下执行:
docker build -t downgoon/vertx-java .
生成一个名叫downgoon/vertx-java
的镜像。我们可以docker images
查看一下:
➜ vertx-docker-java git:(master) ✗ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
downgoon/vertx-java latest 2a02dfa75b82 27 minutes ago 194.3 MB
运行Docker镜像
$ docker run -t -i -p 9090:8080 downgoon/vertx-java
Succeeded in deploying verticle (运行成功后,输出的内容)
项目vertx-java
监听了8080端口,我们通过宿主机的9090端口映射到容器的8080端口。
我们可以通过 docker ps
查看当前运行的容器:
➜ vertx-docker-java git:(master) ✗ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c64afb3b57dc downgoon/vertx-java "sh -c 'exec vertx ru" 28 minutes ago Up 28 minutes 0.0.0.0:9090->8080/tcp backstabbing_roentgen
注意
docker run -t -i
的-i
是运行在前台(交互方式)的意思,如果运行到后台,用-d
参数。
测试访问
➜ ~ curl -i http://localhost:9090
HTTP/1.1 200 OK
Content-Length: 18
Hello Java world !%
回顾小结
在Docker容器中运行你的Java程序,仅仅需要在你原来的Java程序中,增加一个Dockerfile脚本文件。 这个脚本文件就是一种规约,这个规约描述了请运维人员如何运行你的程序。
之所以用“规约”这个词,是因为在Docker出现之前,如果你让运维运行你的程序,你可以有两种方式:
- 写个文档: 文档里面一步步描述了改如何运行这个程序。比如需要安装Java8,需要Maven,然后需要开启4567端口等等。
- 写个bash脚本: 文档描述沟通效率低下,如果想自动化,我们可以写一个bash脚本,让bash脚本把这个事情都做了。但是bash需要依赖外部很多资源,缺乏一个集中管理的机制。
Docker的出现,有一个非常厉害的地方,就是把这些都标准化了,制定成了一种规约。RD与OP之间的交流,仅限一个Dockerfile。
参考资料
附录-1:Vertx 规范
本文的实例只有一个代码文件,如下:
package io.vertx.sample.hello;
import io.vertx.core.AbstractVerticle;
public class HelloVerticle extends AbstractVerticle {
@Override
public void start() throws Exception {
vertx.createHttpServer().requestHandler(request -> {
request.response().end("Hello Java world !");
}).listen(8080);
}
}
它继承了AbstractVerticle
,运行的时候不是用java -jar XXX.jar
,而是vertx run XXX.jar
。
我们可以把Verticle
与vertx
的关系类比成Servlet
与Tomcat/Jetty/Resin
的关系。只不过Servlet
是J2EE的规范,而Verticle
是Vertx
的规范。正如Vertx
官方说的,Vertx
是一个“工具集”,它自成一个体系,完全独立于J2EE。
附录-2:让vertx在容器云商上运行
如何把刚才的代码,运行在网易蜂巢(一个Docker云提供商,地址 c.163.com)呢? 网易云提供什么呢?Docker云。它能把Image运行成Container,但运行这个之前,它得解决Image问题。那么网易云提供什么机制,让用户构建用户自己的Image呢?有3种方式:
- 在线拉代码: 用户提供一个github源代码地址,同时项目中含有Dockerfile文件。网易云能把github的代码拉取下来,并且运行其中的Dockerfile脚本文件,构建出镜像。但这种方式可能有两个问题:
- 没有Dockerfile: 如果源代码中没有Dockerfile,那么构建时候,网易云支持用户上传Dockerfile。
- 无效Dockerfile: 代码中虽然有Dockerfile,但是不适合网易云。比如本文的vertx,虽然有Dockerfile,但是它要求先用mvn编译出target/XXX.jar,Dockerfile只是把编译好的XXX.jar拷贝到镜像中。为此网易云提供“拉代码,mvn编译”,但是实现方式依赖于在Dockerfile中描述mvn编译。网易云官方帮助-构建时编译代码
- 上传本地镜像:用户可以在本地自己制作镜像,然后上传到网易云。网易云官方帮助-上传本地镜像
- 从容器导出: 用户可以先选择一个已经存在的镜像,比如centos镜像,把它运行起来,然后自己手动安装一些东西,比如直接部署一个vertx,然后把它“保存为镜像”。
构建时编译代码
在Dockerfile中描述:
FROM hub.c.163.com/public/tomcat:7.0.28
MAINTAINER netease
RUN apt-get update && apt-get install -y maven openjdk-7-jdk
COPY . ~/java
WORKDIR ~/java
RUN mvn package && cp -rf ~/java/target/robot-dt2/* /var/lib/tomcat7/webapps/ROOT/
ENTRYPOINT /etc/init.d/tomcat7 start
把vertx的实例Dockerfile修改成“增加安装maven”,发现失败了基础镜像无法运行 RUN apt-get update && apt-get install -y maven
。
###
# vert.x docker example using a Java verticle
# To build:
# docker build -t downgoon/vertx-hello .
# To run:
# docker run -t -i -p 8080:8080 downgoon/vertx-hello
###
# Extend vert.x image
FROM vertx/vertx3
ENV VERTICLE_NAME io.vertx.sample.hello.HelloVerticle
ENV VERTICLE_FILE target/hello-verticle-3.3.3.jar
# Set the location of the verticles
ENV VERTICLE_HOME /usr/verticles
EXPOSE 8080
# install maven
RUN apt-get update && apt-get install -y maven
# Copy source to the container
COPY . $VERTICLE_HOME
WORKDIR $VERTICLE_HOME
RUN mvn package
# Launch the verticle
ENTRYPOINT ["sh", "-c"]
CMD ["exec vertx run $VERTICLE_NAME -cp $VERTICLE_HOME/*"]