How to deploy a project with Docker Compose?

Posted by tlchung on Thu, 17 Feb 2022 02:10:25 +0100

  • 💻 Sword finger offer & leetcode question brushing warehouse: https://github.com/Damaer/CodeSolution
  • 📒 Programming knowledge base: https://github.com/Damaer/Coding
    • Document address: https://damaer.github.io/Coding/#/
  • preface
  • Docker Compose
    • 1. What is docker compose?
    • 2. Specific steps of docker compose
    • 3. How to use Docker Compose in an IDEA project

preface

Previously, we deployed springboot, redis and mysql projects with docker, but they are deployed in three different containers. We also need to know the ip addresses of redis and mysql first and manually configure them into the springboot application container. I just want to test them locally quickly. This cost is too high. Is there any way to centrally manage them? For example, build it into a mirror image.

There is always a way. That is Docker Compose.

Previous project address: https://github.com/Damaer/DemoCode/tree/main/springboot/springDocker

Docker Compose

1. What is docker compose?

Docker Compose is actually a docker tool used to define and run complex applications. What is a complex application? For example, the previously written springboot+redis+mysql has three containers. This kind of multiple containers is managed by one tool. Isn't it fragrant?

Docker compose manages multiple docker containers through a configuration file. In the configuration file, all containers are defined through services, and then docker compose script is used to start, stop and restart the application, as well as the services and dependent containers in the application.

2. Specific steps of docker compose

There are generally three steps:

  • Use Dockerfile to define the environment of the application
  • At docker compose YML defines the services that make up the application so that they can run together in an isolated environment.
  • Execute the docker compose up command to start and run the entire application.

I use Mac OS. Docker Compose is also installed when docker is installed. There is no need to install it separately.

3. How to use Docker Compose in an IDEA project

First, POM In the XML file, you should pay attention to the configuration of lowercase artifactId:

    <groupId>com.aphysia</groupId>
    <artifactId>dockerdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>dockerdemo</name>
    <packaging>jar</packaging>

In addition, you need to configure plug-ins:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.0.0</version>
                <!-- Bind a plug-in to a phase implement -->
                <executions>
                    <execution>
                        <id>build-image</id>
                        <!-- Users only need to execute mvn package ,It will be executed automatically mvn docker:build -->
                        <phase>package</phase>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
                    <dockerDirectory>src/main/docker</dockerDirectory>
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
        </plugins>
    </build>

In addition, dockerfile is necessary. The above plug-in has been configured. We need to put dockerfile in < dockerdirectory > Src / main / docker < / dockerdirectory >, and the configuration in dockerfile is as follows:

FROM openjdk:8-jdk-alpine
EXPOSE 8081
VOLUME /tmp
# Rewrite and name it app jar
ADD dockerdemo-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

Theoretically, by this time, we will generate the corresponding jar package by using mvn clean package:

image-20211128215558740

The most important thing for docker compose is to configure docker compose YML, we can put this file in the root directory of the project, and POM XML level:

version: "3"

services:
  redis:
    image: redis:latest
    restart: always
    ports:
      - "6389:6379"
    volumes:
      - /tmp/redis.conf:/etc/redis/redis.conf
    command: redis-server /etc/redis/redis.conf

  mysql:
    image: mysql:latest
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: "123456"
      MYSQL_USER: 'root'
      MYSQL_PASS: '123456'
    ports:
      - "3306:3306"
    volumes:
      - "./db:/var/lib/mysql"
      - "./conf/my.cnf:/etc/my.cnf"
      - "./init:/docker-entrypoint-initdb.d/"
  # Specify service name
  webapp:
    # Specifies the image used by the service
    image: aphysia/dockerdemo
    # Specify container name
    container_name: dockerdemo
    # Specifies the port on which the service runs
    ports:
      - 8081:8081
    # Specify the files that need to be mounted in the container
    volumes:
      - /etc/localtime:/etc/localtime
      - /tmp/dockerdemo/logs:/var/logs

Notable points:

service is the image we configured, including redis, MySQL and webapp. Webapp is actually our application.

In "6389:6379", 6389 is actually the port of our host, that is, my Mac needs to use 6389 to connect to the redis container, while the connection between containers needs to use 6379, which is the port of the container.

/tmp/redis.conf:/etc/redis/redis.conf / TMP / redis Conf is the directory of the host, and this directory needs to be configured in docker, otherwise an error will be reported (remember to add administrator permission when executing):

docker ERROR: * start service *: Mounts denied

image-20211128220527229

mysql 8.0 may report an error Java sql. Sqllontransientconnectionexception: public key retrieval is not allowed because the url link is missing a parameter: allowPublicKeyRetrieval=true

Start possible pit points

After startup, mysql or redis may not be linked, but the container operation is normal:

DockerCompose % docker container ps
CONTAINER ID   IMAGE                COMMAND                  CREATED          STATUS         PORTS                                                  NAMES
32fd6ce598ba   aphysia/dockerdemo   "java -jar /app.jar"     7 minutes ago    Up 7 minutes   0.0.0.0:8081->8081/tcp, :::8081->8081/tcp              dockerdemo
585b9b6bd71d   redis:latest         "docker-entrypoint.s..."   10 minutes ago   Up 7 minutes   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp              dockercompose_redis_1
d96ba57941d9   mysql:latest         "docker-entrypoint.s..."   16 minutes ago   Up 7 minutes   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   dockercompose_mysql_1

No error is reported when docker compose up is executed. An error is reported when requesting:

 io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: /127.0.0.1: 6379

This is because requests between containers cannot use 127.0.0.1, but must use MySQL and redis to represent the network of containers, such as JDBC: mysql://mysql:3306/test?characterEncoding=utf -8&useSSL=false&allowPublicKeyRetrieval=true

Complete application yml:

server:
  port: 8081
spring:
  #Database connection configuration
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://mysql:3306/test?characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
    username: root
    password: 123456
  redis:
    host: redis     ## Server IP of redis
    port: 6379
    ##I don't have a password here, so I don't fill it in
    password:
    ## Set the maximum number of connections. 0 is infinite
    pool:
      max-active: 8
      min-idle: 0
      max-idle: 8
      max-wait: -1
#Related configurations of mybatis
mybatis:
  #mapper profile
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.aphysia.springdocker.model
  #Hump naming
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    root: debug

Another problem is docker compose The image name configured in YML must be correct, or it will appear when docker compose up is executed:

Pulling xxxx...
ERROR: The image for the service you're trying to recreate has been removed. If you continue, volume data could be lost. Consider backing up your data before continuing.

Continue with the new image? [yN]y
Pulling xxxx...
ERROR: pull access denied for postgresql, repository does not exist or may require 'docker login': denied: requested access to the resource is denied

I thought it was the reason for logging in. It was originally a local image. You should directly create instead of pull. If you don't know the name, you can check it through the following command. REPOSITORY is the name:

DockerCompose % docker images
REPOSITORY           TAG            IMAGE ID       CREATED             SIZE
aphysia/dockerdemo   latest         1429aa26790a   54 minutes ago      137MB
<none>               <none>         ceb493583d7c   57 minutes ago      137MB
<none>               <none>         dffcc47602a2   About an hour ago   137MB
<none>               <none>         a695cf2cd2df   About an hour ago   137MB
<none>               <none>         209ce4f96d34   2 hours ago         137MB
redis                latest         40c68ed3a4d2   10 days ago         113MB
mysql                latest         e1d7dc9731da   14 months ago       544MB
openjdk              8-jdk-alpine   a3562aa0b991   2 years ago         105MB

Last start command:

sudo docker-compose up

Successfully started:

image-20211128221753624

Remember to initialize the database data table after startup!!!

drop database IF EXISTS test;
CREATE DATABASE test;
use test;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT "",
  `age` int(11) DEFAULT 0,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `user` VALUES (1, 'Li Si', 11);
INSERT INTO `user` VALUES (2, 'Wang Wu', 11);

image-20211128223429280

So far, it has been completed. There are still many pits in the seemingly simple command.