Docker(七)Docker-Compose部署SpringBoot+Redis+MySQL+Nginx

網際網路叫獸發表於2020-11-04

1、概述

Docker Compose是一個用來定義和執行復雜應用的Docker工具。一個使用Docker容器的應用,通常由多個容器組成。使用Docker Compose不再需要使用shell指令碼來啟動容器。
Compose 通過一個配置檔案來管理多個Docker容器,在配置檔案中,所有的容器通過services來定義,然後使用docker-compose指令碼來啟動,停止和重啟應用,和應用中的服務以及所有依賴服務的容器,非常適合組合使用多個容器進行開發的場景

2、Docker Compose安裝

下載docker compose的當前穩定版本

sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

如果github訪問太慢,可以用daocloud下載

sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.24.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

對二進位制檔案應用可執行許可權

sudo chmod +x /usr/local/bin/docker-compose

建立連結

ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

檢視版本

docker-compose --version

3、專案搭建

springboot 整合 mysql、redis服務

在這裡插入圖片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.yi</groupId>
    <artifactId>springboot-docker</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-docker</name>
    <packaging>jar</packaging>
    <description></description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <commons-pool2.version>2.6.1</commons-pool2.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>${commons-pool2.version}</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
package com.yi.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @method redis配置: RedisConfig檔名不能修改 ; 配置序列化方式以及快取管理器 @EnableCaching 開啟快取
 * @author Mr yi
 */
@Configuration
@EnableCaching
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        template.setValueSerializer(jackson2JsonRedisSerializer());
        // 使用StringRedisSerializer來序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(jackson2JsonRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    public RedisSerializer<Object> jackson2JsonRedisSerializer() {
        // 使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值
        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);
        return serializer;
    }

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 生成一個預設配置,通過config物件即可對快取進行自定義配置
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        // 設定快取的預設過期時間,也是使用Duration設定 (此處為快取1分鐘)
        config = config.entryTtl(Duration.ofMinutes(1))
                // 設定 key為string序列化
                .serializeKeysWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                // 設定value為json序列化
                .serializeValuesWith(
                        RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer()))
                // 不快取空值
                .disableCachingNullValues();

        // 設定一個初始化的快取空間set集合
        Set<String> cacheNames = new HashSet<>();
        cacheNames.add("timeGroup");
        cacheNames.add("user");
        cacheNames.add("UUser");

        // 對每個快取空間應用不同的配置
        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
        configMap.put("timeGroup", config);
        // 該快取空間,快取時間120秒
        configMap.put("user", config.entryTtl(Duration.ofSeconds(120)));
        configMap.put("UUser", config.entryTtl(Duration.ofDays(3)));

        // 使用自定義的快取配置初始化一個cacheManager
        RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
                // 一定要先呼叫該方法設定初始化的快取名,再初始化相關的配置
                .initialCacheNames(cacheNames).withInitialCacheConfigurations(configMap).build();
        return cacheManager;
    }

}

server:
  port: 8080
  #servlet:
    #context-path: /springboot-docker

spring:
  application:
    name: springboot-docker
  datasource:
      host: 127.0.0.1
      #url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2B8
      url: jdbc:mysql://${spring.datasource.host}:3306/test?serverTimezone=GMT%2B8
      username: root
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver
      max-idle: 10
      max-wait: 1000
      min-idle: 5
      initial-size: 5
  #單個redis配置
  redis:
    #Redis伺服器地址
    host: 127.0.0.1
    #Redis伺服器連線埠
    port: 6379
    #Redis伺服器連線密碼(預設為空)
    password: 123456
    # Redis資料庫索引(預設為0)
    database: 0
    lettuce:
      pool:
        # 連線池最大連線數(使用負值表示沒有限制) 預設 8
        max-active: 32
        # 連線池最大阻塞等待時間(使用負值表示沒有限制) 預設 -1
        max-wait: -1
        # 連線池中的最大空閒連線 預設 8
        max-idle: 8
        # 連線池中的最小空閒連線 預設 0
        min-idle: 0
        # 連線超時時間(毫秒)
        timeout: 0

host 配置為 127.0.0.1 本地即可, docker-compose 服務編排時會主動處理

package com.yi;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

@SpringBootApplication
@RestController
public class SpringbootApplication {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }

    @RequestMapping("/hello")
    public String hello() {
        return "hello world!";
    }

    @RequestMapping("/getReids")
    public String getReids() {
        String sql = "select * from user";
        List<Map<String, Object>> list =  jdbcTemplate.queryForList(sql);
        redisTemplate.opsForValue().set("data1", list);
        Object uu = redisTemplate.opsForValue().get("data1");

        return uu.toString();
    }

    @RequestMapping("/saveReids")
    public String saveReids(@RequestParam(value = "name", defaultValue = "yi") String name) {
        String sql = "insert into user (name) values(?)";
        jdbcTemplate.update(sql, new Object[]{name});
        return name.toString();
    }

    @RequestMapping("/deleteReids")
    public String deleteReids() {
        redisTemplate.delete("data1");
        return "delete success!";
    }


}


本地測試

啟動redis

redis-server redis.windows.conf

輸入地址訪問,檢查服務是否正常

http://127.0.0.1:8080/hello
http://127.0.0.1:8080/getReids

在這裡插入圖片描述

4、docker配置檔案

建立docker-bulid 目錄,目錄結構如圖所示

在這裡插入圖片描述

4.1、Dockerfile

構建springboot-docker映象。它包含安裝服務執行所需的環境、程式程式碼等

# Docker image for springboot file run
# VERSION 0.0.1
# Author: yi
# 基礎映象使用java
FROM java:8
# 作者
MAINTAINER yi <yi@gmail.com>
# VOLUME 指定了臨時檔案目錄為/tmp。
# 其效果是在主機 /var/lib/docker 目錄下建立了一個臨時檔案,並連結到容器的/tmp
VOLUME /tmp
# 將jar包新增到容器中並更名為app.jar
ADD springboot-docker-0.0.1-SNAPSHOT.jar app.jar
# 執行jar包
#RUN bash -c 'touch /app.jar'
#執行專案 app.jar。為了縮短 Tomcat 啟動時間,新增一個系統屬性指向 “/dev/./urandom” 作為 Entropy Source
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

4.2、docker-compose

version: "3"

services:

  service_redis:
    image: redis:4.0.14
    container_name: container_redis
    environment:
      - TZ=Asia/Shanghai
    volumes:
      - ./config/redis/redis.conf:/usr/local/etc/redis/redis.conf
      - ./data/redis/:/data/
      - ./log/redis/:/var/log/redis/
    command: redis-server /usr/local/etc/redis/redis.conf
    ports:
      - "6379:6379"
    restart: always
   # networks:
    #  - appnet

  service_mysql:
    image: mysql:5.7
    container_name: container_mysql
    environment:
      TZ: Asia/Shanghai
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_ROOT_HOST: '%'
    volumes:
      - ./config/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./data/mysql/:/var/lib/mysql/
      - ./data/init/:/docker-entrypoint-initdb.d/
      - ./log/mysql/:/var/log/mysql/
    command: [
      '--character-set-server=utf8mb4',
      '--collation-server=utf8mb4_unicode_ci'
    ]
    ports:
      - "3306:3306"
    restart: always
    #networks:
    #  - appnet

  service_web:
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      TZ: Asia/Shanghai
      spring.datasource.host: service_mysql
      spring.redis.host: service_redis
    expose:
      - "8080"
    depends_on:
      - service_redis
      - service_mysql
    restart: always
    #networks:
     # - appnet

  service_nginx:
    container_name: container_nginx
    image: nginx:1.8
    environment:
      - TZ=Asia/Shanghai
    ports:
      - "8000:8000"
    volumes:
      - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./data/nginx/:/usr/share/nginx/html/
      - ./log/nginx/:/var/log/nginx/
    depends_on:
      - service_web
    restart: always

#networks:
  #appnet:
    #driver: bridge

docker-compose 中包含4項服務,其中service_redis、service_mysql、service_nginx 是需要下載的映象(如果本地沒有),service_web 是需要構建的映象,使用Dockerfile進行映象構建。

version: ‘3’ : 構建檔案的語法版本資訊。表示使用第三代語法

4.3、Redis 服務:

  • service_redis:服務名稱,可自定義。
  • image:指定映象來啟動容器,如果本地不存在,從docker hub下載。
  • container_name:容器名稱,可自定義。預設自動生成,生成規則格式:
    【docker-compose.yml 檔案的父目錄名稱 + _ + 服務名稱 + 從一開始的數字】。
  • environment:為啟動的容器新增環境變數。此處配置了容器的時區。
  • volumes:【 宿主機:容器】,對映本地目錄下的配置檔案到容器指定地址下。這裡對映了配置檔案,資料目錄以及日誌目錄。
  • command:容器啟動後執行的命令。此處命令為 使用配置檔案來啟動 Redis 容器。
  • ports:埠對映,宿主機埠:容器埠。
  • restart:always時,表示如果容器啟動失敗,會一直嘗試重連。
  • networks:加入指定網路

4.4、MySQL 服務:

  • service_redis:服務名稱,可自定義。
  • image:指定映象來啟動容器,如果本地不存在,從docker hub下載。
  • container_name:容器名稱,可自定義。預設自動生成,生成規則格式:
    【docker-compose.yml 檔案的父目錄名稱 + _ + 服務名稱 + 從一開始的數字】。
  • environment:為啟動的容器新增環境變數。這裡配置了容器的時區,以及資料庫 ROOT 密碼和許可權。
  • volumes:【 宿主機:容器】,對映本地目錄下的配置檔案到容器指定地址下。這裡對映了配置檔案,資料目錄,初始化 SQL 目錄以及日誌目錄。
  • command:容器啟動後執行的命令。此處命令為設定字元編碼。
  • ports:埠對映,宿主機埠:容器埠。
  • restart:always時,表示如果容器啟動失敗,會一直嘗試重連。
  • networks:加入指定網路

4.5、Nginx服務:

  • service_redis:服務名稱,可自定義。
  • image:指定映象來啟動容器,如果本地不存在,從docker hub下載。
  • container_name:容器名稱,可自定義。預設自動生成,生成規則格式:
    【docker-compose.yml 檔案的父目錄名稱 + _ + 服務名稱 + 從一開始的數字】。
  • environment:為啟動的容器新增環境變數。這裡配置了容器的時區。
  • volumes:【 宿主機:容器】,對映本地目錄下的配置檔案到容器指定地址下。這裡對映了配置檔案,資料目錄以及日誌目錄。
  • ports:埠對映,宿主機埠:容器埠。
  • depends_on :依賴與指定的服務。容器啟動時,會先啟動依賴服務,再啟動當前服務。
  • restart:always時,表示如果容器啟動失敗,會一直嘗試重連。
  • networks:加入指定網路

4.6、Springboot Web服務:

  • service_redis:服務名稱,可自定義。
  • build:指定 Dockerfile 檔案位置,構建映象,並使用這個映象來啟動容器。
  • environment:為啟動的容器新增環境變數。指定了 MySQL 的 host 為 service_mysql 服務,Redis 的 host 為 service_redis 服務。
  • ports:埠對映,宿主機埠:容器埠。
  • depends_on:always時,表示如果容器啟動失敗,會一直嘗試重連。
  • expose :暴露容器內埠,不對映到宿主機。因為 SpringBoot 服務會被 Nginx 做代理轉發,所以不用暴露並對映到外部。
  • networks:加入指定網路

4.7、bulid config目錄

my.cnf

#開啟 bin-log,並指定檔案目錄和檔名字首
log-bin=/var/log/mysql/binlog

需要配置了 bin-log 檔案目錄,則 volumes 中對映的 - ./log/mysql/:/var/log/mysql/目錄才會有資料

[client]

default-character-set=utf8mb4


[mysqld]

character-set-client-handshake = FALSE

character-set-server = utf8mb4

collation-server = utf8mb4_unicode_ci

# 資料庫唯一 ID,主從的標識號絕對不能重複。
server-id = 1

# 開啟 bin-log,並指定檔案目錄和檔名字首
log-bin=/var/log/mysql/binlog

# bin-log 日誌檔案格式,設定為 MIXED 可以防止主鍵重複。
binlog_format = mixed

[mysql]
default-character-set=utf8mb4

nginx.conf

    upstream webhost{
        server docker-compose_service_springboot_1:8080 weight=1;
        server docker-compose_service_springboot_2:8080 weight=2;
    }

① 訪問 Nginx 服務會轉發到 SpringBoot 服務。

② SpringBoot 容器名稱是自動生成的,生成規則為 【docker-compose.yaml 檔案的父目錄名稱 + _ + 服務名稱 + 從一開始的數字】。

③ SpringBoot 容器埠都是 8080。

④ 訪問比例為 1:2。

#user  nobody;
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    upstream webhost{
        server docker-compose_service_springboot_1:8080 weight=1;
        server docker-compose_service_springboot_2:8080 weight=2;
    }

    server {
        listen       8000;
        server_name  localhost;

        location / {
            proxy_pass   http://webhost;
        }

		location /index {
			root /usr/share/nginx/html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }

}

redis.conf

daemonize no:設定前臺啟動,在 Docker 中後臺啟動 Redis 容器會報錯
requirepass 123456,設定redis密碼
#bind 127.0.0.1:註釋,允許外網訪問

# Redis configuration file example.
protected-mode yes

port 6379

tcp-backlog 511

timeout 0

tcp-keepalive 300

daemonize no

supervised no

pidfile /var/run/redis_6379.pid

loglevel notice

logfile "/var/log/redis/redis.log"

databases 16

always-show-logo yes

save 900 1
save 300 10
save 60 10000

stop-writes-on-bgsave-error yes

rdbcompression yes

rdbchecksum yes

dbfilename dump.rdb

dir ./

slave-serve-stale-data yes

slave-read-only yes

repl-diskless-sync no

repl-diskless-sync-delay 5

repl-disable-tcp-nodelay no

slave-priority 100

# requirepass foobared
requirepass 123456

lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no

appendonly no

appendfilename "appendonly.aof"

appendfsync everysec

no-appendfsync-on-rewrite no

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

aof-load-truncated yes

aof-use-rdb-preamble no

lua-time-limit 5000

slowlog-log-slower-than 10000

slowlog-max-len 128

latency-monitor-threshold 0

notify-keyspace-events ""

hash-max-ziplist-entries 512
hash-max-ziplist-value 64

list-max-ziplist-size -2

list-compress-depth 0

set-max-intset-entries 512

zset-max-ziplist-entries 128
zset-max-ziplist-value 64

hll-sparse-max-bytes 3000

activerehashing yes

client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

hz 10

aof-rewrite-incremental-fsync yes

5、docker部署

前提條件,已安裝docker、Docker-Compose,具體參考其它章節

5.1、指定拷貝build目錄到遠端伺服器上

在這裡插入圖片描述

日誌目錄賦值許可權:

chmod -R 777 log/

5.2、啟動 Docker服務

systemctl start docker.service

5.3、啟動服務

docker-compose 命令可以自動完成包括構建映象,(重新)建立服務,啟動服務,並關聯服務相關容器的一系列操作。
docker-compose up:最基本的啟動命令
-d:後臺啟動
–scale:擴充套件服務節點,格式為 服務名=個數

docker-compose up -d --scale service_web=2

在這裡插入圖片描述

在這裡插入圖片描述

5.4、顯示所有容器

docker-compose ps 

在這裡插入圖片描述

5.5、檢視映象構建情況

docker-compose images

在這裡插入圖片描述

5.6、訪問介面測試服務是否正常

ip:8000/hello

http://192.168.73.131:8000/hello
http://192.168.73.131:8000/getReids

5.7、停止並刪除

docker-compose down

docker-compose ps
docker-compose images

在這裡插入圖片描述

相關文章