Docker化Java应用程序

当你对Java应用程序进行容器化操作时,Dockerfile 文件是你要用到的基础组件。

Dockerfile指令介绍

这部分内容请查看官方文档:https://docs.docker.com/engine/reference/builder/

为简单的Java工程编写Dockerfile

由于 官方 已经有了OpenJDK 镜像,因此我们不需要为 OpenJDK 再写一个Dockerfile。

我们这里来为 OracleJDK 创建一个Dockerfile,这个官方并未提供。

编写Dockerfile

新建一个文件夹,并在其中新建一个名为 Dockerfile 的文件,里面内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Dockerfile

FROM phusion/baseimage:0.9.17

MAINTAINER Author Name <author@email.com>

RUN echo "deb http://archive.ubuntu.com/ubuntu trusty main universe" > /etc/apt/sources.list

RUN apt-get -y update

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y -q python-software-properties software-properties-common

ENV JAVA_VER 8
ENV JAVA_HOME /usr/lib/jvm/java-8-oracle

RUN echo 'deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main' >> /etc/apt/sources.list && \
echo 'deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main' >> /etc/apt/sources.list && \
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C2518248EEA14886 && \
apt-get update && \
echo oracle-java${JAVA_VER}-installer shared/accepted-oracle-license-v1-1 select true | sudo /usr/bin/debconf-set-selections && \
apt-get install -y --force-yes --no-install-recommends oracle-java${JAVA_VER}-installer oracle-java${JAVA_VER}-set-default && \
apt-get clean && \
rm -rf /var/cache/oracle-jdk${JAVA_VER}-installer

RUN update-java-alternatives -s java-8-oracle

RUN echo "export JAVA_HOME=/usr/lib/jvm/java-8-oracle" >> ~/.bashrc

RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

CMD ["/sbin/my_init"]

设置基础镜像与作者

1
2
3
4
5
# Dockerfile

FROM phusion/baseimage:0.9.17

MAINTAINER Author Name <author@email.com>

更新Ubuntu源地址

1
2
3
RUN echo "deb http://archive.ubuntu.com/ubuntu trusty main universe" > /etc/apt/sources.list

RUN apt-get -y update

安装python-software-properties

1
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y -q python-software-properties software-properties-common
安装Oracle Java 8
1
2
3
4
5
6
7
8
9
10
11
ENV JAVA_VER 8
ENV JAVA_HOME /usr/lib/jvm/java-8-oracle

RUN echo 'deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main' >> /etc/apt/sources.list && \
echo 'deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main' >> /etc/apt/sources.list && \
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C2518248EEA14886 && \
apt-get update && \
echo oracle-java${JAVA_VER}-installer shared/accepted-oracle-license-v1-1 select true | sudo /usr/bin/debconf-set-selections && \
apt-get install -y --force-yes --no-install-recommends oracle-java${JAVA_VER}-installer oracle-java${JAVA_VER}-set-default && \
apt-get clean && \
rm -rf /var/cache/oracle-jdk${JAVA_VER}-installer

设置Oracle Java为默认

1
2
3
RUN update-java-alternatives -s java-8-oracle

RUN echo "export JAVA_HOME=/usr/lib/jvm/java-8-oracle" >> ~/.bashrc

清除APT

1
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
使用初始化系统
1
CMD ["/sbin/my_init"]

构建镜像

1
$ docker build -f Dockerfile -t demo/oracle-java:8 .

-f: 指定Dockerfile

-t: 指定镜像名称。demo/oracle-java为名称,冒号后面的 8 为标签或版本

.: 指定为当前目录。当前目录的文件和目录将作为构建工件发送到Docker守护程序中去。

测试镜像

在前面的目录中,新增一个java文件 Main.java,内容如下:

1
2
3
4
5
6
public class Main
{
public static void main(String[] args) {
System.out.println("Hello, World");
}
}

编译

1
$ docker run --rm -v $PWD:/app -w /app demo/oracle-java:8 javac Main.java

运行

1
$ docker run --rm -v $PWD:/app -w /app demo/oracle-java:8 java Main

出现 Hello, World 则表示成功。

如果你想使用官方的 OpenJDK 来运行你的代码,并不需要重新编写一个Dockerfile,只需要指定一下即可:

1
2
3
$ docker run --rm -v $PWD:/app -w /app java:8 javac Main.java

$ docker run --rm -v $PWD:/app -w /app java:8 java Main

为Maven工程编写Dockerfile

如果您将OpenJDK与Maven一起使用,则不一定需要编写Dockerfile,因为您可以使用官方Docker Hub存储库的Maven版本。 但是,如果您将Oracle JDK与Maven一起使用,则需要编写自己的Dockerfile。

我们使用上面构建好的 demo/oracle-jdk:8 镜像作为我们这一步的基础镜像。

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Dockerfile
FROM demo/oracle-java:8

ENV MAVEN_VERSION 3.5.4

RUN mkdir -p /usr/share/maven \
&& curl -fsSL http://apache.osuosl.org/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz \
| tar -xzC /usr/share/maven --strip-components=1 \
&& ln -s /usr/share/maven/bin/mvn /usr/bin/mvn

ENV MAVEN_HOME /usr/share/maven

VOLUME /root/.m2

CMD ["mvn"]

构建Docker镜像

1
$ docker build -f Dockerfile -t demo/maven:3.5-jdk-8 .

测试

1
$ docker run -it --rm -v "$PWD":/app -w /app demo/maven:3.5-jdk-8 mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -Dinte

当前目录下将会创建一个 my-app 目录,里面会有一个我们创建的maven工程

构建Maven工程

进入工程目录:

1
$ cd  my-app

构建工程:

1
$ docker run -it --rm -v "$PWD":/app -w /app demo/maven:3.5-jdk-8 mvn package

测试JAR包:

1
$ docker run -it --rm -v "$PWD":/app -w /app demo/maven:3.5-jdk-8 java -cp target/my-app-1.0-SNAPSHOT.jar com.mycompany.app.App

正确输出:

1
Hello World!

为SpringMVC应用编写Dockerfile

基于Spring的应用程序的Docker化有两种方法:

  • 使用已经存在的Maven-base镜像作为基础镜像,并且安装Tomcat,运行web程序。
  • 使用已经存在的Maven-base镜像来编译和打包应用程序。然后使用另一个Tomcat-base Docker容器来部署这个应用。

下面我们来分别介绍一下这两种方法.

基于Mave-base镜像安装Tomcat

新建一个文件夹,同时新建一个Dockerfile文件,内容如下:

1
2
3
4
5
6
7
8
9
10
# Dockerfile
FROM demo/maven:3.5-jdk-8
MAINTAINER Wangwei <w7years@gmail.com>
RUN apt-get update && \
apt-get install -yq --no-install-recommends wget pwgen ca-certificates && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
ENV TOMCAT_MAJOR_VERSION 8
ENV TOMCAT_MINOR_VERSION 8.5.33
ENV CATALINA_HOME /tomcat

安装Tomcat

1
2
3
4
5
6
7
8
9
10
11
12
13
RUN wget -q https://archive.apache.org/dist/tomcat/tomcat-${TOMCAT_MAJOR_VERSION}/v${TOMCAT_MINOR_VERSION}/bin/apache-tomcat-${TOMCAT_MINOR_VERSION}.tar.gz && \
wget -qO- https://archive.apache.org/dist/tomcat/tomcat-${TOMCAT_MAJOR_VERSION}/v${TOMCAT_MINOR_VERSION}/bin/apache-tomcat-${TOMCAT_MINOR_VERSION}.tar.gz.md5 | md5sum -c - && \
tar zxf apache-tomcat-*.tar.gz && \
rm apache-tomcat-*.tar.gz && \
mv apache-tomcat* tomcat

ADD create_tomcat_admin_user.sh /create_tomcat_admin_user.sh
RUN mkdir /etc/service/tomcat
ADD run.sh /etc/service/tomcat/run
RUN chmod +x /*.sh
RUN chmod +x /etc/service/tomcat/run

EXPOSE 8080

使用baseimage-docker的init系统

1
CMD ["/sbin/my_init"]

创建Tomcat 管理员

在相同的目录下新建一个 create_tomcat_admin_user.sh 文件,内容如下:

1
2
3
4
5
6
!/bin/bash

if [ -f /.tomcat_admin_created ]; then
echo "Tomcat 'admin' user already created"
exit 0
fi

生成密码

添加以下脚本用于生成密码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
PASS=${TOMCAT_PASS:-$(pwgen -s 12 1)}
_word=$( [ ${TOMCAT_PASS} ] && echo "preset" || echo "random" )

echo "=> Creating an admin user with a ${_word} password in Tomcat"
sed -i -r 's/<\/tomcat-users>//' ${CATALINA_HOME}/conf/tomcat-users.xml
echo '<role rolename="manager-gui"/>' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo '<role rolename="manager-script"/>' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo '<role rolename="manager-jmx"/>' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo '<role rolename="admin-gui"/>' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo '<role rolename="admin-script"/>' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo "<user username=\"admin\" password=\"${PASS}\" roles=\"manager-gui,manager-script,manager-jmx,admin-gui, admin-script\"/>" >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo '</tomcat-users>' >> ${CATALINA_HOME}/conf/tomcat-users.xml
echo "=> Done!"
touch /.tomcat_admin_created

echo "========================================================================"
echo "You can now configure to this Tomcat server using:"
echo ""
echo " admin:${PASS}"
echo ""
echo "========================================================================"

create_tomcat_admin_user.sh 用于创建Tomcat管理员。另外在创建一个 run.sh 文件,用于执行 create_tomcat_admin_user.sh 并reload Tomcat 。

1
2
3
4
5
6
7
!/bin/bash

if [ ! -f /.tomcat_admin_created ]; then
/create_tomcat_admin_user.sh
fi

exec ${CATALINA_HOME}/bin/catalina.sh run

构建Docker镜像

使用以下命令构建docker镜像:

1
$ docker build -f Dockerfile -t demo/spring:maven-3.5-jdk-8 .

clone测试工程

1
$ git clone  https://github.com/atifsaddique211f/spring-maven-sample.git

构建并打包工程

1
2
$ cd spring-maven-sample
$ docker run -it --rm -v "$PWD":/app -w /app demo/spring:maven-3.5-jdk-8 mvn clean install

该步骤将会生成一个war包:target/springwebapp.war

copy这个war包到Tomcat webapps 目录下

1
$ docker run -it -d --name spring -p 8080:8080 -v "$PWD":/app demo/spring:maven-3.5-jdk-8 bash -c "cp /app/target/springwebapp.war /tomcat/webapps/ & /tomcat/bin/catalina.sh run"

运行成功,访问:http://localhost:8080/springwebapp/car/add

停止Spring

1
$ docker rm -vf spring

在不同的Tomcat镜像中运行Spring App程序

clone spring工程:

1
$ git clone  https://github.com/atifsaddique211f/spring-maven-sample.git

创建Dockerfile

1
2
3
4
# Dockerfile
FROM tomcat:8

ADD target/*.war /usr/local/tomcat/webapps/

构建并打包工程

1
$ docker run -it --rm -v "$PWD":/app -w /app demo/maven:3.5-jdk-8 mvn clean install

构建Dockerfile

1
$ docker build -f Dockerfile -t demo/tomcat:8 .

运行Tomcat

1
$ docker run --rm -p 8080:8080 demo/tomcat:8

Ctrl + C 停止应用程序

参考资料

请我喝杯咖啡吧~