Docker部署spring boot

总结这篇博文时,微服务已经在很多公司落地,回看之前的博文记录,在2016年其实就已经利用docker做一些简单的实验环境了,但一直没有好好总结应用场景,现在算是连容器的坎也没跨过去。谨以此文来警戒自己:“今天不走,明天即使跑也不一定跟得上!”

现在实践总结下docker部署spring boot的过程,对未来的应用做好知识储备。

手动构建spring boot应用

helloworld应用

1.创建spring boot工程
使用IntelliJ IDEA的“Spring Assistant”插件创建spring web项目
Group id: com.docker
Artifact id: hellworld
Project name: helloworld
Package name: com.docker.helloworld

2.创建HelloworldController

vim HelloworldController
package com.docker.helloworld;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloworldController {
    
    private static final Logger logger= LoggerFactory.getLogger(HelloworldController.class);
    @RequestMapping("/")
    public String index(){
        return "Hello world";
    }
}

3.编译运行

mvn clean package && java -jar target/helloworld-0.0.1-SNAPSHOT.jar

此时我们可以通过localhost:8080访问了。

docker构建镜像

1.Dockerfile

#基础镜像java 1.8
From java
#匿名数据卷,在启动容器时忘记挂载数据卷,会自动挂载到匿名卷
VOLUMN /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} helloworld.jar
ENTRYPOINT ["java","-jar","/helloworld.jar"]

2.构建镜像并运行容器

#从dockerfile构建镜像
[root@test]# docker build -t docker/helloworld .

#docker/helloworld就是我们构建的新镜像
[root@test]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker/helloworld   latest              75c3d26e3c57        8 minutes ago       661MB

#运行容器
[root@test]# docker run -d -p 8080:8080 --name hellworld docker/helloworld
#查看镜像
[root@test]# docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS                                        NAMES
feb8b6ef9941        docker/helloworld   "java -jar /hellowor…"   8 minutes ago       Up 8 minutes                 0.0.0.0:8080->8080/tcp                       hellworld

此时我们可以通过localhost:8080访问了。

以上是通过手动运行jar包及通过镜像的形式运行应用,其实mvn也提供相应的插件构建镜像。

mvn构建docker镜像

配置mvn插件

docker-maven-plugin作用是构建应用并打包成docker镜像,推送到docker仓库。

#添加docker-maven-plugin到pom.xml
#版本已经使用新版本
<plugin>
	<groupId>com.spotify</groupId>
	<artifactId>docker-maven-plugin</artifactId>
	<version>1.2.2</version>
	<configuration>
		<imageName>docker/helloworld</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>

其中:
(1)imageName 是构建镜像的名称;

(2)dockerDirectory 是Dockerfile位置,最好是只有Dockerfile,因为在mvn打包时此目录下的所有文件包括Dockerfile将会被copy到${project.build.directory}/docker目录下,此目录一般是target/docker目录;

(3)resource作用是将${project.build.directory}目录下的${project.build.finalName}.jar,复制到${project.build.directory}/docker目录下;如:将target/helloworld-0.0.1-SNAPSHOT.jar 文件复制到target/docker/下;

构建运行

[root@test]# mvn clean package docker:build

[INFO] --- docker-maven-plugin:1.2.2:build (default-cli) @ helloworld ---
[INFO] Using authentication suppliers: [ConfigFileRegistryAuthSupplier]
[INFO] Copying /home/yanggd/java/docker/helloworld/target/helloworld-0.0.1-SNAPSHOT.jar -> /home/yanggd/java/docker/helloworld/target/docker/helloworld-0.0.1-SNAPSHOT.jar
[INFO] Copying src/main/docker/Dockerfile -> /home/yanggd/java/docker/helloworld/target/docker/Dockerfile
[INFO] Building image docker/helloworld
Step 1/5 : From java

Pulling from library/java
5040bd298390: Pull complete 
fce5728aad85: Pull complete 
76610ec20bf5: Pull complete 
60170fec2151: Pull complete 
e98f73de8f0d: Pull complete 
11f7af24ed9c: Pull complete 
49e2d6393f32: Pull complete 
bb9cdec9c7f3: Pull complete 
Digest: sha256:c1ff613e8ba25833d2e1940da0940c3824f03f802c449f3d1815a66b7f8c0e9d
Status: Downloaded newer image for java:latest
 ---> d23bdf5b1b1b
Step 2/5 : VOLUME /tmp

 ---> Running in fa47a820cd54
Removing intermediate container fa47a820cd54
 ---> 434e44760301
Step 3/5 : ARG JAR_FILE=*.jar

 ---> Running in 3e0266b2cb16
Removing intermediate container 3e0266b2cb16
 ---> aa3be3ab4daf
Step 4/5 : COPY ${JAR_FILE} helloworld.jar

 ---> 73cfed161b79
Step 5/5 : ENTRYPOINT ["java","-jar","/helloworld.jar"]

 ---> Running in 1e6d6ec86542
Removing intermediate container 1e6d6ec86542
 ---> 9027adc2d0a4
ProgressMessage{id=null, status=null, stream=null, error=null, progress=null, progressDetail=null}
Successfully built 9027adc2d0a4
Successfully tagged docker/helloworld:latest

其中:第4,5可以看到copy过程,剩下为从Dockerfile构建镜像过程。

#查看镜像
[root@test]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker/helloworld   latest              9027adc2d0a4        About an hour ago   661MB
#运行
docker run -d -p 8080:8080  --name helloworld docker/helloworld

从以上看出此镜像没有tag,添加tag如下:

#在pom.xml的configuration段中添加如下:

<imageTags>
	<imageTag>test</imageTag>
</imageTags>

或者
#在命令行直接打tag
mvn clean package docker:build -DdockerImageTags=v1

#构建完成后,同一image_id 有不同的tag
[root@test]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker/helloworld   v1                  6f3b482d2b78        10 seconds ago      661MB
docker/helloworld   latest              6f3b482d2b78        10 seconds ago      661MB
docker/helloworld   test                6f3b482d2b78        10 seconds ago      661MB

推送镜像到远程仓库阿里云镜像库

1.创建仓库
在阿里云容器镜像服务创建仓库

registry.cn-qingdao.aliyuncs.com/yanggd/test

2.mvn配置镜像库认证

vim settings.xml
#servers块中插入
<server>
  <id>docker-aliyun</id>
  #阿里云开通的账户名
  <username>xxxx</username>
  #开通镜像服务的密码,不是阿里云登录密码
  <password>xxxxx</password>
  <configuration>
    #阿里云绑定邮箱
    <email>xxxxx</email>
  </configuration>
</server>

3.pom.xml配置

<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
		<plugin>
			<groupId>com.spotify</groupId>
			<artifactId>docker-maven-plugin</artifactId>
			<version>1.2.2</version>
			<configuration>
			    <!--镜像名称要于阿里云镜像仓库对应,否则无法push到阿里云仓库-->
			    <!--功能等于docker tag docker/helloworld registry.cn-qingdao.aliyuncs.com/yanggd/test-->
				<imageName>registry.cn-qingdao.aliyuncs.com/yanggd/test</imageName>
				<dockerDirectory>src/main/docker</dockerDirectory>
				<resources>
					<resource>
						<targetPath>/</targetPath>
						<directory>${project.build.directory}</directory>
						<include>${project.build.finalName}.jar</include>
					</resource>
				</resources>
				<!--一定与mvn的id对应-->
				<serverId>docker-aliyun</serverId>
				<registryUrl>registry.cn-qingdao.aliyuncs.com/yanggd/test</registryUrl>
			</configuration>
		</plugin>
	</plugins>
</build>

4.构建并push

#构建,只推送tag为v3至远程仓库
[root@test]# mvn clean package docker:build -DdockerImageTags=v3 -DpushImageTag
[root@test]# docker image ls
REPOSITORY                                              TAG                 IMAGE ID            CREATED              SIZE
registry.cn-qingdao.aliyuncs.com/yanggd/test   latest              08d5a09985a1        20 seconds ago       661MB
registry.cn-qingdao.aliyuncs.com/yanggd/test   v3                  08d5a09985a1        20 seconds ago       661MB

注意:

#若不加-DdockerImageTags=v3 ,会将所有构建的镜像(v3及latest)都上传。
mvn clean package docker:build -DpushImageTag
#若不加-DpushImageTag,只会构建镜像并tag 为v3,但不会push。
mvn clean package docker:build -DdockerImageTags=v3

阿里云镜像库:
在这里插入图片描述

绑定Docker命令到Maven各个阶段

Docker 构建过程为 build、tag、push,其中build、tag对应mvn的package阶段,push对应mvn的deploy。通过将docker命令绑定到mvn的各个阶段,我们可以通过mvn deploy实现构建并push的过程。
补充:
(1)package阶段实现项目编译、单元测试、打包功能,但没有把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库和远程maven私服仓库;
(2) install阶段实现项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库,但没有布署到远程maven私服仓库;
(3) deploy阶段实现项目编译、单元测试、打包功能,同时把打好的可执行jar包(war包或其它形式的包)布署到本地maven仓库和远程maven私服仓库;

1.pom.xml配置插件

<!--一定添加maven-deploy-plugin,通过skip跳过artifact仓库-->
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-deploy-plugin</artifactId>
	<configuration>
		<skip>true</skip>
	</configuration>
</plugin>
<plugin>
	<groupId>com.spotify</groupId>
	<artifactId>docker-maven-plugin</artifactId>
	<version>1.2.2</version>
	<configuration>
		<imageName>registry.cn-qingdao.aliyuncs.com/yanggd/test</imageName>
		<dockerDirectory>src/main/docker</dockerDirectory>
		<resources>
			<resource>
				<targetPath>/</targetPath>
				<directory>${project.build.directory}</directory>
				<include>${project.build.finalName}.jar</include>
			</resource>
		</resources>
		<imageTags>
			<imageTag>${project.version}</imageTag>
		</imageTags>
		<serverId>docker-aliyun</serverId>
		<pushImage>true</pushImage>
		<registryUrl>registry.cn-qingdao.aliyuncs.com/yanggd/test</registryUrl>
	</configuration>
	<executions>
		<execution>
			<id>build-image</id>
			<phase>package</phase>
			<goals>
				<goal>build</goal>
			</goals>
		</execution>
		<execution>
			<id>tag-image</id>
			<phase>package</phase>
			<goals>
				<goal>tag</goal>
			</goals>
			<configuration>
				<image>registry.cn-qingdao.aliyuncs.com/yanggd/test:${project.version}</image>
				<newName>registry.cn-qingdao.aliyuncs.com/yanggd/test:${project.version}</newName>
			</configuration>
		</execution>
		<execution>
			<id>push-image</id>
			<phase>deploy</phase>
			<goals>
				<goal>push</goal>
			</goals>
			<configuration>
				<imageName>registry.cn-qingdao.aliyuncs.com/yanggd/test:${project.version}</imageName>
			</configuration>
		</execution>
	</executions>
</plugin>

注意:
(1)一定要通过maven-deploy-plugin设置skip,否则mvn deploy 推送时报错:

Deployment failed: repository element was not specified in the POM inside distributionManagement element or in -DaltDeploymentRepository=id::layout::url parameter

2.执行命令

#构建、tag 不推送
mvn clean package
#构建、tag及推送到远程仓库
mvn clean deploy 
#跳过整个过程,不执行实际命令,可用测试流程是否正常
mvn clean deploy -DskipDocker
#跳过构建
-DskipDockerBuild
#跳过tag
-DskipDockerTag
#跳过push
-DskipDockerPush

注意:
1.经测试发现,实际<goal>tag</goal>阶段并不会进行tag,而是在<imageName>registry.cn-qingdao.aliyuncs.com/yanggd/test</imageName>进行tag,如果你的imageName设置不正确,则不会推送到自定义仓库,而是默认的官方仓库;
2.此方式会将镜像的所有tag 版本,如v3和latest都会推送到远程仓库;

总结

通过对比,"docker命令绑定mvn各阶段"方式不太灵活,而且会将镜像所有tag进行推送,因此建议使用第一种。

docker部署spring boot的过程算是亲自实践了下,但是在实际过程中运维还需要考虑以下问题:
1.java应用的运行时数据、日志文件的持久化;
2.镜像命令、目录问题、私有镜像库等的配合使用;
3.流水线操作实现测试、版本发布等;
4.docker 运行状态监控等;

PS:
如果你对博文感兴趣,请关注我的公众号“木讷大叔爱运维”,与你分享运维路上的点滴。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值