用 Docker 构建、运行、发布一个 Spring Boot 应用

本文演示了如何用 Docker 构建、运行、发布来一个 Spring Boot 应用。

Docker 简介

Docker 是一个 Linux 容器管理工具包,具备“社交”方面,允许用户发布容器的 image (镜像),并使用别人发布的 image。Docker image 是用于运行容器化进程的方案,在本文中,我们将构建一个简单的 Spring Boot 应用程序。

有关 Docker 的详细介绍,可以移步至 《简述 Docker》

前置条件

用 Maven 构建项目

创建目录结构

项目的目录结构因符合 Maven 的约定。

在 *nix 系统下执行 mkdir -p src/main/java/docker_spring_boot ,生产如下结构 :

└── src
    └── main
        └── java
            └── com
                └── waylau
                    └── docker_spring_boot

创建 pom.xml 文件

<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/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.waylau</groupId>
    <artifactId>docker-spring-boot</artifactId>
    <packaging>jar</packaging>
    <version>1.0.0</version>
    <name>docker-spring-boot</name>
    <description>Getting started with Spring Boot and Docker</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
        <relativePath/>
    </parent>

    <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>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
    <!-- tag::plugin[] -->
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.4.3</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>
    <!-- end::plugin[] -->
        </plugins>
    </build>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <docker.image.prefix>waylau</docker.image.prefix>
        <spring.boot.version>1.3.3.RELEASE</spring.boot.version>
    </properties>
</project>

Spring Boot Maven plugin 提供了很多方便的功能:

  • 它收集的类路径上所有 jar 文件,并构建成一个单一的、可运行的“über-jar”,这使得它更方便地执行和传输服务。
  • 它搜索的 public static void main() 方法来标记为可运行的类。
  • 它提供了一个内置的依赖解析器,用于设置版本号以匹配 Spring Boot 的依赖。您可以覆盖任何你想要的版本,但它会默认选择的 Boot 的版本集。

Spotify 的 docker-maven-plugin 插件是用于构建 Maven 的 Docker Image

  • imageName指定了镜像的名字,本例为 waylau/docker-spring-boot
  • dockerDirectory指定 Dockerfile 的位置
  • resources是指那些需要和 Dockerfile 放在一起,在构建镜像时使用的文件,一般应用 jar 包需要纳入。本例,只需一个 jar 文件。

编写 Spring Boot 应用

编写一个简单的 Spring Boot 应用 :

src/main/java/com/waylau/docker_spring_boot/Application.java:

package com.waylau.docker_spring_boot;

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;

/**
 * 主应用入口
 * @author <a href="http://waylau.com">waylau.com</a>
 * @date 2016年3月19日
 */
@SpringBootApplication
@RestController
public class Application {

    @RequestMapping("/")
    public String home() {
        return "Hello Docker World."
                + "<br />Welcome to <a href='http://waylau.com'>waylau.com</a></li>";
    }

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

}

解释下上面的代码:

  • 类用 @SpringBootApplication @RestController 标识,可用 Spring MVC 来处理 Web 请求。
  • @RequestMapping 将 / 映射到 home() ,并将"Hello Docker World" 文本作为响应。
  • main() 方法使用 Spring Boot 的 SpringApplication.run() 方法来启动应用。

运行程序

使用 Maven

编译:

mvn package

运行:

java -jar target/docker-spring-boot-1.0.0.jar

访问项目

如果程序正确运行,浏览器访问 http://localhost:8080/,可以看到页面 “Hello Docker World.” 字样。

将项目容器化

Docker 使用 Dockerfile 文件格式来指定 image 层,

创建文件 src/main/docker/Dockerfile:

FROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD docker-spring-boot-1.0.0.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

解释下这个配置文件:

  • VOLUME 指定了临时文件目录为/tmp。其效果是在主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp。改步骤是可选的,如果涉及到文件系统的应用就很有必要了。/tmp目录用来持久化到 Docker 数据文件夹,因为 Spring Boot 使用的内嵌 Tomcat 容器默认使用/tmp作为工作目录
  • 项目的 jar 文件作为 "app.jar" 添加到容器的
  • ENTRYPOINT 执行项目 app.jar。为了缩短 Tomcat 启动时间,添加一个系统属性指向 "/dev/urandom" 作为 Entropy Source

构建 Docker Image

执行构建成为 docker image:

mvn package docker:build

运行

运行 Docker Image

docker run -p 8080:8080 -t waylau/docker-spring-boot
[root@waylau spring-boot]# docker run -p 8080:8080 -t waylau/docker-spring-boot

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.3.3.RELEASE)

2016-03-20 08:45:51.276  INFO 1 --- [           main] c.waylau.docker_spring_boot.Application  : Starting Application v1.0.0 on 048fb623038f with PID 1 (/app.jar started by root in /)
2016-03-20 08:45:51.289  INFO 1 --- [           main] c.waylau.docker_spring_boot.Application  : No active profile set, falling back to default profiles: default
2016-03-20 08:45:51.722  INFO 1 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@669af5fc: startup date [Sun Mar 20 08:45:51 GMT 2016]; root of context hierarchy
2016-03-20 08:45:54.874  INFO 1 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'beanNameViewResolver' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]]
2016-03-20 08:45:57.893  INFO 1 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2016-03-20 08:45:57.982  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2016-03-20 08:45:57.984  INFO 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.0.32
2016-03-20 08:45:58.473  INFO 1 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2016-03-20 08:45:58.473  INFO 1 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 6877 ms
2016-03-20 08:45:59.672  INFO 1 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2016-03-20 08:45:59.695  INFO 1 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'characterEncodingFilter' to: [/*]
2016-03-20 08:45:59.701  INFO 1 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2016-03-20 08:45:59.703  INFO 1 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2016-03-20 08:45:59.703  INFO 1 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'requestContextFilter' to: [/*]
2016-03-20 08:46:00.862  INFO 1 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@669af5fc: startup date [Sun Mar 20 08:45:51 GMT 2016]; root of context hierarchy
2016-03-20 08:46:01.166  INFO 1 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/]}" onto public java.lang.String com.waylau.docker_spring_boot.Application.home()
2016-03-20 08:46:01.189  INFO 1 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2016-03-20 08:46:01.190  INFO 1 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2016-03-20 08:46:01.302  INFO 1 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-03-20 08:46:01.302  INFO 1 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-03-20 08:46:01.438  INFO 1 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2016-03-20 08:46:01.833  INFO 1 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2016-03-20 08:46:02.332  INFO 1 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2016-03-20 08:46:02.343  INFO 1 --- [           main] c.waylau.docker_spring_boot.Application  : Started Application in 13.194 seconds (JVM running for 15.828)

访问项目

如果程序正确运行,浏览器访问 http://localhost:8080/,可以看到页面 “Hello Docker World.” 字样。

推送 image 到 Docker Hub

首先,你在 Docker Hub 要有注册账号,且创建了相应的库;

其次,docker 推送前,先要登录,否则报unauthorized: access to the requested resource is not authorized的错误

执行:

docker login

输出为:

[root@waylau spring-boot]# docker login
Username: waylau
Password:
Email: waylau521@gmail.com
WARNING: login credentials saved in /root/.docker/config.json
Login Succeeded

执行推送

docker push waylau/docker-spring-boot
[root@waylau spring-boot]# docker push waylau/docker-spring-boot
The push refers to a repository [docker.io/waylau/docker-spring-boot]
751d29eef02e: Layer already exists
4da3741f39c7: Pushed
5f70bf18a086: Layer already exists
7e4d0cb13643: Layer already exists
8f045733649f: Layer already exists
latest: digest: sha256:eb4d5308ba1bb27489d808279e74784bda6761b3574f4298d746abba59b35164 size: 9415

镜像加速器

Docker Hub 在国外,有时候拉取 Image 极其缓慢,可以使用国内的镜像来实现加速

阿里云

echo "DOCKER_OPTS=\"--registry-mirror=https://yourlocation.mirror.aliyuncs.com\"" | sudo tee -a /etc/default/docker
sudo service docker restart

其中 https://yourlocation.mirror.aliyuncs.com 是您在阿里云注册后的专属加速器地址:

DaoCloud

sudo echo “DOCKER_OPTS=\”\$DOCKER_OPTS –registry-mirror=http://your-id.m.daocloud.io -d\”” >> /etc/default/docker
sudo service docker restart

其中 http://your-id.m.daocloud.io 是您在 DaoCloud 注册后的专属加速器地址:

源码

获取项目源码, https://github.com/waylau/docker-demos 中的 samples/spring-boot

获取项目镜像, 执行

docker pull waylau/docker-spring-boot

参考引用

时间: 2024-11-02 08:44:49

用 Docker 构建、运行、发布一个 Spring Boot 应用的相关文章

用 Docker、Gradle 来构建、运行、发布一个 Spring Boot 应用

本文演示了如何用 Docker.Gradle 来构建.运行.发布来一个 Spring Boot 应用. Docker 简介 Docker 是一个 Linux 容器管理工具包,具备"社交"方面,允许用户发布容器的 image (镜像),并使用别人发布的 image.Docker image 是用于运行容器化进程的方案,在本文中,我们将构建一个简单的 Spring Boot 应用程序. 有关 Docker 的详细介绍,可以移步至 <简述 Docker> 前置条件 JDK 1.8

在阿里云容器服务上创建一个spring boot应用

环境需求 你喜欢的文本编辑器或者IDE JDK1.8或以上版本 Maven3.0或以上版本 如果你不是在linux操作系统上面做开发,你需要docker-toolbox来构建Linux的虚拟环境 第一步:创建一个spring boot应用 下载并解压spring boot应用模板代码git clone https://github.com/spring-guides/gs-spring-boot-docker.gitcd gs-spring-boot-docker/complete 编辑代码文件

如何使用Docker构建运行时间较长的脚本

如何使用Docker构建运行时间较长的脚本 Docker 我想我已经找到了一个非常不错的Docker使用案例.你是不是会觉得这是一篇写Docker有多好多好的文章,开始之前我想和你确认,这篇文章会介绍如何把文件系统作为持久性的数据结构. 因此,这篇文章的见解同样适用于其他的 copy-on-write文件系统,如BTRFS和ZFS. 问题 让我们从这个我试图解决的问题开始.我开发了一个会运行很长时间的构建脚本,这个脚本中包含了很多的步骤. 这个脚本会运行1-2个小时. 它会从网络下载比较大的文件

创建你的第一个Spring Boot应用

Spring Boot应该是目前比较火的一个微服务的框架.所以我也来学习一下这个不算新的新东西,也算是追逐一下潮流. 准备工作 Spring Boot要求JDK1.7以上,Maven3.2以上.所以你首先要配置JDK1.7或者1.8的环境变量(我是用的1.8),然后配置Maven环境变量.至于怎么配置这两项请出门左转自行百度. 安装Spring Boot CLI Spring Boot CLI是Spring Boot提供的一个命令行工具.安装非常简单,你只需要把下载来的spring-boot-c

Spring Boot与Docker(三):构建你的第一个微服务和相关容器以及容器的连接

本文讲的是Spring Boot与Docker(三):构建你的第一个微服务和相关容器以及容器的连接,[编者的话]本篇是<使用Spring Boot和Docker构建微服务架构>系列的第三篇,本篇我们将会准备开始构建一个员工对象微服务.原文作者为3Pillar环球旗下美国Adbanced技术集团的总监Dan Greene,Dan有十八年的软件设计和开发经验,包括在电子商务.B2B集成.空间分析.SOA架构.大数据以及云计算等领域的软件产品架构经验,他是AWS认证解决方案架构师,在3Pillar之

《深入实践Spring Boot》一3.5 运行与发布

3.5 运行与发布 Spring Boot需要一个启动程序作为应用的入口,在webui模块中,我们设计了一个入口程序,如代码清单3-25所示.使用这个入口程序,就可以调试和发布工程了.代码清单3-25 Web应用启动主程序 package com.test.webui; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplica

使用Spring Cloud和Docker构建微服务

本文讲的是使用Spring Cloud和Docker构建微服务,[编者的话]这是系列博文中的第一篇,本文作者使用Spring Cloud和Docker构建微服务平台,文章的例子浅显易懂. 本系列博文主要向大家介绍如何使用Spring Cloud和Docker构建微服务平台. 什么是Spring Cloud? Spring Cloud 是Pivotal提供的用于简化分布式系统构建的工具集.Spring Cloud引入了云平台连接器(Cloud Connector)和服务连接器(Service Co

使用 Spring Boot 快速构建 Spring 框架应用,PropertyPlaceholderConfigurer

Spring 框架对于很多 Java 开发人员来说都不陌生.自从 2002 年发布以来,Spring 框架已经成为企业应用开发领域非常流行的基础框架.有大量的企业应用基于 Spring 框架来开发.Spring 框架包含几十个不同的子项目,涵盖应用开发的不同方面.如此多的子项目和组件,一方面方便了开发人员的使用,另外一个方面也带来了使用方面的问题.每个子项目都有一定的学习曲线.开发人员需要了解这些子项目和组件的具体细节,才能知道如何把这些子项目整合起来形成一个完整的解决方案.在如何使用这些组件上

如何运行Spring Boot应用

介绍 Spring Boot 是 Spring 产品中一个新的子项目,致力于简便快捷地搭建基于 Spring 的独立可运行的应用.大多数的 Spring Boot 应用只需要非常少的 Spring 配置. 你能够使用 Spring Boot 创建 Java 应用并通过 java -jar 来运行或者创建传统的通过 war 来部署的应用.Spring Boot 也提供了一个命令行工具来运行 spring 脚本. Spring Boot 的目标是: 快速开发基于 Spring 的应用 开箱即用的微服