一個 Spring Boot 應用在開發(fā)完成后蚂且,我們可以打包成一個 jar 文件直接運行。通常使用 nohup java -jar app.jar & (或寫個腳本) 的方式使其在服務器后臺運行个从。
Docker 技術的發(fā)展為微服務落地提供了更加便利的環(huán)境为鳄,使用 Docker 部署 Spring Boot 其實非常簡單诽俯,借助 Docker 我們可以做到運行環(huán)境與服務器環(huán)境的隔離汇跨,同時可以方便的管理發(fā)布版本。通過版本 tag 不僅可以方便的回滾到相應版本祖今,使用端口映射也可以方便的配合藍綠發(fā)布校坑。
本文測試和開發(fā)環(huán)境如下:
CentOS Linux release 7.6.1810
Spring Boot 2.1.2.RELEASE
Apache Maven 3.0.5 (Red Hat 3.0.5-17)
Java version: 1.8.0_162
Docker version 18.09.1, build 4c52b90
1. 先做一個簡單的Spring Boot Web 工程
1.1 Boot版本和依賴如下:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</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>
1.2 創(chuàng)建一個簡單的Controller:
@RestController
public class DockerController {
@RequestMapping("/hello")
public String index() {
return "Hello Docker!";
}
}
1.3 啟動Spring Boot,簡單測試可用千诬。
2. Spring Boot 項目添加 Docker 支持
2.1 在 pom.xml的properties中添加 Docker 鏡像名稱:
<properties>
<docker.image.prefix>springboot</docker.image.prefix>
</properties>
2.2 plugins 中添加 Docker 構建插件:
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</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>
2.3 在工程中創(chuàng)建目錄src/main/docker撒踪,并在其下創(chuàng)建 Dockerfile 文件
Dockerfile 文件用來說明如何來構建鏡像。
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD hello-docker-0.0.1-SNAPSHOT.jar helloapp.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/helloapp.jar"]
Dockerfile 文件很簡單大渤,首先構建 Jdk 基礎環(huán)境制妄,然后添加 Spring Boot Jar 到鏡像中:
-FROM ,表示使用 Jdk8 環(huán)境 為基礎鏡像泵三,如果鏡像不是本地的會從 DockerHub 進行下載
-VOLUME 耕捞,VOLUME 指向了一個/tmp的目錄衔掸,由于 Spring Boot 使用內置的Tomcat容器,Tomcat 默認使用/tmp作為工作目錄俺抽。這個命令的效果是:在宿主機的/var/lib/docker目錄下創(chuàng)建一個臨時文件并把它鏈接到容器中的/tmp目錄
-ADD 敞映,拷貝文件并且重命名
-ENTRYPOINT ,為了縮短 Tomcat 的啟動時間磷斧,添加java.security.egd的系統(tǒng)屬性指向/dev/urandom作為 ENTRYPOINT
3. 準備構建打包環(huán)境
在Windows上打包構建不是特別方便振愿,故選取CentOS為例。
3.1 Docker
3.1.1 Docker 要求 CentOS 系統(tǒng)的內核版本高于 3.10
查看本頁面的前提條件來驗證你的CentOS 版本是否支持 Docker 弛饭。
[root@spark ~]# uname -r
3.10.0-693.el7.x86_64
3.1.2 使用 root 權限登錄 Centos冕末。確保 yum 包更新到最新。
[root@spark ~]# sudo yum update
Loaded plugins: fastestmirror, langpacks
base | 3.6 kB 00:00:00
extras
.....以下省略.....
3.1.3 卸載舊版本(如果安裝過舊版本的話)
$ sudo yum remove docker docker-common docker-selinux docker-engine
[root@spark ~]# sudo yum remove docker docker-common docker-selinux docker-engine
Loaded plugins: fastestmirror, langpacks
No Match for argument: docker
No Match for argument: docker-common
No Match for argument: docker-engine
Resolving Dependencies
--> Running transaction check
---> Package container-selinux.noarch 2:2.74-1.el7 will be erased
--> Processing Dependency: container-selinux >= 2.9 for package: docker-ce-18.03.1.ce-1.el7.centos.x86_64
--> Running transaction check
---> Package docker-ce.x86_64 0:18.03.1.ce-1.el7.centos will be erased
--> Finished Dependency Resolution
Dependencies Resolved
=================================================================================================================================================================================================
Package Arch Version Repository Size
=================================================================================================================================================================================================
Removing:
container-selinux noarch 2:2.74-1.el7 @extras 37 k
Removing for dependencies:
docker-ce x86_64 18.03.1.ce-1.el7.centos @docker-ce-stable 151 M
Transaction Summary
=================================================================================================================================================================================================
Remove 1 Package (+1 Dependent package)
Installed size: 151 M
Is this ok [y/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Erasing : docker-ce-18.03.1.ce-1.el7.centos.x86_64 1/2
Erasing : 2:container-selinux-2.74-1.el7.noarch 2/2
Verifying : 2:container-selinux-2.74-1.el7.noarch 1/2
Verifying : docker-ce-18.03.1.ce-1.el7.centos.x86_64 2/2
Removed:
container-selinux.noarch 2:2.74-1.el7
Dependency Removed:
docker-ce.x86_64 0:18.03.1.ce-1.el7.centos
Complete!
3.1.4 安裝需要的軟件包
yum-util 提供yum-config-manager功能侣颂,另外兩個是devicemapper驅動依賴的
[root@spark ~]# sudo yum install -y yum-utils device-mapper-persistent-data lvm2
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
* base: mirrors.163.com
* extras: mirrors.163.com
* updates: centos.ustc.edu.cn
base | 3.6 kB 00:00:00
extras | 3.4 kB 00:00:00
mysql-connectors-community | 2.5 kB 00:00:00
mysql-tools-community | 2.5 kB 00:00:00
mysql57-community | 2.5 kB 00:00:00
updates | 3.4 kB 00:00:00
mysql-connectors-community/x86_64/primary_db | 29 kB 00:00:00
Package yum-utils-1.1.31-50.el7.noarch already installed and latest version
Package device-mapper-persistent-data-0.7.3-3.el7.x86_64 already installed and latest version
Package 7:lvm2-2.02.180-10.el7_6.2.x86_64 already installed and latest version
Nothing to do
3.1.5 設置yum源
[root@spark ~]# sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
Loaded plugins: fastestmirror, langpacks
adding repo from: https://download.docker.com/linux/centos/docker-ce.repo
grabbing file https://download.docker.com/linux/centos/docker-ce.repo to /etc/yum.repos.d/docker-ce.repo
repo saved to /etc/yum.repos.d/docker-ce.repo
3.1.6 查看所有倉庫中所有docker版本
[root@spark ~]# yum list docker-ce --showduplicates | sort -r
* updates: centos.ustc.edu.cn
Loading mirror speeds from cached hostfile
Loaded plugins: fastestmirror, langpacks
* extras: mirrors.163.com
docker-ce.x86_64 3:18.09.1-3.el7 docker-ce-stable
docker-ce.x86_64 3:18.09.0-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.1.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.06.0.ce-3.el7 docker-ce-stable
docker-ce.x86_64 18.03.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 18.03.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.12.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.12.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.09.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.09.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.06.2.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.06.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.06.0.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.03.3.ce-1.el7 docker-ce-stable
docker-ce.x86_64 17.03.2.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.03.1.ce-1.el7.centos docker-ce-stable
docker-ce.x86_64 17.03.0.ce-1.el7.centos docker-ce-stable
* base: mirrors.163.com
Available Packages
3.1.7 安裝
[root@spark ~]# sudo yum install docker-ce
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
* base: mirrors.163.com
* extras: mirrors.163.com
* updates: centos.ustc.edu.cn
Resolving Dependencies
--> Running transaction check
---> Package docker-ce.x86_64 3:18.09.1-3.el7 will be installed
--> Processing Dependency: container-selinux >= 2.9 for package: 3:docker-ce-18.09.1-3.el7.x86_64
--> Processing Dependency: containerd.io for package: 3:docker-ce-18.09.1-3.el7.x86_64
--> Processing Dependency: docker-ce-cli for package: 3:docker-ce-18.09.1-3.el7.x86_64
--> Running transaction check
---> Package container-selinux.noarch 2:2.74-1.el7 will be installed
---> Package containerd.io.x86_64 0:1.2.2-3.el7 will be installed
---> Package docker-ce-cli.x86_64 1:18.09.1-3.el7 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
=================================================================================================================================================================================================
Package Arch Version Repository Size
=================================================================================================================================================================================================
Installing:
docker-ce x86_64 3:18.09.1-3.el7 docker-ce-stable 19 M
Installing for dependencies:
container-selinux noarch 2:2.74-1.el7 extras 38 k
containerd.io x86_64 1.2.2-3.el7 docker-ce-stable 22 M
docker-ce-cli x86_64 1:18.09.1-3.el7 docker-ce-stable 14 M
Transaction Summary
=================================================================================================================================================================================================
Install 1 Package (+3 Dependent packages)
Total download size: 55 M
Installed size: 235 M
Is this ok [y/d/N]: N
Exiting on user command
Your transaction was saved, rerun it with:
yum load-transaction /tmp/yum_save_tx.2019-01-16.08-57.CfQg8F.yumtx
3.1.8 舊版本存在錯誤
因為之前已經安裝過舊版本的docker档桃,在安裝的時候或許有類似報錯:
Transaction check error:
file /usr/bin/docker from install of docker-ce-17.12.0.ce-1.el7.centos.x86_64 conflicts with file from package docker-common-2:1.12.6-68.gitec8512b.el7.centos.x86_64
file /usr/bin/docker-containerd from install of docker-ce-17.12.0.ce-1.el7.centos.x86_64 conflicts with file from package docker-common-2:1.12.6-68.gitec8512b.el7.centos.x86_64
file /usr/bin/docker-containerd-shim from install of docker-ce-17.12.0.ce-1.el7.centos.x86_64 conflicts with file from package docker-common-2:1.12.6-68.gitec8512b.el7.centos.x86_64
file /usr/bin/dockerd from install of docker-ce-17.12.0.ce-1.el7.centos.x86_64 conflicts with file from package docker-common-2:1.12.6-68.gitec8512b.el7.centos.x86_64
可以卸載舊版本的包
$ sudo yum erase docker-common-2:1.12.6-68.gitec8512b.el7.centos.x86_64
3.2 啟動
3.3 使用Docker 中國加速器
vi /etc/docker/daemon.json
{
"registry-mirrors": ["https://registry.docker-cn.com"],
"live-restore": true
}
重新啟動docker,注意上面文件準確憔晒, 否則會出錯藻肄。
systemctl restart docker
3.4 安裝JDK和Maven
此處略過過程,不清楚者可以搜索拒担。
4. 使用 Docker 部署 Spring Boot 項目
把工程copy到CentOS嘹屯,
4.1 可以先做個測試:
mvn package
java -jar target/hello-docker-0.0.1-SNAPSHOT.jar
4.2 構建
[root@spark hello-docker]# mvn package docker:build
[root@spark hello-docker]# mvn package docker:build
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building hello-docker 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ hello-docker ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ hello-docker ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ hello-docker ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /root/wsun/hello-docker/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ hello-docker ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ hello-docker ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.example.demo.HelloDockerApplicationTests
15:02:30.699 [main] DEBUG org.springframework.test.context.junit4.SpringJUnit4ClassRunner - SpringJUnit4ClassRunner constructor called with [class com.example.demo.HelloDockerApplicationTests]
..............此處省略一大段.................
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.2.RELEASE)
2019-01-16 15:02:33.921 INFO 112939 --- [ main] c.e.demo.HelloDockerApplicationTests : Starting HelloDockerApplicationTests on spark with PID 112939 (started by root in /root/wsun/hello-docker)
2019-01-16 15:02:33.922 INFO 112939 --- [ main] c.e.demo.HelloDockerApplicationTests : No active profile set, falling back to default profiles: default
2019-01-16 15:02:37.613 INFO 112939 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-01-16 15:02:38.355 INFO 112939 --- [ main] c.e.demo.HelloDockerApplicationTests : Started HelloDockerApplicationTests in 6.782 seconds (JVM running for 8.874)
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 8.475 s - in com.example.demo.HelloDockerApplicationTests
2019-01-16 15:02:38.844 INFO 112939 --- [ Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.1.1:jar (default-jar) @ hello-docker ---
[INFO] Building jar: /root/wsun/hello-docker/target/hello-docker-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.2.RELEASE:repackage (repackage) @ hello-docker ---
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
[INFO] Replacing main artifact with repackaged archive
[INFO]
[INFO] --- docker-maven-plugin:1.0.0:build (default-cli) @ hello-docker ---
15:02:44.320 [main] DEBUG com.spotify.docker.client.DockerCertificates - /root/.docker/ca.pem, /root/.docker/key.pem or /root/.docker/cert.pem does not exist, not using SSL
15:02:44.712 [main] DEBUG com.spotify.docker.client.DockerConfigReader - Using configfile: /root/.dockercfg
[INFO] Using authentication suppliers: [ConfigFileRegistryAuthSupplier]
[INFO] Copying /root/wsun/hello-docker/target/hello-docker-0.0.1-SNAPSHOT.jar -> /root/wsun/hello-docker/target/docker/hello-docker-0.0.1-SNAPSHOT.jar
[INFO] Copying src/main/docker/Dockerfile -> /root/wsun/hello-docker/target/docker/Dockerfile
[INFO] Building image springboot/hello-docker
Step 1/4 : FROM openjdk:8-jdk-alpine
---> 04060a9dfc39
Step 2/4 : VOLUME /tmp
---> Using cache
---> 6902c065fe96
Step 3/4 : ADD hello-docker-0.0.1-SNAPSHOT.jar helloapp.jar
---> e176d3a85dfd
Step 4/4 : ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/helloapp.jar"]
---> Running in ee9ce9b3d247
Removing intermediate container ee9ce9b3d247
---> 865352bb0109
ProgressMessage{id=null, status=null, stream=null, error=null, progress=null, progressDetail=null}
Successfully built 865352bb0109
Successfully tagged springboot/hello-docker:latest
[INFO] Built springboot/hello-docker
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 26.952s
[INFO] Finished at: Wed Jan 16 15:02:50 CST 2019
[INFO] Final Memory: 28M/97M
[INFO] ------------------------------------------------------------------------
4.3 查看鏡像:
[root@spark hello-docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
springboot/hello-docker latest 865352bb0109 2 minutes ago 119MB
4.4 啟動
[root@spark hello-docker]# docker run -p 8080:8080 -t springboot/hello-docker
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.2.RELEASE)
2019-01-16 07:08:03.677 INFO 1 --- [ main] com.example.demo.HelloDockerApplication : Starting HelloDockerApplication v0.0.1-SNAPSHOT on e4a6703bcdeb with PID 1 (/helloapp.jar started by root in /)
2019-01-16 07:08:03.680 INFO 1 --- [ main] com.example.demo.HelloDockerApplication : No active profile set, falling back to default profiles: default
2019-01-16 07:08:08.768 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2019-01-16 07:08:08.941 INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-01-16 07:08:08.941 INFO 1 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.14]
2019-01-16 07:08:08.988 INFO 1 --- [ main] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64/server:/usr/lib/jvm/java-1.8-openjdk/jre/lib/amd64:/usr/lib/jvm/java-1.8-openjdk/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib]
2019-01-16 07:08:09.273 INFO 1 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-01-16 07:08:09.273 INFO 1 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 5353 ms
2019-01-16 07:08:10.058 INFO 1 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-01-16 07:08:10.763 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2019-01-16 07:08:10.796 INFO 1 --- [ main] com.example.demo.HelloDockerApplication : Started HelloDockerApplication in 8.838 seconds (JVM running for 10.178)
[root@spark hello-docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e4a6703bcdeb springboot/hello-docker "java -Djava.securit…" About a minute ago Up About a minute 0.0.0.0:8080->8080/tcp serene_buck
4.5 測試
5. 使用jar包部署
我們習慣于windows下IDE開發(fā),也可以采用先打了Jar包从撼,然后在Linux上做鏡像州弟。
5.1 windows環(huán)境構建jar包
在centos7 ~ 創(chuàng)建一個文件夾docker 里面放置 上面的Dockerfile 和 springBoot 打包的項目
[root@spark docker]# ls
Dockerfile hello-docker-0.0.1-SNAPSHOT.jar
創(chuàng)建一個新的Dockerfile:
[root@spark docker]# cat Dockerfile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD hello-docker-0.0.1-SNAPSHOT.jar helloapp1.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/helloapp1.jar"]
5.2 構建鏡像
[root@spark docker]# docker build -t docker .
Sending build context to Docker daemon 16.68MB
Step 1/4 : FROM openjdk:8-jdk-alpine
---> 04060a9dfc39
Step 2/4 : VOLUME /tmp
---> Using cache
---> 6902c065fe96
Step 3/4 : ADD hello-docker-0.0.1-SNAPSHOT.jar helloapp1.jar
---> f49885f6520b
Step 4/4 : ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/helloapp1.jar"]
---> Running in bd96d074f542
Removing intermediate container bd96d074f542
---> d8731e6fca73
Successfully built d8731e6fca73
Successfully tagged docker:latest
[root@spark docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker latest d8731e6fca73 43 seconds ago 119MB
springboot/hello-docker latest 865352bb0109 About an hour ago 119MB
5.3 啟動
[root@spark docker]# docker run -d -p 8090:8090 docker
1badb56ee4610621c47053cd504f79835832e31e024ec0e1ae900c24e600185c