Learning Spring Boot: (23) Using Docker in Spring Boot

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:

  1. Remote command api (need to know Docker commands)
  2. 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.servicethe file, modify ExecStartthe 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.

  1. Create a new Dockerfilebuild 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"]
  2. Execute the maven command to package the project mvn clean package --DskipTests, and then put the jar package into the Dockerfileproject directory.

  3. Then enter the src/dockerdirectory 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.xmlconsistent with the path configured above, so my path is to create a new file under ${baseProjectFolder}/src/dockerthe 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

  1. Enter the host where docker is installed, and use the command to view the image ( IMAGE IDsame 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
  2. 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 buildlet it orchestrate the service itself.

The way the system configuration file application.ymluses 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.profilesspecify different environments. It docker-compose.ymlis 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.ymldirectory :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.shor other shellscripts to start and block the current service until the dependent service is loaded
    wait-for-it. The github address is: wait-for-it

Summarize

  1. 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.

code

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325724034&siteId=291194637