I know you have read several articles I wrote about docker during this period. It's not painful or itchy, and you still don't feel the convenience of docker. Yes, I know your felling.
It's really boring to know what the concept is in the early stage. Please don't rush to start at once. When you know something about docker, I'll give you a series of small examples with Spring Boot, which will make you feel that using Docker is so cool.
Today's director is Docker family's docker-comparison, starring Spring Boot, Nginx, Mysql three red and purple bowls. When famous directors are together, they are often ready to do something. The next classic blockbuster is worth looking forward to.
Spring Boot + Nginx + Mysql is the most commonly used combination in practical work. The front end uses Nginx proxy to forward requests to Tomcat service embedded in the back end Spring Boot. Mysql is responsible for data-related interaction in business. So how can we solve these environments without docker?
- 1. Install Nginx, configure Nginx-related information, and restart.
- 2. Install Mysql, configure character set time zone and other information, restart, and finally initialize the script.
- 3. Start Spring Boot project and conduct debugging test as a whole.
You see, I only wrote three lines, but in fact, it's very difficult to build these environments, but this is not the end. It takes a while to migrate to another environment. What should we do again? Normally, test environment, SIT environment, UAT environment, production environment! We need to build it four times. Didn't someone say that it was built four times? It's no big deal, so I want to tell you, Too yong, Too Simple.
Let's look at the following factors:
First, this is only the simplest case, if the project involves MongoDB, Redis, ES... What about some of the environments?
Second, if you build environments or debug programs regularly, you will know what environmental problems are. Sometimes it's exactly the same configuration, but in another environment it's impossible to run. So you spend a lot of time looking for it, only to find that there is a missing parameter or comma problem, or that the kernel version of the system is inconsistent, or that you don't understand why in the end! Only one server can be replaced, so using Docker can avoid these pits perfectly.
Well, let's start without much nonsense.
Spring Boot case
First, we will prepare a small scenario of Spring Boot using Mysql. Let's give an example of a Web application using Spring Boot, which provides a method of counting the number of visits according to IP address. Each time we request, we store the statistics in Mysql and display them on the page.
configuration information
Dependency package
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Spring Boot Web support is added, Jpa is used to operate database, Myql driver package is added, etc.
configuration file
spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.jpa.properties.hibernate.hbm2ddl.auto=update spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect spring.jpa.show-sql=true
Configured database link information, Jpa update table schema, dialect, and whether Sql is displayed
Core code
The core code is very simple. Every time a request comes, it determines whether it has been counted, if there is no new data, if there is statistical data to update the data.
@RestController
public class VisitorController {
@Autowired
private VisitorRepository repository;
@RequestMapping("/")
public String index(HttpServletRequest request) {
String ip=request.getRemoteAddr();
Visitor visitor=repository.findByIp(ip);
if(visitor==null){
visitor=new Visitor();
visitor.setIp(ip);
visitor.setTimes(1);
}else {
visitor.setTimes(visitor.getTimes()+1);
}
repository.save(visitor);
return "I have been seen ip "+visitor.getIp()+" "+visitor.getTimes()+" times.";
}
}
Entity class and Repository layer code is relatively simple, not posted here, you are interested in downloading the source code to view.
When all of the above is completed, start the project and visit http://localhost:8080/we can see the return result as follows:
I have been seen ip 0:0:0:0:0:0:0:1 1 times.
A second visit will become
I have been seen ip 0:0:0:0:0:0:0:1 2 times.
Multiple visits have been superimposed to illustrate the completion of the demonstration project development.
Docker ization Reform
First, we'll transform the directory into such a structure.
Let's start with the outermost layer:
- docker-compose.yaml: docker-compose core file that describes how to build the entire service
- Nginx: Configuration of nginx
- app: Spring Book Project Address
If we need to customize Mysql, we can also create a MySQL folder at the outermost level and configure it in this directory.
Doker-compose.yaml file details
version: '3' services: nginx: container_name: v-nginx image: nginx:1.13 restart: always ports: - 80:80 - 443:443 volumes: - ./nginx/conf.d:/etc/nginx/conf.d mysql: container_name: v-mysql image: mysql/mysql-server:5.7 environment: MYSQL_DATABASE: test MYSQL_ROOT_PASSWORD: root MYSQL_ROOT_HOST: '%' ports: - "3306:3306" restart: always app: restart: always build: ./app working_dir: /app volumes: - ./app:/app - ~/.m2:/root/.m2 expose: - "8080" depends_on: - nginx - mysql command: mvn clean spring-boot:run -Dspring-boot.run.profiles=docker
- Version:'3': Represents the use of third-generation grammar to build docker-compose.yaml files.
- Services: Used to represent the services compose needs to start, we can see that there are three services in this file: nginx, mysql, app.
- container_name: Container name
- Environment: The information under this node is passed into the container as an environment variable. In this example, the mysql service configures database, password, and privilege information.
- ports: ports that are open to the outside world
- restart: always indicates that if the service starts unsuccessfully, it will try all the time.
- volumes: Load the configuration file in the local directory to the container destination address
- Dependent_on: Dependent services can be configured to indicate that the services under dependent_on need to be started before starting this service.
- Command: MVN clean spring-boot: run-Dspring-boot.run.profiles=docker: means to start a project with this command, and - Dspring-boot.run.profiles=docker means to start with application-docker.properties file configuration information.
Interpretation of Nginx Files
nginx has a file app.conf in the directory, which mainly configures service forwarding information.
server { listen 80; charset utf-8; access_log off; location / { proxy_pass http://app:8080; proxy_set_header Host $host:$server_port; proxy_set_header X-Forwarded-Host $server_name; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /static { access_log off; expires 30d; alias /app/static; } }
This piece of content is relatively simple, configuring request forwarding, forwarding the request of port 80 to port 8080 of service app. The configuration information of proxy_pass http://app:8080 needs to be explained. App is used here instead of localhost, because they are not in a container, and the service communication of a group of compose needs to be accessed by the name of services.
Spring Boot Project Renovation
In the app directory, the Dockerfile file is added at the same level as the pom.xm file. The contents of the file are as follows:
FROM maven:3.5-jdk-8
Only one sentence, depending on the base mirror Maven 3.5 and jdk 1.8. Because the project startup command is set in the docker-compose.yaml file, there is no need to add the startup command here.
Create application-dev.properties and application-docker.properties files under the resources directory of the project
- Configuration information in application-dev.properties is consistent with the above
- The configuration information in application-docker.properties is slightly modified, and the connection information of the database is changed from jdbc:mysql://localhost:3306/test to jdbc:mysql://mysql:3306/test.
So all our configurations have been completed.
deploy
We will copy the project to the server for testing. The server needs to install the Docker and Docker Compos environment first. If you don't know anything about it, you can see my two previous articles:
Copy the project to the server and enter the directory CD docker compose-spring boot-mysql-nginx
Start service: docker-compose up
[root@VM_73_217_centos dockercompose-springboot-mysql-nginx]# docker-compose up Creating network "dockercomposespringbootmysqlnginx_default" with the default driver Creating v-nginx ... done Creating v-mysql ... done Creating dockercomposespringbootmysqlnginx_app_1 ... done Attaching to v-nginx, v-mysql, dockercomposespringbootmysqlnginx_app_1 v-mysql | [Entrypoint] MySQL Docker Image 5.7.21-1.1.4 v-mysql | [Entrypoint] Initializing database app_1 | [INFO] Scanning for projects... ... app_1 | 2018-03-26 02:54:55.658 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' app_1 | 2018-03-26 02:54:55.660 INFO 1 --- [ main] com.neo.ComposeApplication : Started ComposeApplication in 14.869 seconds (JVM running for 30.202)
See the information Tomcat started on port(s): 8080 indicates that the service started successfully. You can also use docker-compose up-d background boot
Access the server address; http://58.87.69.230/, return: I have seen IP 172.19.0.21 times. Represents that the overall service started successfully.
Use docker-compose ps to view all current containers in the project
[root@VM_73_217_centos dockercompose-springboot-mysql-nginx]# docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------------------------------------------------------
dockercomposespringbootmysqlnginx_app_1 /usr/local/bin/mvn-entrypo ... Up 8080/tcp
v-mysql /entrypoint.sh mysqld Up (healthy) 0.0.0.0:3306->3306/tcp, 33060/tcp
v-nginx nginx -g daemon off; Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
You can see the status, commands, ports and other information of the services in the project.
Close the service docker-compose down
[root@VM_73_217_centos dockercompose-springboot-mysql-nginx]# docker-compose down
Stopping dockercomposespringbootmysqlnginx_app_1 ... done
Stopping visitor-nginx ... done
Stopping visitor-mysql ... done
Removing dockercomposespringbootmysqlnginx_app_1 ... done
Removing visitor-nginx ... done
Removing visitor-mysql ... done
docker-compose order
When using docker-compose startup, Mysql connection anomalies often occur in the project report. After a day of tracking, the problem is finally found. Although docker-compose can define the order of service startup by depend_on, it can not determine whether the service is started or not, so there will be a phenomenon that Mysql service startup is slow. When Spring Book project has been started, but Mysql has not been initialized, so when the project connects to Mysql database, there will be a connection to the database. Abnormal.
There are two solutions to this problem:
1. Adequate fault-tolerant and retrial mechanisms, such as connecting to databases, can be retried by service consumers until the first connection fails. That is to say, in services: restart: always
2. Wait synchronously and use wait-for-it.sh or other shell scripts to block the current service startup until the dependent service is loaded. This scheme can be tried later.
summary
Without comparison, there is no harm. Before using Docker, we need to build such an environment. We need to install Nginx and Mysql, debug a series of configurations, and worry about various environmental problems. After using Docker, we can finish the service online and offline with two simple commands.
docker-compose up
docker-compose down
In fact, container technology is still a lot of optimization of deployment operation and maintenance, which is just the beginning, after the use of Swarm will really feel its convenience and strength.