foreword
Simply learn how to use Docker to build and publish an image in Spring Boot. Now we build an image, run a container, and publish an image through the remote docker api.
Here are only two ways:
- Remote command api (need to know Docker commands)
- maven plugin (no need to know Docker commands)
Enable Docker api remote access
Enable the function of docker api remote operation,
for example, in centos 7, in /usr/lib/systemd/system/docker.service
the file, modify ExecStart
the parameters:
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
You can customize the port settings.
Reload all modified configuration files and restart docker,
systemctl daemon-reload
systemctl restart docker.service
It should be noted that since there is no password to log in to any authority verification, the external network or production environment needs to be used with a certificate.
Build image by command
This method is actually very simple, that is, you need to know the docker command to operate.
After opening the Docker Api above, we can use the network environment to operate the Docker engine.
Create a new
Dockerfile
build image file, create a new folder, specially put the files needed to build the image, what I created is/src/docker/
FROM java:8 EXPOSE 8080 VOLUME /tmp ADD springboot-docker.jar app.jar ENTRYPOINT ["java","-jar","/app.jar"]
Execute the maven command to package the project
mvn clean package --DskipTests
, and then put the jar package into theDockerfile
project directory.Then enter the
src/docker
directory and execute:docker -H tcp://xxx.xxx.xxx.xxx:2375 build -t test .
Start building the image:
Sending build context to Docker daemon 31.74MB Step 1/5 : FROM java:8 ---> d23bdf5b1b1b Step 2/5 : EXPOSE 8080 ---> Using cache ---> 060a43a42146 Step 3/5 : VOLUME /tmp ---> Using cache ---> b4f88fde6181 Step 4/5 : ADD springboot-docker.jar app.jar ---> 3a40188825b0 Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"] ---> Running in ab093916fc4c Removing intermediate container ab093916fc4c ---> 45a3966feb60 Successfully built 45a3966feb60 Successfully tagged test:latest
Build images with docker-maven-plugin
Join under the maven projectdocker-maven-plugin
<!--打包docker插件相关参数的配置-->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.4.14</version>
<configuration>
<!--打包的镜像名-->
<imageName>${project.groupId}/${project.artifactId}</imageName>
<!--Dockerfile文件位置,以项目的 root 目录为根节点,建议到单独建立一个目录-->
<dockerDirectory>./src/docker/</dockerDirectory>
<!--Docker 远程的 API 地址及端口-->
<dockerHost>http://xxx.xxx.xxx.199:2375</dockerHost>
<imageTags>
<imageTag>latest</imageTag>
</imageTags>
<!--执行构建docker镜像的时候需要哪些文件,springboot项目指定 打包好的jar 镜像就好-->
<resources>
<resource>
<!--这里指定的文件是target中的jar文件-->
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
Create Dockerfile
It needs to be pom.xml
consistent with the path configured above, so my path is to create a new file under ${baseProjectFolder}/src/docker
the folder of Dockerfile
, and add command parameters related to building docker:
FROM java:8
EXPOSE 8080
VOLUME /tmp
ADD springboot-docker.jar app.jar # 根据打包的jar 包文件名进行修改
ENTRYPOINT ["java","-jar","/app.jar"]
Pack
Execute the command in the root directory of the application (package and dokcer build):
$ mvn clean package docker:build -DskipTests
For example, using my project to complete the docker build information after packaging:
[INFO] Building image com.wuwii/springboot-docker
Step 1/5 : FROM java:8
---> d23bdf5b1b1b
Step 2/5 : EXPOSE 8080
---> Running in b7936baae57f
Removing intermediate container b7936baae57f
---> 060a43a42146
Step 3/5 : VOLUME /tmp
---> Running in 65e2b8ac44d3
Removing intermediate container 65e2b8ac44d3
---> b4f88fde6181
Step 4/5 : ADD springboot-docker.jar app.jar
---> aa3762cda143
Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"]
---> Running in d9f5f63b9736
Removing intermediate container d9f5f63b9736
---> 622a7d1e315c
ProgressMessage{id=null, status=null, stream=null, error=null, progress=null, progressDetail=null}
Successfully built 622a7d1e315c
Successfully tagged com.wuwii/springboot-docker:latest
use mirror
Enter the host where docker is installed, and use the command to view the image (
IMAGE ID
same as above):$ docker image ls com.wuwii/springboot-docker REPOSITORY TAG IMAGE ID CREATED SIZE com.wuwii/springboot-docker latest 622a7d1e315c 22 minutes ago 659MB
Run the container:
$ docker run -d -p 8080:8080 --name learn com.wuwii/springboot-docker 180fe4a7ddfc10c0cf2c37649ae1628e804564bfe1594ef05840e707801e6da3
Listen to port 8080 and test whether it is successful.
service orchestration compose
Generally, our WEB projects will use a lot of external tools, such as Redis, MYSQL, ES, etc. If we start the deployment one by one, it will be too troublesome. We also need to test if this set of environments can be used elsewhere. ?
These pitfalls can be avoided by using service orchestration.
Adding a Mysql database to our project, create a new one in the root directory docker-compose.yml
:
version: '3'
services:
web:
depends_on:
- db
ports:
- "8080:8080" # 建议加上引号,如果单独两位数的数字,可能出现解析问题
restart: always
# build:
# context: ./src/docker # Dockerfile 文件的目录,可以远程地址,绝对 or 相对
# dockerfile: Dockerfile # 如果你的 Dockerfile 重命名了,需要指定
image: test:latest
environment:
DB_HOST: db:3306
DATABASE: learn
DB_USERNAME: root # 测试用下 root
DB_PASSWORD: 123456 # # 建议使用 secret
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: learn
MYSQL_USER: kronchan
MYSQL_PASSWORD: 123456
volumes:
db_data: # 使用的数据卷必须声明
Above I used the image that has been built before, and then executed the orchestration. It is better to use it directly to build
let it orchestrate the service itself.
The way the system configuration file application.yml
uses default values does not affect the use of development:
spring:
datasource:
url: jdbc:mysql://${DB_HOST:localhost:3306}/${DATABASE:learn}?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD:123456}
driver-class-name: com.mysql.jdbc.Driver
jpa:
show-sql: true
database: mysql
hibernate:
ddl-auto: update
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL57Dialect # 方言根据 数据库版本选择吧
You can also use different to spring.profiles
specify different environments. It docker-compose.yml
is also common practice to override the execution command to specify the environment in :command: mvn clean spring-boot:run -Dspring-boot.run.profiles=xxx
Finally start, execute in the docker-compose.yml
directory :docker-compose up
shut down servicedocker-compose down
Notice
The problem of docker-compose order, this is a problem that needs to be paid attention to when starting to learn orchestration. If mysql starts slowly in the above service orchestration, the web project will fail to start. When it starts, it does not know whether the dependent services are started or not. , this problem occurs.
The solutions are as follows:
- Sufficient fault tolerance and retry mechanisms, such as connecting to the database, when the initial connection fails, the service consumer can continue to retry until the location is connected
- Docker-compose is split and deployed in two parts. The services to be started first are placed in one docker-compose, and the services to be started later are placed in two docker-composes, which are started twice, and both use the same network.
- Synchronously wait, use
wait-for-it.sh
or othershell
scripts to start and block the current service until the dependent service is loaded
wait-for-it
. The github address is: wait-for-it
Summarize
- Mainly, when writing Dockerfile, it is best to take out a separate folder to put it. When I started, I put it directly in the root path of the project. As a result, when building the image, it always appeared that other files were also copied to Docker. In the directory, you need to pay attention to this context when using the maven plug-in under WINDOW. Otherwise, it is easy to copy all the files of a disk in, which is a lesson for beginners. The solution is to create a separate folder and put the things you need separately, so you don't have to think about so many problems.