preface
Simply learn how to use Docker to build and publish an image in Spring Boot. Now we build an image, run a container, publish an image and so on through the remote docker api.
Only two methods are introduced here:
- Remote command api (need to know Docker command)
- maven plug-in (you don't need to know the Docker command)
Enable Docker api remote access
Enable the remote operation function of docker api,
For example, in centos 7, in the / usr/lib/systemd/system/docker.service file, modify the parameters of ExecStart:
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 because there is no password to log in and any permission verification, the certificate is required for the external network or production environment.
Command mode to build image
This method is actually very simple. You need to understand the docker command before you can operate it.
After opening the Docker Api above, we can use the network environment to operate the Docker engine.
-
Create a Dockerfile to build the image file. Create a new folder to store the files needed to build the image. I created / 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 the Dockerfile project directory.
-
Then enter the src/docker directory and execute:
docker -H tcp://xxx.xxx.xxx.xxx:2375 build -t test .
Start building the mirror:
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
?
Building images using docker Maven plugin
Add docker maven plugin under maven project
<!--pack docker Configuration of plug-in related parameters--> <plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>0.4.14</version> <configuration> <!--Packaged image name--> <imageName>${project.groupId}/${project.artifactId}</imageName> <!--Dockerfile File location to project root The directory is the root node. It is recommended to create a separate directory--> <dockerDirectory>./src/docker/</dockerDirectory> <!--Docker Remote API Address and port--> <dockerHost>http://xxx.xxx.xxx.199:2375</dockerHost> <imageTags> <imageTag>latest</imageTag> </imageTags> <!--Execute build docker What files are needed for mirroring, springboot Project specified packaged jar Just mirror--> <resources> <resource> <!--The file specified here is target Medium jar file--> <targetPath>/</targetPath> <directory>${project.build.directory}</directory> <include>${project.build.finalName}.jar</include> </resource> </resources> </configuration> </plugin>
Create Dockerfile
It needs to be consistent with the path configured above in pom.xml, so my path is ${baseProjectFolder}/src/docker. Create a new file Dockerfile and add the command parameters related to building docker:
FROM java:8 EXPOSE 8080 VOLUME /tmp ADD springboot-docker.jar app.jar # Modify according to the file name of the packaged jar package ENTRYPOINT ["java","-jar","/app.jar"]
pack
Execute the command under the root directory of the application (package and dokcer build):
$ mvn clean package docker:build -DskipTests
For example, I use my project to package and complete the construction of docker:
[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 (the IMAGE ID is consistent with the 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 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 composition
In general, many external tools are used in our WEB projects, such as Redis, MYSQL, ES, etc. if we start building and deploying one by one, it's too troublesome. We have to test. Can we use this set of environment elsewhere?
Using service orchestration can avoid these pitfalls.
Add Mysql database to our project, and create a docker-compose.yml in the root directory:
version: '3' services: web: depends_on: - db ports: - "8080:8080" # Quotation marks are recommended. If a single two digit number, parsing problems may occur restart: always # build: # context: ./src/docker # The directory of Dockerfile file, which can be a remote address, absolute or relative # dockerfile: Dockerfile # If your Dockerfile is renamed, you need to specify image: test:latest environment: DB_HOST: db:3306 DATABASE: learn DB_USERNAME: root # root for test DB_PASSWORD: 123456 # # It is recommended to use 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: # The data volume used must be declared
Above, I use the previously built image and then execute the orchestration. Better, I use build directly to make it choreograph the service itself.
The system configuration file application.yml uses the default value, which 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 # Select the dialect according to the database version
You can also use different spring.profiles to specify different environments. It is also common to override the specified environment for executing commands in docker-compose.yml: Command: MVN clean spring boot: Run - dspring boot. Run. Profiles = XXX
Finally, start and execute in the docker-compose.yml Directory: docker compose up
Close the service docker compose down
be careful
The problem of docker compose sequence is a problem that needs attention when learning 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 service is started or not.
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 composition is split and deployed in two parts. The services to be started first are placed in one docker composition, and the services to be started later are placed in two docker compositions. They are started twice and use the same network.
- Wait synchronously. Use wait-for-it.sh or other shell scripts to start blocking the current service until the dependent service is loaded
The github address of wait for it is: wait-for-it
summary
- When writing Dockerfile, I'd better take out a separate folder and put it in the root path of the project. As a result, when building the image, it always appears that other files are copied to the Docker directory together. For the operation of using the maven plug-in under windows, we need to pay attention to this context, Otherwise, it's easy to copy all the files on a disk. It's 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 consider so many problems.