Compose 是 Docker 公司推出的一个工具软件,可以管理多个 Docker 容器组成一个应用。你需要定义一个 YAML 格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。然后,只要一个命令,就能同时启动/关闭这些容器。 负责实现对Dokcer容器集群的快速编排。
docker建议我们每一个容器中只运行一个服务,因为docker容器本身占用资源极少,所以最好是将每个服务单独的分割开来但是这样我们又面临了一个问题?
如果我需要同时部署好多个服务,难道要每个服务单独写Dockerfile然后在构建镜像,构建容器,这样累都累死了,所以docker官方给我们提供了docker-compose多服务部署的工具
例如要实现一个Web微服务项目,除了Web服务容器本身,往往还需要再加上后端的数据库mysql服务容器,redis服务器,注册中心eureka,甚至还包括负载均衡容器等等。。。。。。
Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。
可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose 解决了容器与容器之间如何管理编排的问题。
下载安装 Compose file version 3 reference | Docker Documentation 
Install Docker Compose | Docker Documentation 
1 2 3 4 5 6 7 8 9 10 sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s) -$(uname -m) "  -o /usr/local /bin/docker-compose sudo chmod +x /usr/local /bin/docker-compose docker-compose --version sudo rm /usr/local /bin/docker-compose 
常用命令 
命令 
解释 
 
 
docker-compose -h 
查看帮助 
 
docker-compose up 
启动所有docker-compose服务 
 
docker-compose up -d 
启动所有docker-compose服务并后台运行 
 
docker-compose down 
停止并删除容器、网络、卷、镜像。 
 
docker-compose exec  yml里面的服务id 
进入容器实例内部 docker-compose exec docker-compose.yml文件中写的服务id /bin/bash 
 
docker-compose ps 
展示当前docker-compose编排过的运行的所有容器 
 
docker-compose top 
展示当前docker-compose编排过的容器进程 
 
docker-compose logs  yml里面的服务id 
查看容器输出日志 
 
dokcer-compose config 
检查配置 
 
dokcer-compose config -q 
检查配置,有问题才有输出 
 
docker-compose restart 
重启服务 
 
docker-compose start 
启动服务 
 
docker-compose stop 
停止服务 
 
使用步骤 
编写Dockerfile定义各个微服务应用并构建出对应的镜像文件 
使用docker-compose.yml定义一个完整业务单元,安排好整体应用中的各个容器服务 
执行docker-compose up命令来启动并运行整个应用程序,完成一键部署上线。 
 
改造微服务项目 properties 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 server.port =6001 spring.datasource.type =com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name =com.mysql.jdbc.Driver spring.datasource.url =jdbc:mysql://ip:3306/db2021?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username =root spring.datasource.password =123456 spring.datasource.druid.test-while-idle =false spring.redis.database =0 spring.redis.host =ip spring.redis.port =6379 spring.redis.password =spring.redis.lettuce.pool.max-active =8 spring.redis.lettuce.pool.max-wait =-1ms spring.redis.lettuce.pool.max-idle =8 spring.redis.lettuce.pool.min-idle =0 mybatis.mapper-locations =classpath:mapper/*.xml mybatis.type-aliases-package =com.kylin.docker_boot.entity spring.swagger2.enabled =true 
pom.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 <properties >     <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding >      <maven.compiler.source > 1.8</maven.compiler.source >      <maven.compiler.target > 1.8</maven.compiler.target >      <junit.version > 4.12</junit.version >      <log4j.version > 1.2.17</log4j.version >      <lombok.version > 1.16.18</lombok.version >      <mysql.version > 5.1.47</mysql.version >      <druid.version > 1.1.16</druid.version >      <mapper.version > 4.1.5</mapper.version >      <mybatis.spring.boot.version > 1.3.0</mybatis.spring.boot.version >  </properties > <dependencies >          <dependency >          <groupId > com.google.guava</groupId >          <artifactId > guava</artifactId >          <version > 23.0</version >      </dependency >           <dependency >          <groupId > org.redisson</groupId >          <artifactId > redisson</artifactId >          <version > 3.13.4</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-actuator</artifactId >      </dependency >           <dependency >          <groupId > io.springfox</groupId >          <artifactId > springfox-swagger2</artifactId >          <version > 2.9.2</version >      </dependency >      <dependency >          <groupId > io.springfox</groupId >          <artifactId > springfox-swagger-ui</artifactId >          <version > 2.9.2</version >      </dependency >           <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-starter-data-redis</artifactId >      </dependency >           <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-starter-cache</artifactId >      </dependency >           <dependency >          <groupId > org.apache.commons</groupId >          <artifactId > commons-pool2</artifactId >      </dependency >           <dependency >          <groupId > redis.clients</groupId >          <artifactId > jedis</artifactId >          <version > 3.1.0</version >      </dependency >           <dependency >          <groupId > mysql</groupId >          <artifactId > mysql-connector-java</artifactId >          <version > 5.1.47</version >      </dependency >           <dependency >          <groupId > com.alibaba</groupId >          <artifactId > druid-spring-boot-starter</artifactId >          <version > 1.1.10</version >      </dependency >      <dependency >          <groupId > com.alibaba</groupId >          <artifactId > druid</artifactId >          <version > ${druid.version}</version >      </dependency >           <dependency >          <groupId > org.mybatis.spring.boot</groupId >          <artifactId > mybatis-spring-boot-starter</artifactId >          <version > ${mybatis.spring.boot.version}</version >      </dependency >           <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-starter-amqp</artifactId >      </dependency >      <dependency >          <groupId > commons-codec</groupId >          <artifactId > commons-codec</artifactId >          <version > 1.10</version >      </dependency >                <dependency >          <groupId > cn.hutool</groupId >          <artifactId > hutool-all</artifactId >          <version > 5.2.3</version >      </dependency >      <dependency >          <groupId > junit</groupId >          <artifactId > junit</artifactId >          <version > ${junit.version}</version >      </dependency >      <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-devtools</artifactId >          <scope > runtime</scope >          <optional > true</optional >      </dependency >      <dependency >          <groupId > org.springframework.boot</groupId >          <artifactId > spring-boot-starter-test</artifactId >          <scope > test</scope >      </dependency >      <dependency >          <groupId > log4j</groupId >          <artifactId > log4j</artifactId >          <version > ${log4j.version}</version >      </dependency >      <dependency >          <groupId > org.projectlombok</groupId >          <artifactId > lombok</artifactId >          <version > ${lombok.version}</version >          <optional > true</optional >      </dependency >           <dependency >          <groupId > javax.persistence</groupId >          <artifactId > persistence-api</artifactId >          <version > 1.0.2</version >      </dependency >           <dependency >          <groupId > tk.mybatis</groupId >          <artifactId > mapper</artifactId >          <version > ${mapper.version}</version >      </dependency >  </dependencies > 
config RedisConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @Configuration @Slf4j public  class  RedisConfig          @Bean      public  RedisTemplate<String, Serializable> redisTemplate (LettuceConnectionFactory lettuceConnectionFactory)       {        RedisTemplate<String,Serializable> redisTemplate = new  RedisTemplate<>();         redisTemplate.setConnectionFactory(lettuceConnectionFactory);                  redisTemplate.setKeySerializer(new  StringRedisSerializer());                  redisTemplate.setValueSerializer(new  GenericJackson2JsonRedisSerializer());         redisTemplate.setHashKeySerializer(new  StringRedisSerializer());         redisTemplate.setHashValueSerializer(new  GenericJackson2JsonRedisSerializer());         redisTemplate.afterPropertiesSet();         return  redisTemplate;     } } 
SwaggerConfig
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Configuration @EnableSwagger2 public  class  SwaggerConfig     @Value("${spring.swagger2.enabled}")      private  Boolean enabled;     @Bean      public  Docket createRestApi ()           return  new  Docket(DocumentationType.SWAGGER_2)                 .apiInfo(apiInfo())                 .enable(enabled)                 .select()                 .apis(RequestHandlerSelectors.basePackage("com.kylin.docker_boot" ))                  .paths(PathSelectors.any())                 .build();     }     public  ApiInfo apiInfo ()           return  new  ApiInfoBuilder()                 .title("尚硅谷Java大厂技术" +"\t" +new  SimpleDateFormat("yyyy-MM-dd" ).format(new  Date()))                 .description("docker-compose" )                 .version("1.0" )                 .termsOfServiceUrl("https://www.atguigu.com/" )                 .build();     } } 
entitiy User
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 @Table(name = "t_user") public  class  User     @Id      @GeneratedValue(generator = "JDBC")      private  Integer id;          private  String username;          private  String password;          private  Byte sex;          private  Byte deleted;          @Column(name = "update_time")      private  Date updateTime;          @Column(name = "create_time")      private  Date createTime;          public  Integer getId ()           return  id;     }          public  void  setId (Integer id)           this .id = id;     }          public  String getUsername ()           return  username;     }          public  void  setUsername (String username)           this .username = username;     }          public  String getPassword ()           return  password;     }          public  void  setPassword (String password)           this .password = password;     }          public  Byte getSex ()           return  sex;     }          public  void  setSex (Byte sex)           this .sex = sex;     }          public  Byte getDeleted ()           return  deleted;     }          public  void  setDeleted (Byte deleted)           this .deleted = deleted;     }          public  Date getUpdateTime ()           return  updateTime;     }          public  void  setUpdateTime (Date updateTime)           this .updateTime = updateTime;     }          public  Date getCreateTime ()           return  createTime;     }          public  void  setCreateTime (Date createTime)           this .createTime = createTime;     } } 
UserDTO
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 @NoArgsConstructor @AllArgsConstructor @Data @ApiModel(value = "用户信息") public  class  UserDTO  implements  Serializable     @ApiModelProperty(value = "用户ID")      private  Integer id;     @ApiModelProperty(value = "用户名")      private  String username;     @ApiModelProperty(value = "密码")      private  String password;     @ApiModelProperty(value = "性别 0=女 1=男 ")      private  Byte sex;     @ApiModelProperty(value = "删除标志,默认0不删除,1删除")      private  Byte deleted;     @ApiModelProperty(value = "更新时间")      private  Date updateTime;     @ApiModelProperty(value = "创建时间")      private  Date createTime;          public  Integer getId ()           return  id;     }          public  void  setId (Integer id)           this .id = id;     }          public  String getUsername ()           return  username;     }          public  void  setUsername (String username)           this .username = username;     }          public  String getPassword ()           return  password;     }          public  void  setPassword (String password)           this .password = password;     }          public  Byte getSex ()           return  sex;     }          public  void  setSex (Byte sex)           this .sex = sex;     }          public  Byte getDeleted ()           return  deleted;     }          public  void  setDeleted (Byte deleted)           this .deleted = deleted;     }          public  Date getUpdateTime ()           return  updateTime;     }          public  void  setUpdateTime (Date updateTime)           this .updateTime = updateTime;     }          public  Date getCreateTime ()           return  createTime;     }          public  void  setCreateTime (Date createTime)           this .createTime = createTime;     }     @Override      public  String toString ()           return  "User{"  +                 "id="  + id +                 ", username='"  + username + '\''  +                 ", password='"  + password + '\''  +                 ", sex="  + sex +                 '}' ;     } } 
mapper UserMapper
1 2 public  interface  UserMapper  extends  Mapper <User > } 
UserMapper.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?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 ="com.atguigu.docker.mapper.UserMapper" >   <resultMap  id ="BaseResultMap"  type ="com.atguigu.docker.entities.User" >           <id  column ="id"  jdbcType ="INTEGER"  property ="id"  />      <result  column ="username"  jdbcType ="VARCHAR"  property ="username"  />      <result  column ="password"  jdbcType ="VARCHAR"  property ="password"  />      <result  column ="sex"  jdbcType ="TINYINT"  property ="sex"  />      <result  column ="deleted"  jdbcType ="TINYINT"  property ="deleted"  />      <result  column ="update_time"  jdbcType ="TIMESTAMP"  property ="updateTime"  />      <result  column ="create_time"  jdbcType ="TIMESTAMP"  property ="createTime"  />    </resultMap >  </mapper > 
service 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 @Service @Slf4j public  class  UserService      public  static  final  String CACHE_KEY_USER = "user:" ;     @Resource      private  UserMapper userMapper;     @Resource      private  RedisTemplate redisTemplate;          public  void  addUser (User user)       {                 int  i = userMapper.insertSelective(user);         if (i > 0 )         {                          user = userMapper.selectByPrimaryKey(user.getId());                          String key = CACHE_KEY_USER+user.getId();             redisTemplate.opsForValue().set(key,user);         }     }          public  User findUserById (Integer id)       {        User user = null ;         String key = CACHE_KEY_USER+id;                  user = (User) redisTemplate.opsForValue().get(key);         if (user == null )         {                          user = userMapper.selectByPrimaryKey(id);             if (user == null )             {                                                   return  user;             }else {                                  redisTemplate.opsForValue().set(key,user);             }         }         return  user;     } } 
controller 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 @Api(description = "用户User接口") @RestController @Slf4j public  class  UserController     @Resource      private  UserService userService;     @ApiOperation("数据库新增3条记录")      @RequestMapping(value = "/user/add",method = RequestMethod.POST)      public  void  addUser ()       {        for  (int  i = 1 ; i <=3 ; i++) {             User user = new  User();             user.setUsername("zzyy" +i);             user.setPassword(IdUtil.simpleUUID().substring(0 ,6 ));             user.setSex((byte ) new  Random().nextInt(2 ));             userService.addUser(user);         }     }     @ApiOperation("删除1条记录")      @RequestMapping(value = "/user/delete/{id}",method = RequestMethod.POST)      public  void  deleteUser (@PathVariable  Integer id)       {        userService.deleteUser(id);     }     @ApiOperation("修改1条记录")      @RequestMapping(value = "/user/update",method = RequestMethod.POST)      public  void  updateUser (@RequestBody  UserDTO userDTO)       {        User user = new  User();         BeanUtils.copyProperties(userDTO,user);         userService.updateUser(user);     }     @ApiOperation("查询1条记录")      @RequestMapping(value = "/user/find/{id}",method = RequestMethod.GET)      public  User findUserById (@PathVariable  Integer id)       {        return  userService.findUserById2(id);     } } 
同样将其打成jar包,传输到服务器的/mydocker目录中
构建镜像 在/mydocker中运行docker build -t kylin_docker:1.6 .
不使用compose 创建MySQL容器 首先我们要在Docker中运行MySQL容器
1 docker run -p 3306:3306 --name mysql57 --privileged=true  -v /kylinuse/mysql/conf:/etc/mysql/conf.d -v /kylinuse/mysql/logs:/logs -v /kylinuse/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7 
接着使用docker exce -it mysql57 /bin/bash进入容器中
接着使用mysql -u root -p输入密码进入mysql
create database db2021;创建库
创建表
1 2 3 4 5 6 7 8 9 10 11 12 use db2021; CREATE  TABLE  `t_user` (  `id` INT (10 ) UNSIGNED NOT  NULL  AUTO_INCREMENT,   `username` VARCHAR (50 ) NOT  NULL  DEFAULT  ''  COMMENT '用户名' ,   `password` VARCHAR (50 ) NOT  NULL  DEFAULT  ''  COMMENT '密码' ,   `sex` TINYINT(4 ) NOT  NULL  DEFAULT  '0'  COMMENT '性别 0=女 1=男 ' ,   `deleted` TINYINT(4 ) UNSIGNED NOT  NULL  DEFAULT  '0'  COMMENT '删除标志,默认0不删除,1删除' ,   `update_time` TIMESTAMP  NOT  NULL  DEFAULT  CURRENT_TIMESTAMP  ON  UPDATE CURRENT_TIMESTAMP  COMMENT '更新时间' ,   `create_time` TIMESTAMP  NOT  NULL  DEFAULT  CURRENT_TIMESTAMP  COMMENT '创建时间' ,   PRIMARY  KEY (`id`) ) ENGINE= INNODB AUTO_INCREMENT= 1  DEFAULT  CHARSET= utf8mb4 COMMENT= '用户表' ; 
创建Redis容器 1 docker run  -p 6379:6379 --name redis608 --privileged=true  -v /app/redis/redis.conf:/etc/redis/redis.conf -v /app/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf 
使用docker exec -it redis608 /bin/bash进入容器
使用redis-cli连接redis服务
使用keys *查看数据
运行微服务镜像 docker run -d -p 6001:6001 kylin_docker:1.6
访问ip:6001/swagger-ui.html
接着我们可以看数据库,Redis是否插入成功
成功访问,但是还是存在一些问题
先后顺序要求固定,先mysql+redis才能微服务访问成功 
要运行多个run命令 
容器间的启停或宕机,有可能导致ip地址对应的容器实例变化,映射出错,要么生产IP写死(不推荐),要么通过服务调用。 
 
使用compose 编写docker-compose.yml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 version:  "3" services:   microService:    	     image:  kylin_docker:1.6           container_name:  ms01           ports:        -  "6001:6001"           volumes:        -  /app/microService:/data           networks:         -  kylin_net            depends_on:         -  redis        -  mysql       redis:      image:  redis:6.0.8      ports:        -  "6379:6379"      volumes:        -  /app/redis/redis.conf:/etc/redis/redis.conf        -  /app/redis/data:/data      networks:         -  kylin_net           command:  redis-server  /etc/redis/redis.conf       mysql:      image:  mysql:5.7           environment:        MYSQL_ROOT_PASSWORD:  '123456'        MYSQL_ALLOW_EMPTY_PASSWORD:  'no'        MYSQL_DATABASE:  'db2021'        MYSQL_USER:  'kylin'        MYSQL_PASSWORD:  'kylin123'      ports:         -  "3306:3306"      volumes:         -  /app/mysql/db:/var/lib/mysql         -  /app/mysql/conf/my.cnf:/etc/my.cnf         -  /app/mysql/init:/docker-entrypoint-initdb.d      networks:        -  kylin_net      command:  --default-authentication-plugin=mysql_native_password   networks:     kylin_net:   
docker-compose config -q检查是否有语法错误
修改项目的配置文件,采用服务名访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 server.port =6001 spring.datasource.type =com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name =com.mysql.jdbc.Driver spring.datasource.url =jdbc:mysql://mysql:3306/db2021?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.datasource.username =root spring.datasource.password =123456 spring.datasource.druid.test-while-idle =false spring.redis.database =0 spring.redis.host =redis spring.redis.port =6379 spring.redis.lettuce.pool.max-active =8 spring.redis.lettuce.pool.max-wait =-1ms spring.redis.lettuce.pool.max-idle =8 spring.redis.lettuce.pool.min-idle =0 mybatis.mapper-locations =classpath:mapper/*.xml mybatis.type-aliases-package =com.kylin.docker_boot.entity spring.swagger2.enabled =true 
接着上传到服务器/mydocker目录下,docker build -t kylin_docker:1.6 .构建镜像
使用docker-compose up -d可以看见启动了三个容器,同时可以看到mysql,redis我们没有给容器命名,采用的是所在目录_服务名_序列号的命名方式
mydocker_redis_1 
mydocker_mysql_1 
 
docker network ls
网桥命名则会加上所在目录_为前缀
接着同样进入msyql容器创建库,表。进入swagger发送请求,运行成功!