I know all of you have read my articles on Docker these days. They are not painful, but you still don’t feel the convenience of Docker. Yes, I think so too.
It is really boring to understand the concept in the early stage, please don’t worry about the exciting start. When you have some understanding of docker related concepts, I will give you a series of small examples combined with Spring Boot later, which will make you feel so cool to use Docker!
Today’s performance is directed by Docker-Compare of the Docker family, starring three big bowls of red and purple, Spring Boot, Nginx and Mysql. When the famous directors play together, they are always ready to make trouble. Next, another classic blockbuster is worth everyone’s expectation.
Spring Boot + Nginx + Mysql is the most commonly used combination in practical work. The most front-end uses Nginx proxy to forward requests to the Tomcat service embedded in the back-end Spring Boot. Mysql is responsible for data-related interactions in the business. So how did we navigate these environments before Docker?
- 1. Install Nginx, configure Nginx information, and restart the system.
- 2. Install Mysql, configure the character set and time zone, restart Mysql, and initialize the script.
- 3. Start the Spring Boot project and conduct the overall joint commissioning test.
As you can see, I’ve only written three lines, but it takes a lot of work to set up these environments, but that’s not the end. When you use them for a period of time, you have to move to another environment. How do you do it again? Under normal circumstances, test environment, SIT environment, UAT environment, production environment! We need to repeat the setup four times. Some people say it’s not four times? It’s not a big deal, so I want to tell you,Too yong,Too Simple.
Let’s look at a few factors:
First, this is just the simplest case, if the project involves MongoDB, Redis, ES… What about a bunch of environments? Second, if you often build environments or debug programs, you know what environment problems are? Sometimes it’s exactly the same configuration, but it doesn’t work in another environment. You spend a lot of time looking it up, only to discover that there is a missing argument or comma, or that the kernel version of the system is inconsistent, or you don’t understand why! You can only change to another server, so using Docker can perfectly avoid these pits.
All right, let’s get started without further ado!
Spring Boot case
Let’s first prepare a small scenario with Spring Boot using Mysql. Let’s do this example. Use Spring Boot to make a Web application, providing a method to count the number of accesses by IP address. The statistics are stored in Mysql and displayed on the page on each request.
Configuration information
Depend on the 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>
Copy the code
Add Spring Boot Web support, use Jpa to operate database, add Myql driver package, etc.
The 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
Copy the code
The link information for the database is configured, and Jpa updates the table schema, dialect, and whether Sql is displayed
The core code
The core code is very simple, every time a request comes, determine whether the statistics have been counted, if not counted new data, if there is statistical data update 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."; }}Copy the code
The entity class and Repository layer code is relatively simple, so I won’t post it here. If you are interested, you can download the source code to view it.
When all is said and done, start the project and go to: http://localhost:8080/ and we should see something like this:
I have been seen ip 0:0:0:0:0:0:0:1 1 times.
Copy the code
If I visit it again, it will become
I have been seen ip 0:0:0:0:0:0:0:1 2 times.
Copy the code
Multiple visits have been superimposed, indicating that the demonstration project development is complete.
Docker reformed
First, let’s transform the directory into this structure
Let’s start with the outermost layer:
docker-compose.yaml
Docker-compose: the core docker-compose file, which describes how to build the entire servicenginx
: About nginx configurationapp
: Address of the Spring Boot project
If we need to customize Mysql specifically, we can also create a Mysql folder on the outermost layer and configure it in this directory.
docker-compose.yaml
File,
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=dockerCopy the code
version: '3'
: indicates that the docker-comemage. yaml file is built using the third generation syntax.services
: is used to represent the service that compose needs to start. There are three services in this file: nginx, mysql, app.container_name
: Container nameenvironment
: Information under this node is passed into the container as environment variables. In this example, the mysql service is configured with database, password, and permission information.ports
: indicates an open portrestart: always
Indicates that the service will continue to try if the service fails to start.volumes
: Loads the configuration file in the local directory to the container target addressdepends_on
: Indicates that a dependent service can be configured, indicating that the service must be started firstdepends_on
Start the service after the following service.command: mvn clean spring-boot:run -Dspring-boot.run.profiles=docker
: indicates to start the project with this command,-Dspring-boot.run.profiles=docker
Said the use ofapplication-docker.properties
File configuration information for startup.
Nginx file interpretation
Nginx has a file app.conf in the directory, which mainly configures the 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; }}Copy the code
This part is relatively simple. Configure request forwarding to forward requests from port 80 to port 8080 of the service app. The proxy_pass http://app:8080 configuration information needs to be explained. The reason for using app instead of localhost is that they are not in the same container, and the communication between the compose service needs to be accessed using the name of services.
Spring Boot project transformation
Add the Dockerfile file to the app directory at the same level as the pom.xm file.
The FROM maven: 3.5 JDK - 8Copy the code
Only one sentence, depending on the base image maven3.5 and JDK 1.8. Because the project startup command is set up in the docker-comemage. yaml file, there is no need to add the startup command.
Create application-dev.properties and application-docker.properties files in the resources directory of your project
application-dev.properties
The configuration information is the same as the precedingapplication-docker.properties
In the configuration information to do a slight transformation, the database connection information byjdbc:mysql://localhost:3306/test
Instead ofjdbc:mysql://mysql:3306/test
。
So we have all the configuration done.
The deployment of
We will copy the project to the server for testing. The server needs to install Docker and Docker Compos environment first. If you don’t know, you can check my previous two articles:
- Docker(1) : Docker introduction tutorial
- Docker Compose (4) : Docker Compose
Copy the project to the server and go to CD dockercomposing -springboot-mysql-nginx
Start the 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 - [the main] O.S.B.W.E mbedded. Tomcat. TomcatWebServer: tomcat is started on the port (s) : 8080 (HTTP) with the context path 'app_1 | 2018-03-26 02:54:55. 660 INFO 1 - [the main] com.neo.Com poseApplication: Started ComposeApplication in 14.869 seconds (JVM running for 30.202)Copy the code
Tomcat started on port(s): 8080 Indicates that the service is successfully started. You can also use docker-compose up -d to start in the background
Access server address; http://58.87.69.230/, return: I have been seen IP 172.19.0.2 1 times. The overall service is successfully started
usedocker-compose ps
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; The Up 0.0.0.0:443 - > 443 / TCP, 0.0.0.0:80 - > 80 / TCPCopy the code
You can see the status, command, port, and other information of the service in the project.
Close the servicedocker-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
Copy the code
Docker – compose sequence
When docker-compose is used for startup, the project often reported Mysql connection exception. After tracking for a day, the problem was finally found. Docker-compose can use depends_on to define the order of service startup, but cannot determine whether the service has been started. Therefore, Mysql service startup is slow. When the Spring Boot project has been started, However, Mysql has not been initialized yet, so when the project connects to the Mysql database, it will have an exception to connect to the database.
There are two solutions to this problem:
1. Sufficient fault tolerance and retry mechanisms, such as connecting to a database. If the initial connection fails, the service consumer can retry again and again until the service is connected. That is, in the service definition: restart: always
2. Wait synchronously. Use wait-for-it-sh or other shell scripts to start and block the current service until the dependent service is loaded. This scheme can be tried later.
conclusion
No comparison, no harm, before the use of Docker, we need to build such an environment, we need to install Nginx, Mysql, and then a series of configuration debugging, but also worry about various environmental problems; After using Docker, two simple commands can complete the online and offline service.
docker-compose up
docker-compose down
Copy the code
Swarm is the first batch of container technology to optimize deployment operations. Swarm is the first batch of container technology to optimize deployment operations. Swarm is the first batch of container technology to optimize deployment operations.
Example code – Github
Example code – code cloud
reference
Docker Compose with Spring Boot, MySQL and NGINX