本文演示了如何用 Docker 构建、运行、发布来一个 Spring Boot 应用。
Docker 简介
Docker 是一个 Linux 容器管理工具包,具备“社交”方面,允许用户发布容器的 image (镜像),并使用别人发布的 image。Docker image 是用于运行容器化进程的方案,在本文中,我们将构建一个简单的 Spring Boot 应用程序。
前置条件
- JDK 1.8+
- Maven 3.0+
- Docker 最新版。有关 Docker 在的安装,可以搜索下,跟常规软件安装一样。 如果你的电脑不是 Linux 系统,最好装个虚拟机,在虚拟机里面装个 Linux ,因为 Docker 的依赖 Linux。
创建一个Springboo项目
创建maven springboot项目
可以通过spring io 官网来快速创建,也可以使用IDEA来快速创建。
假设你已经创建了一个标准的是springboot项目,大概目录如下:
我们需要在main目录下创建一个 docker 目录,然后在该目录下创建 Dockerfile 文件。
然后配置 pom.xml 文件,内容大致如下:
<?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>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>docker</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>docker</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<!-- 在docker运行时要用的,只是一个前缀而已,就像包名一样,可自己任意定义此名称,重要:不能用驼峰命名法,最好全小写 -->
<docker.image.prefix>dockertest</docker.image.prefix>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<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>
<!-- docker 插件 begin -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.13</version>
<configuration>
<!--镜像名称以及版本号-->
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<!--依赖的基础镜像-->
<baseImage>java</baseImage>
<!--Dockerfile的位置 -->
<dockerDirectory>src/main/docker</dockerDirectory>
<!-- 这里是复制 jar 包到 docker 容器指定目录配置 -->
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
<!-- docker 插件 end -->
</plugins>
</build>
</project>
修改 Spring Boot 应用入口文件
这里为了简便我们直接修改了Spring Boot 应用的启动文件,增加一个Controller。正常情况下你应该创建单独的Controller来处理访问连接 :
package com.example.docker;
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;
@RestController
@SpringBootApplication
public class DockerApplication {
@RequestMapping("/")
public String home() {
return "Hello Docker World.";
}
public static void main(String[] args) {
SpringApplication.run(DockerApplication.class, args);
}
}
解释下上面的代码:
- 类用
@SpringBootApplication
@RestController
标识,可用 Spring MVC 来处理 Web 请求。 @RequestMapping
将/
映射到home()
,并将"Hello Docker World" 文本作为响应。main()
方法使用 Spring Boot 的SpringApplication.run()
方法来启动应用。
运行程序
使用 Maven,你也可以使用IDEA自带的maven控制台来打包,或者启动应用
使用idea启动springboot
使用idea插件打包项目,打包完成后的jar在项目根目录的 target 目录下
或者你也可以通过mvn命令编译:
mvn package
运行:
java -jar target/docker-0.0.1-SNAPSHOT.jar
访问项目
如果程序正确运行,浏览器访问 http://localhost:8080/,可以看到页面 “Hello Docker World.” 字样。
将项目容器化
Docker 使用 Dockerfile 文件格式来指定 image 层,
所以我们上面创建了文件 src/main/docker/Dockerfile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD docker-0.0.1-SNAPSHOT.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" ]
解释下这个配置文件:
- FROM 是指定了应用哪个基本容器镜像,因为我们需要jdk java环境,所以这里指定了
openjdk:8-jdk-alpine
镜像 VOLUME
指定了临时文件目录为/tmp
。其效果是在主机/var/lib/docker
目录下创建了一个临时文件,并链接到容器的/tmp
。该步骤是可选的,如果涉及到文件系统的应用就很有必要了。/tmp
目录用来持久化到 Docker 数据文件夹,因为 Spring Boot 使用的内嵌 Tomcat 容器默认使用/tmp
作为工作目录- ADD 是将项目的
docker-0.0.1-SNAPSHOT.jar
文件名重命名为 "app.jar" 并添加到容器 ENTRYPOINT
执行项目 app.jar。为了缩短 Tomcat 启动时间,添加一个系统属性指向 "/dev/urandom" 作为 Entropy Source
构建 Docker Image
执行构建成为 docker image:
mvn package docker:build
当然你也可以通过IDEA的maven插件来,点击按钮执行构建镜像
分别点击,1、clean 2、package 3、docker/docker:build
构建完成后,我们可以使用 docker images 来查看我们刚刚构建的镜像
通过docker images 命令我们看到刚才构建的镜像已经成功
运行
运行我们刚才构建的docker 镜像
docker run -p 8080:8080 -t dockertest/docker
前面的8080是指本机的端口,后面的是容器的端口。即把本机的8080端口映射到容器的8080端口上。
myiMac:docker auan$ docker run -p 18080:8080 -t dockertest/docker
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.5.RELEASE)
2019-05-31 08:21:27.442 INFO 1 --- [ main] com.example.docker.DockerApplication : Starting DockerApplication v0.0.1-SNAPSHOT on 31eb12a6a818 with PID 1 (/app.jar started by root in /)
2019-05-31 08:21:27.447 INFO 1 --- [ main] com.example.docker.DockerApplication : No active profile set, falling back to default profiles: default
2019-05-31 08:21:28.636 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2019-05-31 08:21:28.675 INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-05-31 08:21:28.675 INFO 1 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.19]
2019-05-31 08:21:28.778 INFO 1 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-05-31 08:21:28.778 INFO 1 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1276 ms
2019-05-31 08:21:29.001 INFO 1 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-05-31 08:21:29.123 WARN 1 --- [ main] ion$DefaultTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration)
2019-05-31 08:21:29.261 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2019-05-31 08:21:29.265 INFO 1 --- [ main] com.example.docker.DockerApplication : Started DockerApplication in 2.354 seconds (JVM running for 2.763)
访问项目
如果程序正确运行,浏览器访问 http://localhost:8080/,可以看到页面 “Hello Docker World.” 字样。
推送 image 到 Docker Hub
首先,你在 Docker Hub 要有注册账号,且创建了相应的库;
其次,docker 推送前,先要登录,否则报unauthorized: access to the requested resource is not authorized
的错误
执行:
docker login
输出为:
Username: auan
Password:
Email: *****@gmail.com
WARNING: login credentials saved in /root/.docker/config.json
Login Succeeded
执行推送
docker push dockertest/docker
The push refers to a repository [docker.io/dockertest/docker]
11fe0c5fec8c: Pushed
9f41d126a004: Pushed
ceaf9e1ebef5: Pushed
9b9b7f3d56a0: Pushed
f1b5933fe4b5: Pushed
latest: digest: sha256:583a1b2519535df7d49d18281c0ba29df610f71a6b52cfd0c7b357c96e7637fc size: 1371
镜像加速器
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 注册后的专属加速器地址
遇到的问题:
1、maven构建时报错:
maven docker 插件 org.apache.http.client.ClientProtocolException: Cannot retry request with a non-repeatable request entity: Broken pipe -> [Help 1]
文章评论(0)