At present, we have updated the “Java Concurrent Programming” and “Docker tutorial”, welcome to pay attention to the “back-end advanced road”, easy to read all articles.

Java concurrent programming:

  • Java Concurrent Programming Series -(1) Concurrent programming basics
  • Java Concurrent Programming Series -(2) Concurrency utility classes for threads
  • Java Concurrent Programming series -(3) Atomic Operations with CAS
  • Java Concurrent Programming series -(4) Explicit locks with AQS
  • Java Concurrent Programming Series -(5) Java concurrent containers
  • Java Concurrent Programming Series -(6) Java thread pools
  • Java Concurrent Programming Series -(7) Java thread safety
  • Java Concurrent Programming series -(8) JMM and underlying implementation principles
  • Java Concurrent Programming Series -(9) Concurrency in JDK 8/9/10

Docker tutorial:

  • Docker series -(1) Principle and basic operation
  • Docker series -(2) image production and release
  • Docker series -(3) Docker-compose usage and load balancing

JVM Performance optimization:

  • JVM Performance Optimization Series -(1) Java Memory region
  • JVM Performance Optimization Series -(2) Garbage collector and Memory allocation Strategies

The last article introduced the production and release of Docker images. This article mainly introduces docker-compose tool, which is often used in actual Docker engineering deployment, as well as docker network configuration and load balancing.

Docker – compose is introduced

In the actual development process, we often put different modules in separate Docker in a project, which is convenient for maintenance and expansion. For example, one of our projects may have MySQL images, Nginx images, and Spring Boot backend images. In actual deployment, we can adopt the method introduced in the previous article to package and start them separately. But this takes too much effort and is prone to error. Therefore, docker-compose tool came into being to solve the management problem of multiple Docker images in engineering deployment.

Docker – compose. Yaml files

Just as you need a Dockerfile for your build image, you need a similar configuration file called docker-comemess.yaml to use docker-compose.

Here is an example of a docker-file:

Note the following points in the docker-compose file:

  • Version: ‘3’ : indicates that the syntax of the third generation is used. Each generation has a slightly different syntax, so we choose the latest one.
  • Services: represents the service that compose needs to start. Typically, a docker image can be used as a separate service.
  • Container_name: indicates the name of the container
  • We can use this parameter to pass variables to the container. This is useful when we switch between different environment configurations without having to change the configuration in the code every time
  • Ports: open ports
  • Restart: always: if the service fails to start, keep trying.
  • Volumes: load the local directory to the container target directory. Share the local directory with the container for data interaction. You can also output the docker log to the specified location on the host.
  • Depends_on: Start the depends_on service.
  • Command: MVN clean spring-boot:run: the command is used to start the project

A depends_on method is used to start different images in sequence, such as waiting for the database to be initialized. This method does not guarantee that the preceding container is fully initialized. This method means that the current container will be started if the preceding container is started. In this case, the presequence container is not initialized, and subsequent container startup will lead to connection failure and other errors.

So the best way is the official (docs.docker.com/compose/sta…). The recommended wait scripts can be found at github.com/vishnubob/w… .

wait-for-it.sh host:port [-s] [-t timeout] [-- command args]
-h HOST | --host=HOST       Host or IP under test
-p PORT | --port=PORT       TCP port under test
                            Alternatively, you specify the host and port as host:port
-s | --strict               Only execute subcommand if the test succeeds
-q | --quiet                Don't output any status messages -t TIMEOUT | --timeout=TIMEOUT Timeout in seconds, zero for no timeout -- COMMAND ARGS Execute command with args after the test finishesCopy the code

You can also specify a certain amount of time to wait while creating the image. In the following example, elasticSearch is initialized before running test.jar.

FROM openjdk:8
ADD ["The target/test - 1.0.0. Jar"."test.jar"]
ADD ["wait-for-it.sh"."wait-for-it.sh"]
RUN ["chmod"."+x"."wait-for-it.sh"]
EXPOSE 1234
ENTRYPOINT ["./wait-for-it.sh"."elastic:9200"."--"."java"."-jar"."/test.jar"]
Copy the code

Details about more docker – compose file, you can refer to the official document docs.docker.com/compose/get…

Docker-compose start/stop

Docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose

Docker network communication

The network aspect of Docker is relatively weak. If A novice does not know why container A cannot access container B, the problem will often occur.

Communication between containers

A common scenario is that we need to debug both the front end and the back end on the host. Usually we start the front end at a localhost port, such as 8080; Start the backend on another local port, such as 1234. Without the container, it is possible for the front end to access all interfaces of localhost:1234 directly in the code without any problems.

However, if the front end and back end are wrapped in different containers, then the front end directly accesses localhost:1234, and an error is reported. The reason is that the two containers are independent and cannot be accessed directly by localhost.

The official solution is to create a new network and then specify that both the front and back end containers run on that network when they start.

docker network create mynet
docker run --network mynet --name frontend ...
docker run --network mynet --name backend ...
Copy the code

The front-end can now access the back-end interface via http://backend:1234.

Note: some blogs point out that you can get the IP of the back-end container by using docker inspect [container_name] and then directly accessing the IP and port. This may work on Linux, but it is not directly accessible over IP on MAC due to the container implementation principle.

Docker-compose network environment

By default, when you start multiple containers with Docker-compose, docker-compose will automatically create a network for you and run multiple services in that network. Therefore, between different containers, directly using the container name + port can be accessed.

Docker-compose implements load balancing

In actual production environments, multiple back-end services must be started and load balancing is performed simultaneously to ensure service quality. With Docker-compose, we can easily achieve this function.

Docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose Backend :5000 Can also be used to access backend services inside the front container.

version: "3"

services:
  front:
    image: front:latest
  backend:
    image: "backend:latest"
    ports:
      - "5000:5000"
Copy the code

Docker-compose provides a –scale parameter for load balancing, which makes it easy to start multiple services at the same time. The following are instructions for using this parameter.

--scale SERVICE=NUM        Scale SERVICE to NUM instances. Overrides the
                           `scale` setting in the Compose file if present.
Copy the code

In this case, we specify to generate three back-end services directly at startup.

docker-compose up --scale backend=3
Copy the code

Docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose: docker-compose

version: "3"

services:
  front:
    image: front:latest
  backend:
    image: "backend:latest"
    ports:
      - "5000"
Copy the code

After following the same instructions above, you can see the following output: there are three different native ports bound to port 5000 of the container.

Name Command State Ports -------------------------------------------------------------------------------------------- example_backend_1 /usr/bin/dumb-init -- /sbi ... Up (healthy) 0.0.0.0:32776->5000/tcp example_backend_2 /usr/bin/dumb-init -- /sbi... Up (healthy) 0.0.0.0:32775->5000/tcp example_backend_3 /usr/bin/dumb-init -- /sbi... The Up (healthy) 0.0.0.0:32777 - > 5000 / TCPCopy the code

Of course, if you only want to access port 5000 on the back end from inside the container, you can remove the port configuration and change it to the following configuration:

version: "3"

services:
  front:
    image: front:latest
  backend:
    image: "backend:latest"
Copy the code

Docker-compose up –scale backend=3 after startup, we can only access the backend service inside the container with http:\\backend:5000 because we started three, Requests from the front end are randomly allocated to the three services at the back end to ensure the overall service quality.

Reference links:

  • Stackoverflow.com/questions/4…
  • Pspdfkit.com/blog/2018/h…

Search “The Way to back-end Improvement” and follow to get the latest articles and BATJ premium interview courses worth 2000 yuan.