使用 docker 部署 java webapp

本文主要记录一下如何使用 docker 部署 java 的 webapp。

建立 demo webapp


这里为了方便, 使用spring-boot来搭建一个webapp。

首先使用 maven 下载依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.1.RELEASE</version>
</parent>

<groupId>org.niko.spring.boot</groupId>
<artifactId>starter-web-docker</artifactId>
<name>Spring Boot Starter</name>
<description>Spring Boot Starter</description>
<url>http://projects.spring.io/spring-boot/</url>

<organization>
<name>Pivotal Software, Inc.</name>
<url>http://www.spring.io</url>
</organization>

<properties>
<main.basedir>${basedir}/../..</main.basedir>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>

</build>

<!-- Add Spring repositories -->
<!-- (you don't need this if you are using a .RELEASE version) -->
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>

然后编写 启动器 和 Controller:


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class Application {

@RequestMapping("/")
public String home() {
return "Hello Docker World";
}

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

}

构建包:

mvn package

成功后, target 文件夹下面会有一个 starter-web-docker-1.3.1.RELEASE.jar 文件:

$ ll ./target/
total 15196
drwxrwxr-x 8 niko niko 4096 Nov 13 17:13 ./
drwxrwxr-x 5 niko niko 4096 Nov 13 17:12 ../
drwxrwxr-x 3 niko niko 4096 Nov 13 17:12 classes/
drwxrwxr-x 3 niko niko 4096 Nov 13 17:12 generated-sources/
drwxrwxr-x 3 niko niko 4096 Nov 13 17:12 generated-test-sources/
drwxrwxr-x 2 niko niko 4096 Nov 13 17:13 maven-archiver/
drwxrwxr-x 3 niko niko 4096 Nov 13 17:13 maven-status/
-rw-rw-r-- 1 niko niko 15521233 Nov 13 17:13 starter-web-docker-1.3.1.RELEASE.jar
-rw-rw-r-- 1 niko niko 3594 Nov 13 17:13 starter-web-docker-1.3.1.RELEASE.jar.original
drwxrwxr-x 2 niko niko 4096 Nov 13 17:12 test-classes/

编写 Dockerfile


FROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD starter-web-docker-1.3.1.RELEASE.jar app.jar
RUN sh -c 'touch /app.jar'
ENV JAVA_OPTS=""
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

用 docker-maven-plugin 提高生产力


自动生成 image.

<properties>
<docker.image.prefix>springio</docker.image.prefix>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.11</version>
<configuration>
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>

构建 image


现在开始构建 docker image.

$ mvn package docker:build
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Spring Boot Starter 1.3.1.RELEASE
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- Docker-maven-plugin:0.4.11:build (default-cli) @ starter-web-docker-hello ---
[INFO] Copying /home/niko/dev/code/java/MavenProj/OpenSources/spring/spring-boot/starter-web-docker/target/starter-web-docker-hello-1.3.1.RELEASE.jar -> /home/niko/dev/code/java/MavenProj/OpenSources/spring/spring-boot/starter-web-docker/target/docker/starter-web-docker-hello-1.3.1.RELEASE.jar
[INFO] Copying src/main/docker/Dockerfile -> /home/niko/dev/code/java/MavenProj/OpenSources/spring/spring-boot/starter-web-docker/target/docker/Dockerfile
[INFO] Building image springio/starter-web-docker-hello
Step 1 : FROM frolvlad/alpine-oraclejdk8:slim
---> a290f8607aef
Step 2 : VOLUME /tmp
---> Using cache
---> c4ed57bbd8e3
Step 3 : ADD starter-web-docker-hello-1.3.1.RELEASE.jar app.jar
---> Using cache
---> 57c7382f828d
Step 4 : RUN sh -c 'touch /app.jar'
---> Using cache
---> 37ee84639687
Step 5 : ENV JAVA_OPTS ""
---> Using cache
---> 3fd3017669ff
Step 6 : ENTRYPOINT sh -c java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar
---> Using cache
---> e12ac1f796a2
Successfully built e12ac1f796a2
[INFO] Built springio/starter-web-docker-hello
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.745 s

查看 image


构建完成后, 可以查看主机上现有的 images :

$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
springio/starter-web-docker-hello latest e12ac1f796a2 5 minutes ago 198.2 MB
frolvlad/alpine-oraclejdk8 slim a290f8607aef 2 weeks ago 167.2 MB
hello-world latest c54a2cc56cbb 4 months ago 1.848 kB

启动 image

$ docker run -p 8080:8080 -t springio/starter-web-docker-hello:latest

说明:
-p 进行端口映射, 格式为 主机端口:容器端口
-t 分配一个 pseudo-TTY

查看正在运行的 image


$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b5154800fbeb springio/starter-web-docker-hello:latest "sh -c 'java $JAVA_OP" About a minute ago Up About a minute 0.0.0.0:8080->8080/tcp ecstatic_ardinghelli

可以看到, springio/starter-web-docker-hello:latest 正在运行, 此时打开 localhost:8080 也可以看到 Hello Docker World 的页面消息了。

停止


可以指定 CONTAINER ID 来停止运行。

$ docker stop b5154800fbeb
b5154800fbeb

参考


https://spring.io/guides/gs/spring-boot-docker/