简单的docker学习 第9章 Docker Compose

第9章 Docker Compose

对于现代应用来说,大多都是通过很多的微服务互相协同组成的一个完整应用。例如,订单管理、用户管理、品类管理、缓存服务、数据库服务等,它们构成了一个电商平台的应用。而部署和管理大量的服务容器是一件非常繁琐的事情。而 Docker Compose 就是解决这类问题的。

9.1 简介

Docker Compose 是一个需要在 Docker 主机上进行安装的 Docker 容器编排外部工具。其并不是通过脚本或各种冗长的 Docker 命令来将应用组件组织起来,而是通过一个声明式的配置文件描述整个应用,然后通过一条命令完成应用部署。部署成功后,还可通过一系列简单命令实现对其完整生命周期的管理。

Docker Compose 的前身是 Fig(无花果)。

9.2 compose 文件

9.2.1 文件简介

Docker Compose 使用 YAML 文件来定义服务。官方推荐的默认文件名为 compose.yml ,但同时也支持 docker-compose.yml。由于一个 compose 文件中定义的为一个项目的所有服务,所以一般为在创建 compose文件之前先新建一个目录,目录名称一般为项目名称,然后再将项目所需的所有镜像、微服务的 Dockerfile 放入该目录,并在该目录中新建 compose 文件。compose 文件中包含 6 个顶级属性:version、services、networks、volumes、configs secrets,及很多的它们下面所包含的属性。下面简单介绍一下常用的属性。

9.2.2 version

version 是一个顶级属性,但已经过时,不再需要在 compose 文件中出现了。从以下官网说明中可以看出。

image-20240715090933480

image-20240715090944786

9.2.3 networks

networks 作为一个顶级属性,用于定义和创建应用中所使用到的所有网络。其下包含的第一级属性即为网络名称,这个网络名称可以随意命名。而在网络名称下还可包含很多的属性,常用属性如下:

services:
  app:
    networks:
      # 这里使用的并不是网络名称
      - app_bridge
networks:
  app_bridge:
  	# 这才是网络名称
    name: appBGnet
	driver: bridge
  • name

    networks 下的第一级属性—网络名称,并不是真正的网络名称,而仅仅是网络名称的一部分。在真正生成网络后,其真正的网络名称格式为:当前 compose 文件所在目录名_networks 下的第一级属性。但如果设置了name属性,则网络名称即为这里指定的名称,不会出现名称再合成情况。

  • driver

    用于指定网络驱动,缺省驱动为 Bridge。

  • attachable

    如果该属性设置为 true,则除了当前 compose 中定义的服务外,其它独立容器也可以连接到此网络,并能与该网络中的服务通信并且连接到该网络的其它独立容器通信。缺省状态为false。

9.2.4 volumes

volumes 作为一个顶级属性,用于定义和创建应用中所使用到的所有 volume。其下包含的第一级属性即为 volume 的卷标,这个卷标可以随意命名。这个卷标所代表的是当前 Docker主机中的目录,至于该目录的具体位置,是由系统自动分配的。在网络名称下还可包含很多的属性,但这些属性并不常用,所以这里不进行介绍了。

9.2.5 serivces

services 是一个顶级属性,用于定义一个应用中所包含的服务。Docker Compose 会将每个服务部署在各自的容器中。其下包含的第一级的属性即为服务名称,这个名称可以根据服务内容随意命名。而在服务名称下还可包含很多的属性,常用属性如下:

  • build

    用于指定一个 Dockerfile 的路径。而该 Dockerfile 则是用于创建当前服务镜像的。这个路径可以是以斜杠(/)开头的绝对路径,也可以是相对于当前 compose 文件的、以点(.)号开头的相对路径。如果 Dockerfile 文件名不是默认名称,则需要通过 build 下的 context 属性指定路径,dockerfile 属性指定文件名。

    build:
      context: ./
      dockerfile: myDockerfile
    
  • image

    用户指定当前服务所需要使用的镜像,这个镜像可以是本地镜像,也可以是远程镜像仓库中的镜像(会自动 pull)。如果设置了 build,此时再设置的 image 属性即为构建出的镜像的名称与 Tag。

  • container_name

    该属性用于设置容器名称,但并不是必须的。如果没有设置该属性,容器名称则会采用“合成方式”。而合成时需要用到 services 下的第一级属性。在 services 下存在一级属性,称为服务名称。该级属性是作为 services 下的第一级属性出现的。服务名称将来会作为容器名称的一部分出现。容器的名称格式为:当前 compose文件所在目录名_ 服务名称。如果在 services 下没有指定 image 属性,而是使用 bild 属性,即没有现成的镜像,而是根据 build 下指定Dockerfile 生成镜像,此时生成的镜像名称格式为:当前 compose 文件所在目录名-服务名称

  • ports

    一个列表。前面为暴露出的端口号,后面为容器中应用的端口号。如果仅设置了一个端口号,那么这个端口号是容器中应用的端口号,其暴露到宿主机的端口号会被随机分配

    ports:
      # 绑定容器的 80 端口到主机的 80 端口
      - 80:80
      # 绑定容器的 80 端口到主机的 9000 端口
      - 9000:80
      # 绑定容器的 443 端口到主机的任意端口,容器启动时随机分配绑定的主机端口号
      - 443
    
  • command

    用于覆盖 Dockerfile 中的 CMD 指令内容,即启动该服务容器后立即运行的命令。如果直接按照Dockerfile中的CMD指令内容执行即可,则compose文件中无需该command属性。

  • depends_on

    一个列表。用于指定当前服务的启动所依赖的应用名称。即列表中指定的服务会先于当前服务启动

  • deploy

    用于指定当前服务容器的部署设置。其下有一个常用属性 replicas,用于指定该服务启动的容器的数量。即实现一个服务多个容器。一旦指定了 deploy:replicas,就不能再指定container_name 属性了。因为各个启动的容器名称不能相同,而只能由系统自动生成。

    services:
      frontend:
        image: awesome/webapp
        deploy:
          mode: replicated
          replicas: 6
    
  • networks

    用于指定当前服务容器要连接到的网络。该网络必须是已经存在的,或通过顶级属性networks 创建的网络。

  • volumes

    用于指定当前服务容器所使用到的所有 volume。这些 volume 可以使用路径与卷标两种方式。例如,下面是路径方式,非常直观,易于查看,但需要管理本地路径

    db:
      image: mariadb:latest
      ports:
        - "3306:3306"
      volumes:
        - /etc/mysql:/var/lib/mysql
    

    再如,下面是卷标方式,backend 与 backup 两个服务共享了 db-data 的卷,逻辑简洁明了,且无需管理本地路径。但具体卷标所代表的是 Docker 主机的哪个路径,并不能直观的看到。需要通过 docker volume inspect [卷标]来查看。

    services:
      backend:
        image: awesome/database
        volumes:
          - db-data:/etc/data
      backup:
        image: backup-service
        volumes:
          - db-data:/var/lib/backup/data
    volumes:
      db-data:
    

9.3 常用命令

Docker Compose通过docker-compose系列命令查看和控制compose中的所有服务容器。

  • docker-compose pull

    拉取 compose 中服务依赖的全部镜像或指定镜像。通过在命令后添加服务名称来指定。

  • docker-compose config

    检查 compose 文件是否正确。可添加选项-q,表示只有存在问题时才有输出。

  • docker-compose up

    启动 compose 中的所有容器。-d 选项表示后台启动。

  • docker-compose logs

    查看 comopse 中所有服务或指定服务的运行日志。通过在命令后添加服务名称来指定。默认情况下,将对不同的服务日志使用不同的颜色来区分。

  • docker-compose ps

    列出 compose 中所有服务或指定服务。通过在命令后添加服务名称来指定。

  • docker-compose top

    列出 compose 中当前正在运行的所有服务或指定服务。通过在命令后添加服务名称来指定。

  • docker-compose images

    列出 compose 中所有服务或指定服务对应的镜像。通过在命令后添加服务名称来指定。

  • docker-compose port

    列出指定服务容器的指定端口所映射的宿主机端口

  • docker-compose run

    在指定服务上执行一条命令

  • docker-compose exec

    进入指定服务容器。通过在命令后添加服务名称来指定。

  • docker-compose pause

    暂停 compose 中所有服务容器或指定服务容器。通过在命令后添加服务名称来指定

  • docker-compose unpause

    恢复 compose 中处于暂停状态的所有服务容器或指定服务容器。通过在命令后添加服务名称来指定。

  • docker-compose stop

    停止 compose 中所有服务容器或指定服务容器。通过在命令后添加服务名称来指定。

  • docker-compose restart

    重启 compose 中所有服务容器或指定服务容器。通过在命令后添加服务名称来指定。

  • docker-compose start

    启动 compose 中所有服务容器或指定服务容器。通过在命令后添加服务名称来指定

  • docker-compose kill

    通过发送 SIGKILL 信号停止指定服务的容器。

  • docker-compose rm

    删除 compose 中的、处于停止状态的所有服务容器或指定服务容器。通过在命令后添加服务名称来指定

  • docker-compose down

    停止并删除 compose 中的所有服务容器、网络、镜像、数据卷。

9.4 安装

9.4.1 下载安装包

访问官网地址 https://docs.docker.com/compose/install/standalone/ ,下载文件到 /usr/local/bin/目录下并且更名为 docker-compse

image-20240715102617177

curl -SL https://github.com/docker/compose/releases/download/v2.28.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose

image-20240715103118800

9.4.2 添加可执行权限

为 docker-compose 文件添加可执行权限。

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

image-20240715103312687

9.4.3 测试
docker-compose version

image-20240715103349740

9.5 项目构建

9.5.1 项目代码
  • 功能描述

    这是一个金融产品交易平台中的部分功能,是一个 Spring Boot 工程。控制器具有三个接口:查询所有产品、根据产品名称查询、上线新产品。整个架构包含一个 Redis 与 MySQL服务器

  • pom依赖

    <?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">
        <parent>
            <artifactId>spring-batch</artifactId>
            <groupId>cn.git</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>docker-demo</artifactId>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
    
        <dependencies>
            <!--spring boot 与 redis 整合依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
            <!--mybatis 与 spring boot 整合依赖-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
            <!--mysql 驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>
            <!-- druid 驱动 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.12</version>
            </dependency>
            <!--tomcat 内置的 JSP 解析器-->
            <dependency>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-jasper</artifactId>
            </dependency>
            <!--jstl 依赖-->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <version>1.2</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <!-- compiler -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                        <annotationProcessorPaths>
                            <path>
                                <groupId>org.mapstruct</groupId>
                                <artifactId>mapstruct-processor</artifactId>
                                <version>${mapstruct.version}</version>
                            </path>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                                <version>${lombok.version}</version>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>
                <!-- package -->
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    
  • 实体类

    package cn.git.docker.entity;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    /**
     * @description: 产品
     * @program: bank-credit-sy
     * @author: lixuchun
     * @create: 2024-07-15
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Product {
    
        /**
         * 主键
         */
        private Integer id;
    
        /**
         * 名称
         */
        private String name;
    
        /**
         * 利率
         */
        private Double rate;
    
        /**
         * 总额度
         */
        private Double amount;
    
        /**
         * 募集金额
         */
        private Double raised;
    
        /**
         * 周期
         */
        private Integer cycle;
    
        /**
         * 结束时间
         */
        private String endTime;
    
    }
    
    
  • sql 文件

    以下是生成 product 表及相应数据的 SQL 文件内容。

    CREATE DATABASE IF NOT EXISTS `test`;
    USE `test`;
    DROP TABLE IF EXISTS `product`;
    CREATE TABLE `product` (
     `id` int(11) NOT NULL AUTO_INCREMENT,
     `name` varchar(20) DEFAULT NULL,
     `rate` double DEFAULT NULL,
     `amount` double DEFAULT NULL,
     `raised` double DEFAULT NULL,
     `cycle` int(11) DEFAULT NULL,
     `end_Time` char(10) DEFAULT '0',
     PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
    
    INSERT INTO `product` VALUES(1,'TXTY',2.76,50000,20000,30,'2022-07-10'),
    (2,'GTTY',2.86,30000,30000,60,'2022-07-12'),
    (3,'GTGX',2.55,60000,50000,90,'2022-07-09'),
    (4,'GFMA',2.96,30000,20000,7,'2022-05-10'),
    (5,'TYXD',2.65,80000,60000,20,'2022-07-05'),
    (6,'HNSY',3.05,30000,20000,10,'2022-06-10'),
    (7,'HNSX',2.76,50000,30000,30,'2022-07-02'),
    (8,'LXSY',2.86,30000,20000,20,'2022-07-11');
    
    
  • productMapper.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="cn.git.docker.mapper.ProductMapper">
    
        <insert id="insertProduct">
            insert into product (name, raised, rate, cycle, amount, end_time)
            values (#{name}, #{raised}, #{rate}, #{cycle}, #{amount}, #{endTime})
        </insert>
    
        <select id="selectAllProducts" resultType="cn.git.docker.entity.Product">
            select * from product
        </select>
    
        <select id="selectProductListByName" resultType="cn.git.docker.entity.Product">
            select * from product where name like '%' #{name} '%'
        </select>
    </mapper>
    
  • RedisUtil工具类

    package cn.git.docker.util;
    
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    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.StringRedisSerializer;
    import org.springframework.stereotype.Component;
    
    @Component
    public class RedisUtil {
    
        private static RedisTemplate<String, Object> redisTemplate;
    
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
            // 创建RedisTemplate<String, Object>对象
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            // 配置连接工厂
            template.setConnectionFactory(factory);
            // 定义Jackson2JsonRedisSerializer序列化对象
            Jackson2JsonRedisSerializer<Object> jacksonSeial = new Jackson2JsonRedisSerializer<>(Object.class);
            ObjectMapper om = new ObjectMapper();
            // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会报异常
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jacksonSeial.setObjectMapper(om);
            StringRedisSerializer stringSerial = new StringRedisSerializer();
            // redis key 序列化方式使用stringSerial
            template.setKeySerializer(stringSerial);
            // redis value 序列化方式使用jackson
            template.setValueSerializer(jacksonSeial);
            // redis hash key 序列化方式使用stringSerial
            template.setHashKeySerializer(stringSerial);
            // redis hash value 序列化方式使用jackson
            template.setHashValueSerializer(jacksonSeial);
            template.afterPropertiesSet();
            return template;
        }
    
        @Autowired
        public void RedisService(RedisTemplate<String, Object> redisTemplate) {
            this.redisTemplate = redisTemplate;
        }
    
        public void set(String key, Object value) {
            redisTemplate.opsForValue().set(key, value);
        }
    
        public Object get(String key) {
            return redisTemplate.opsForValue().get(key);
        }
    }
    
    
  • Controller

    package cn.git.docker.controller;
    
    import cn.git.docker.entity.Product;
    import cn.git.docker.service.ProductService;
    import cn.git.docker.util.RedisUtil;
    import com.alibaba.fastjson.JSONObject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.List;
    
    /**
     * @description: 产品controller
     * @program: bank-credit-sy
     * @author: lixuchun
     * @create: 2024-07-15
     */
    @RestController
    @RequestMapping("/product")
    public class ProductController {
    
        @Autowired
        private RedisUtil redisUtil;
    
        @Autowired
        private ProductService productService;
    
        @GetMapping("/save")
        public String saveProduct() {
            Product product = new Product();
            product.setAmount(1000.0);
            product.setCycle(3);
            product.setEndTime("2024-07-15");
            product.setName("test");
            product.setRaised(103.0);
            product.setRate(0.03);
            productService.saveProduct(product);
    
            redisUtil.set(product.getName(), JSONObject.toJSONString(product));
            return JSONObject.toJSONString(product);
        }
    
        @GetMapping("/all")
        public String findAllProductList() {
            List<Product> allProductList = productService.findAllProductList();
            return JSONObject.toJSONString(allProductList);
        }
    
        @GetMapping("/all/{name}")
        public String findProductByName(@PathVariable String name) {
            List<Product> productList = productService.findProductByName(name);
            return JSONObject.toJSONString(productList);
        }
    }
    
    
  • yaml配置文件

    spring:
      application:
        name: docker-demo
      # 数据源配置
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://192.168.138.129:3306/test?useUnicode=true&characterEncoding=utf-8
        username: root
        password: 101022
    
      # redis配置
      redis:
        host: 192.168.138.129
        port: 6379
        database: 0
      # 缓存配置
      cache:
        type: redis
        cache-names: pc
    
    # 日志配置
    logging:
      file:
        name: "/var/applogs/finance.log"
      pattern:
        file: level-%-5level - %msg%n
        console: level-%-5level - %msg%n
      level:
        root: info
        cn.git.docker: debug
    
    # mybatis配置
    mybatis:
      mapper-locations: classpath:/mappers/*Mapper.xml
      # 设置实体类的包路径,用于别名自动扫描
      type-aliases-package: cn.git.docker.entity
      configuration:
        jdbc-type-for-null: 'null'
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
        map-underscore-to-camel-case: false
    server:
      port: 8088
    
9.5.2 定义 Dockerfile

在 Docker 主机的任意目录中新建一个目录,该新建目录名称与项目名称相同。这里在 /root 目录中 mkdir 一个名称为 finance(金融)的目录。然后在该目录中新建 Dockerfile 文件。

# 指定当前镜像继承自 openjdk:8u102,因为下面要运行 Jar 包,需要 JDK 环境
FROM openjdk:8u102
# 作者与项目相关说明
MAINTAINER zhangsan zs@163.com
LABEL version="1.0" description="docker compose test application"
# 将当前目录下的 jar 包 copy 到容器中。
# 注意,这个当前目录指的是 docker build 命令最后一个参数指定的上下文路径
COPY docker-demo-1.0-SNAPSHOT.jar docker-demo.jar
# 一定要执行的 exec
ENTRYPOINT ["java", "-jar", "docker-demo.jar"]
# 原服务指定对外暴露的端口号
EXPOSE 8088

注意,可以在 Dockerfile 中通过 VOLUME 指定数据卷

9.5.3 项目打包上传

image-20240715144049270

image-20240715144104414

9.6 手工启动项目

为了与使用 Docker Compose 编排项目进行对比,体现 Docker Compose 的方便快捷,这里先使用纯手工方式启动项目。

9.6.1 启动 mysql 容器
docker run --name mysql -e MYSQL_ROOT_PASSWORD=101022 -v /root/mysql/data:/var/lib/mysql -v /root/mysql/log:/var/log/mysql -v /root/mysql/conf:/etc/mysql/conf.d -dp 3306:3306 mysql:5.7

执行准备好的sql文件

9.6.2 启动redis容器

注意,这里可以直接执行下面的启动 redis 容器的命令的前提是,借用了之前在“常用服务器安装”章节中安装单机版 Redis 中创建的外挂文件/root/redis/redis.conf。

docker run --name myredis \
--network host \
-v /root/redis/redis.conf:/etc/redis/redis.conf \
-v /root/redis/data:/data \
-dp 6379:6379 redis:latest redis-server /etc/redis/redis.conf
9.6.3 启动应用容器
  • 检查应用配置文件

    在构建应用镜像之前,打开项目的配置文件,再次确认配置文件中指定的 mysql 与 redis主机的 IP 地址是否为 Docker 主机的 IP。注意,不是相应的 Docker 容器的 IP。如果不是,在修改后需要重新对项目进行 package 打包。然后再次将打包后的 jar 包上传到 Linux 系统的finance 项目目录中。

    image-20240715144647387

  • 构建应用镜像

    docker build -t finance:1.0 .
    

    image-20240715145005796

  • 启动容器

    日志持久化,配置文件中配置目录映射到服务器目录

    docker run --name myapp \
    -v /root/myapp/log:/var/applogs \
    -dp 9000:8088 finance:1.0
    

    image-20240715145335313

9.6.4 访问应用

访问地址分别新增查询数据

http://192.168.138.129:9000/product/save
http://192.168.138.129:9000/product/all
http://192.168.138.129:9000/product/all/test

image-20240715145444374

image-20240715145512134

image-20240715145558293

查看redis中数据信息

image-20240715145714295

查看服务日志信息如下:

docker logs -f --tail=50 myapp

image-20240715145822056

9.7 Compose 编排启动项目

手工启动项目不仅繁琐易错,而且还存在一个致命问题:当前应用访问的 mysql 与 redis只能是运行在当前 Docker 宿主机之上的,否则将无法访问到它们。因为在应用的配置文件中已经将 mysql 与 redis 的 IP 进行了硬编码。而使用 Docker Compose 可以解决所有问题

9.7.1 定义 compose.yml

在 finance 目录中新建一个文件 compose.yml。

services:
  app:
    build: ./
    # 当你运行docker-compose up或docker-compose build时,Docker Compose将使用Dockerfile构建镜像,并将其标记为myapp:v1.0
    # image字段在build字段存在的情况下,用于指定构建完成后镜像的名称和tag,而不是用来直接使用现有镜像。build字段不存在,image字段用于指定使用的镜像。
    image: myapp:v1.0
    container_name: myapp
    ports:
      - 9000:8088
    volumes:
      - ./logs:/var/applogs
    depends_on:
      - mysql
      - redis
  mysql:
    image: mysql:5.7
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: 101022
    ports:
      - 3306:3306
    volumes:
      - /root/mysql/log:/var/log/mysql
      - /root/mysql/data:/var/log/mysql
      - /root/mysql/conf:/etc/mysql/conf.d
  redis:
    image: redis:latest
    container_name: redis
    # 主机模式,和宿主机使用相同网络
	network_mode: host
    ports:
      - 6379:6379
    vloumes:
      - /root/redis/redis.conf:/etc/redis/redis.conf
      - /root/redis/data:/data
    command: redis-server /etc/redis/redis.conf

编写完成之后使用命令检查compose文件是否编辑正确,没有返回错误信息则编辑正确

docker-compose config -q

image-20240716090313568

9.7.2 修改应用
  • 修改配置文件

    对于应用程序,需要修改其配置文件 application.yml。将 mysql 与 redis 的主机名修改为它们相应服务的名称,修改后重新上传文件

    image-20240715151853354

9.7.3 启动所有容器
docker-compose up -d

image-20240715160759048

写入数据库测试数据信息

image-20240715161043373

9.7.4 访问应用

与前面手工启动项目的访问方式相同。

http://192.168.138.129:9000/product/save
http://192.168.138.129:9000/product/all
http://192.168.138.129:9000/product/all/test

image-20240715161152571

image-20240715163718981

image-20240715163808988

查看执行日志信息

docker logs -f --tail=50 myapp

image-20240716084715047

9.7.6 指定各组件名称

前面的 compose.yml 文件中应用生成的镜像采用的是默认名称,mysql 与 redis 生成的容器名称采用的是默认名称,生成并加入的 bridge 网络也称默认名称的网络。这些组件的所使用的默认名称,也可以被指定名称所代替。

image-20240715164037006

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值