9.DockerCompose容器编排
通过网盘分享的文件:MD文档笔记
链接: https://pan.baidu.com/s/1ao2wfyLEdN50YmIqdzfGYQ?pwd=5w5z 提取码: 5w5z
–来自百度网盘超级会员v6的分享
一.Compose 简介
Docker Compose 是一个需要在 Docker 主机上安装的 Docker 容器编排外部工具
可以使用 YML 文件来配置应用程序需要的所有服务,然后通过一条命令就可以从 YML 配置文件中创建并启动所有服务,还可通过一系列简单命令实现对其完整生命周期的管理
Docker Compose 的前身是Fig(无花果)
二.Compose文件
1.文件简介
Docker Compose 使用 YAML 文件来定义服务
官方推荐的默认文件名为compose.yml,但同时也支持 docker-compose.yml
由于一个 compose 文件中定义的是一个项目中所有服务,所以一般在创建 compose文件之前先新建一个目录,目录名称一般为项目名称,然后再将项目所需的所有镜像、微服务的 Dockerfile 放入该目录,并在该目录中新建 compose 文件
compose 文件中包含 6 个顶级属性及很多的它们下面所包含的属性
- version
- services
- networks
- volumes
- configs
- secrets
2.顶级属性
2.1.version
version 是一个顶级属性,但已经过时,不再需要在 compose 文件中出现了
从以下官网说明中可以看出
https://docs.docker.com/reference/compose-file/

2.2.networks
networks 作为一个顶级属性,用于定义和创建应用中所使用到的所有网络
其下包含的第一级属性即为网络名称,这个网络名称可以随意命名
networks:
frontend: # 网络名称
driver: bridge # 驱动类型(bridge 是默认值)
driver_opts: # 驱动特定选项
com.docker.network.driver.mtu: "1450"
ipam: # IP 地址管理
driver: default
config:
- subnet: 172.28.0.0/16
gateway: 172.28.0.1
attachable: true # 允许外部容器连接此网络
backend:
driver: overlay # Swarm 模式使用 overlay 实现跨主机通信
internal: true # 内部网络,禁止访问外网
proxy_net:
external: true # 表示该网络已在 Docker 中创建
name: my_existing_network # 外部网络的实际名称
常用属性如下
-
driver_opts
传递给驱动的额外参数
-
ipam
自定义 IP 分配方案
-
internal
是否隔离外部网络访问
-
external
是否由外部创建(Compose 不创建)
-
name
networks 下的第一级属性(网络名称),并不是真正的网络名称,而仅仅是网络名称的一部分
在真正生成网络后,其真正的网络名称格式为:当前 compose 文件所在目录名_ networks 下的第一级属性
-
driver
用于指定网络驱动
-
bridge:单机网络(缺省驱动为 bridge)
-
host
-
none
-
-
attachable
如果该属性设置为 true,则除了当前 compose 中定义的服务外,其它独立容器也可以连接到此网络
缺省状态为 false
2.3.volumes
volumes 作为一个顶级属性,用于定义和创建应用中所使用到的所有 volume
其下包含的第一级属性即为volume 的卷标,这个卷标可以随意命名,这个卷标所代表的是当前 Docker主机中的目录,至于该目录的具体位置,是由系统自动分配的
常用的属性
driver |
存储驱动,默认为 local |
|---|---|
driver_opts |
特定于驱动的选项(如 bind mount、tmpfs) |
labels |
标签,便于管理 |
external |
是否外部创建 |
name |
实际卷名称(当 external=true 时必须匹配) |
【示例】
services:
backend:
image: awesome/database
volumes:
- db-data: /etc/data
backup:
image: backup-service
volumes:
- db-data:/var/lib/backup/data
volumes:
db-data:
2.4.serivces
services 是一个顶级属性,用于定义一个应用中所包含的服务
Docker Compose 会将每个服务部署在各自的容器中
其下包含的第一级的属性即为服务名称,这个名称可以根据服务内容随意命名,而在服务名称下还可包含很多的属性,常用属性如下
(1).build
用于指定一个 Dockerfile 的路径,该 Dockerfile 则是用于创建当前服务镜像的
-
路径
-
路径可以是以斜杠(/)开头的绝对路径
-
可以是相对于当前 compose 文件的、以点(.)号开头的相对路径
-
-
名称
如果 Dockerfile 文件名不是默认名称,则需要通过 build 下的 context 属性指定路径,dockerfile 属性指定文件名
build: context: ./ dockerfile: myDockerfile
(2).image
指定当前服务所需要使用的镜像,这个镜像可以是本地镜像,也可以是远程镜像仓库中的镜像(会自动 pull)
如果设置了 build,此时再设置的 image 属性即为构建出的镜像的名称与 Tag
(3).container_name
该属性用于设置容器名称,但并不是必须的
如果没有设置该属性,容器名称则会采用 “合成方式”,而合成时需要用到 services 下的第一级属性
-
在 services 下存在一级属性,称为服务名称,该级属性是作为 services 下的第一级属性出现的,服务名称将来会作为容器名称的一部分出现,容器的名称格式为:当前 compose文件所在目录名_ 服务名称
-
如果在 services 下没有指定 image 属性,而是使用 bild 属性,即没有现成的镜像,而是根据 build 下指定的 Dockerfile 生成镜像,此时生成的镜像名称格式为:当前 compose 文件所在目录名-服务名称
(4).ports
一个端口号列表:前面为暴露出的端口号,后面为容器中应用的端口号
如果仅设置了一个端口号,那么这个端口号是容器中应用的端口号,其暴露到宿主机的端口号会被随机分配
ports:
- 80: 80 # 绑定容器的 80 端口到主机的 80 端口
- 9000: 80 # 绑定容器的 80 端口到主机的 9000 端口
- 443 # 绑定容器的 443 端口到主机的任意端口,容器启动时随机分配绑定的主机端口号
(5).command
用于覆盖 Dockerfile 中的 CMD 指令内容,即启动该服务容器后立即运行的命令
如果直接按照Dockerfile 中的CMD 指令内容执行即可,则compose 文件中无需该command 属性
(6).depends_on
一个列表
用于指定当前服务的启动所依赖的应用名称
即列表中指定的服务会先于当前服务启动
(7).deploy
用于指定当前服务容器的部署设置
其下有一个常用属性 replicas,用于指定该服务启动的容器的数量(即实现一个服务多个容器)
一旦指定了 deploy:replicas,就不能再指定 container_name 属性了,因为各个启动的容器名称不能相同,而只能由系统自动生成
services:
frontend:
image: awesome/webapp
deploy:
mode: replicated
replicas: 6
(8).networks
用于指定当前服务容器要连接到的网络
该网络必须是已经存在的,或通过顶级属性networks 创建的网络
(9).volumes
用于指定当前服务容器所使用到的所有 volume
这些 volume 可以使用路径与卷标两种方式
【示例1】下面是路径方式,非常直观,易于查看,但需要管理本地路径
db:
image: mariadb:latest
ports:
- "3306:3306"
volumes:
- /etc/mysql:/var/lib/mysql
【示例2】
下面是卷标方式,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:
2.5.secrets
安全地传递敏感信息(密码、密钥等)到容器内
所有 secrets 默认挂载为只读文件,路径 /run/secrets/<name>
常用属性
| 属性 | 说明 |
|---|---|
file |
从本地文本文件加载内容 |
environment |
从宿主机环境变量读取值 |
external |
使用已有 secret |
name |
对应 Docker 中的 secret 名称 |
【示例】
secrets:
db_password: # secret 名称
file: ./secrets/db_pass.txt # 从本地文件读取内容
jwt_key:
environment: JWT_SECRET_KEY # 从当前环境变量获取(Compose 主机上设置)
tls_cert:
external: true # 使用 Docker 已有的 secret(如通过 `docker secret create` 创建)
name: prod_tls_cert
services:
web:
image: nginx
secrets:
- db_password
- source: db_password
target: /run/secrets/postgres_password # 自定义挂载路径
uid: "1000"
gid: "1000"
mode: 0400 # 权限设置
2.6.configs
用于传递非敏感的配置文件(如 Nginx conf、JSON 配置等)
类似于 secrets,但内容不加密,适合通用配置文件
【示例】
configs:
app_config:
file: ./config/app.yaml # 从本地文件加载
nginx_conf:
external: true # 使用已创建的 config
name: live_nginx_conf
services:
web:
image: nginx
configs:
- source: app_config
target: /etc/myapp/config.yaml
uid: "1000"
gid: "1000"
mode: 0440
2.7.name
显式设置 Compose 项目的名称
默认项目名为当前目录名
【示例】
name: production-api-stack
services:
web:
image: myapp:latest
设置后,所有资源前缀变为 production-api-stack_web_1 而非 <dir>_web_1
3.常用命令
Docker Compose 通过docker-compose 系列命令查看和控制compose 中的所有服务容器
(1).docker-compose pull
拉取compose 中服务依赖的全部镜像或指定镜像
通过在命令后添加服务名称来指定
(2).docker-compose config
检查 compose 文件是否正确
可添加选项-q,表示只有存在问题时才有输出
(3).docker-compose up
启动 compose 中的所有容器
-d 选项表示后台启动
(4).docker-compose logs
查看comopse 中所有服务或指定服务的运行日志
通过在命令后添加服务名称来指定
默认情况下,将对不同的服务日志使用不同的颜色来区分
(5).docker-compose ps
列出 compose 中所有服务或指定服务
通过在命令后添加服务名称来指定
(6).docker-compose top
列出 compose 中当前正在运行的所有服务或指定服务
通过在命令后添加服务名称来指定
(7).docker-compose images
列出compose 中所有服务或指定服务对应的镜像
通过在命令后添加服务名称来指定
(8).docker-compose port
列出指定服务容器的指定端口所映射的宿主机端口
(9).docker-compose run
在指定服务上执行一条命令
(10).docker-compose exec
进入指定服务容器
通过在命令后添加服务名称来指定
(11).docker-compose pause
暂停 compose 中所有服务容器或指定服务容器
通过在命令后添加服务名称来指定
(12).docker-compose unpause
恢复 compose 中处于暂停状态的所有服务容器或指定服务容器
通过在命令后添加服务名称来指定
(13).docker-compose stop
停止 compose 中所有服务容器或指定服务容器
通过在命令后添加服务名称来指定
(14).docker-compose restart
重启 compose 中所有服务容器或指定服务容器
通过在命令后添加服务名称来指定
(15).docker-compose start
启动 compose 中所有服务容器或指定服务容器
通过在命令后添加服务名称来指定
(16).docker-compose kill
通过发送 SIGKILL 信号停止指定服务的容器
(17).docker-compose rm
删除 compose 中处于停止状态的所有服务容器或指定服务容器
通过在命令后添加服务名称来指定
(18).docker-compose down
停止并删除 compose 中的所有服务容器、网络、镜像、数据卷
4.Compose 使用步骤
- 使用 Dockerfile 定义应用程序的环境
- 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行
- 执行 docker-compose up 命令来启动并运行整个应用程序
三.Compose 安装
1.CentOS安装
(1).使用Python安装
yum -y install python3-pip
pip3 install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple
pip3 install docker-compose -i https://pypi.tuna.tsinghua.edu.cn/simple
docker-compose version
(2).使用github安装
Linux 上可以从 Github 上下载它的二进制包来使用
最新发行的版本地址:https://github.com/docker/compose/releases

运行以下命令以下载 Docker Compose 的当前稳定版本
# 下载2.38.1版本
sudo curl -L "https://github.com/docker/compose/releases/download/v2.38.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 下载v5.1.0版本
sudo curl -L "https://github.com/docker/compose/releases/download/v5.1.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
下载过程会非常慢,甚至前几次都无法连接,需要多次尝试

反复几次下载之后下载成功

该命令会从 github 下载 docker compose 插件到当前主机的/usr/local/bin 目录中,并被重命名为 docker-compose
要安装其他版本的 Compose请替换版本号"2.38.1"
添加可执行权限
sudo chmod +x /usr/local/bin/docker-compose
ll /usr/local/bin

创建软链
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

测试是否安装成功
docker-compose version

注意: 对于 alpine,需要以下依赖包: py-pip,python-dev,libffi-dev,openssl-dev,gcc,libc-dev,和 make
2.macOS
Mac 的 Docker 桌面版和 Docker Toolbox 已经包括 Compose 和其他 Docker 应用程序,因此 Mac 用户不需要单独安装 Compose
3.windows PC
Windows 的 Docker 桌面版和 Docker Toolbox 已经包括 Compose 和其他 Docker 应用程序,因此 Windows 用户不需要单独安装 Compose
四.项目构建
1.手工启动项目示例
1.1.项目代码
这是一个金融产品交易平台中的部分功能,是一个 Spring Boot 工程
控制器具有三个接口
- 查询所有产品
- 根据产品名称查询
- 上线新产品
整个架构包含一个 Redis 与 MySQL服务器
(1).数据库
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,
`endTime` 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');
(2).启动类
package com.abc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@EnableCaching
@SpringBootApplication
public class SsrmApplication {
public static void main(String[] args) {
SpringApplication.run(SsrmApplication.class, args);
}
}
(3).依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.abc</groupId>
<artifactId>ssrm</artifactId>
<version>0.0.1-SNAPSHOT</version>
<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>
<tika.version>1.28.5</tika.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.23</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers</artifactId>
<version>${tika.version}</version>
<type>pom</type>
</dependency>
<!--<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>${tika.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-parsers-standard-package</artifactId>
<version>${tika.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika</artifactId>
<version>${tika.version}</version>
</dependency>-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
(4).配置文件
这里特别要注意 mysql 与 redis 的 IP,使用的是相应 Docker 主机的 IP
mybatis:
mapper-locations: classpath:*.xml
type-aliases-package: com.abc.bean
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.1.11:3306/test?useUnicode=true&characterEncoding=utf-8
username: root
password: root
redis:
host: 192.168.1.11
port: 6379
cache:
type: redis
cache-names: pc
logging:
file:
name: "/var/applogs/finance.log"
pattern:
console: level-%-5level - %msg%n
file: level-%-5level - %msg%n
level:
root: warn
com.abc.dao: debug
(5).控制器
package com.abc.controller;
import com.abc.bean.Product;
import com.abc.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class ProductController {
@Autowired
private ProductService service;
// 查询所有产品
@GetMapping("/")
public String indexHandle() {
List<Product> allProducts = service.findAllProducts();
StringBuilder sb = new StringBuilder();
for (Product product : allProducts) {
sb.append(product).append("<br>");
}
return sb.toString();
}
// 上架新产品
@PostMapping("/register")
public String registerHandle(@RequestBody Product product) {
// 添加新产品
service.saveProduct(product);
return "save success";
}
// 根据产品名称查询产品
@GetMapping("/list")
public String listHandle(String name) {
List<Product> result = service.findProductsByName(name);
StringBuilder sb = new StringBuilder();
for (Product product : result) {
sb.append(product).append("<br>");
}
return sb.toString();
}
}
(6).实体类
package com.abc.bean;
import lombok.Data;
import java.io.Serializable;
@Data
public class Product implements Serializable {
private Integer id;
// 产品名称
private String name;
// 年化利率
private Double rate;
// 募集总额
private Double amount;
// 已募集金额
private Double raised;
// 产品周期
private Integer cycle;
// 产品募集结束时间
private String endTime;
}
(7).Service
- ProductService
package com.abc.service;
import com.abc.bean.Product;
import java.util.List;
public interface ProductService {
void saveProduct(Product product);
List<Product> findAllProducts();
List<Product> findProductsByName(String name);
}
- ProductServiceImpl
package com.abc.service;
import com.abc.bean.Product;
import com.abc.dao.ProductDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductDao dao;
@Override
@Transactional(rollbackFor = Exception.class)
@CacheEvict(value = "pc", allEntries = true)
public void saveProduct(Product product) {
dao.insertProduct(product);
}
@Cacheable(value = "pc", key = "'product_'+#name")
@Override
public List<Product> findProductsByName(String name) {
return dao.selectProductsByName(name);
}
@Cacheable(value = "pc", key = "'product_all'")
@Override
public List<Product> findAllProducts() {
return dao.selectAllProducts();
}
}
(8).DAO
package com.abc.dao;
import com.abc.bean.Product;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ProductDao {
void insertProduct(Product product);
List<Product> selectAllProducts();
List<Product> selectProductsByName(String name);
}
(9).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="com.abc.dao.ProductDao">
<insert id="insertProduct">
insert into product(name, rate, amount, raised, cycle, endTime)
values(#{name}, #{rate}, #{amount}, #{raised}, #{cycle}, #{endTime})
</insert>
<select id="selectAllProducts" resultType="Product">
select id,name,rate, amount, raised, cycle, endTime
from product
</select>
<select id="selectProductsByName" resultType="Product">
select id,name,rate, amount, raised, cycle, endTime
from product
where name like '%' #{xxx} '%'
</select>
</mapper>
1.2.定义Dockerfile
在 Docker 主机的任意目录中新建一个目录,该新建目录名称与项目名称相同
这里在/root 目录中 mkdir 一个名称为 finance(金融)的目录
mkdir -p /root/ssrm

然后在该目录中新建 Dockerfile 文件
[root@docker ~]# cd /root/ssrm/
[root@docker ssrm]# vim Dockerfile
# 指定当前镜像继承自 openjdk:8u102,因为下面要运行 Jar 包,需要 JDK 环境
FROM openjdk:8u102
# 作者与项目相关说明
MAINTAINER zhangsan zs@163.com
LABEL version="1.0" description="this is a spring boot application"
# 将当前目录下的 jar 包 copy 到容器中
# 注意:这个当前目录指的是 docker build 命令最后一个参数指定的上下文路径
COPY ssrm-0.0.1-SNAPSHOT.jar ssrm.jar
# 一定要执行的 exec
ENTRYPOINT ["java", "-jar", "ssrm.jar"]
# 指定对外暴露的端口号
EXPOSE 9000

注意可以在 Dockerfile 中通过 VOLUME 指定数据卷
1.3.项目打包
将项目 package 打为 jar 包,然后再上传到 Docker 主机的"/root/ssrm"目录中

1.4.手工启动项目
为了与使用 Docker Compose 编排项目进行对比,体现 Docker Compose 的方便快捷,这里先使用纯手工方式启动项目
1.4.1.启动 mysql 容器
在该系统中,要首先启动 mysql 或 redis,这里先启动 mysql 容器
docker run --name mysql \
-e MYSQL_ROOT_PASSWORD=root \
-v /root/software/mysql/data:/var/lib/mysql \
-v /root/software/mysql/log:/var/log \
-v /root/software/mysql/conf:/etc/mysql/conf.d \
-dp 3306:3306 \
mysql:8

进入 mysql
docker exec -it mysql /bin/bash
mysql -uroot -p

- 创建数据库
show databases;
create database if not exists test;
use test;
drop table if exists product;

- 创建表
CREATE TABLE IF NOT EXISTS `product`(
`id` INT(11) not null AUTO_INCREMENT,
`name` VARCHAR(100) default NULL,
`rate` double default NULL,
`amount` double default NULL,
`raised` double default NULL,
`cycle` int(11) default NULL,
`endTime` char(10) default '0',
PRIMARY KEY ( `id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

- 插入数据
insert into product(id,name,rate,amount,raised,cycle,endTime)values(1,'TXTY',2.76,50000,20000,6,'2020-10-10');
insert into product(id,name,rate,amount,raised,cycle,endTime)values(2,'JULY',3.31,20000,40000,7,'2021-11-11');
insert into product(id,name,rate,amount,raised,cycle,endTime)values(3,'LUCY',1.09,2456,4537,3,'2011-11-11');
insert into product(id,name,rate,amount,raised,cycle,endTime)values(4,'TOM' ,8.09,8976,3456,4,'2031-11-11');

查看数据表
SHOW TABLES;

查询数据
select * from product;

1.4.2.启动 redis 容器
注意这里可以直接执行下面的启动 redis 容器的命令的前提是,借用了之前在"常用服务器安装"章节中安装单机版 Redis 中创建的外挂文件/root/software/redis/redis.conf
docker run --name myredis \
-v /root/software/redis/redis.conf:/etc/redis/redis.conf \
-v /root/software/redis/data:/data \
-dp 6379:6379 \
redis:7 \
redis-server /etc/redis/redis.conf

1.4.3.启动应用容器
(1).检查应用配置文件
在构建应用镜像之前,打开项目的配置文件,再次确认配置文件中指定的 mysql 与 redis主机的 IP 地址是否为 Docker 主机的 IP
注意:不是相应的 Docker 容器的 IP,而是宿主机的IP,因为是通过宿主机的端口映射到容器的端口上的
如果不是则需要在修改后重新对项目进行 package 打包,然后再次将打包后的 jar 包上传到 Linux 系统的"/root/ssrm" 项目目录中

(2).构建应用镜像
构建镜像
docker build -t finance:1.0 .

此时便可查看到该新创建出的镜像
docker images

(3).启动容器
docker run --name myapp \
-v /root/myapp/log:/var/applogs \
-dp 9000:8080 finance:1.0

此时已经启动了三个容器
docker ps

(4).访问应用
-
页面访问
http://192.168.1.11:9000/

-
查看 Redis
此时查看 Redis,可以看到新增的缓存
[root@docker ssrm]# docker exec -it myredis /bin/bash root@6ced4e608fb9:/data# root@6ced4e608fb9:/data# redis-cli 127.0.0.1:6379> 127.0.0.1:6379> keys *
-
查看日志
此时查看数据卷/root/myapp/log 中的日志文件 finance.log
cat /root/myapp/log/finance.log
2.Compose 编排启动项目
手工启动项目不仅繁琐易错,而且还存在一个致命问题:当前应用访问的 mysql 与 redis只能是运行在当前 Docker 宿主机之上的,否则将无法访问到它们
因为在应用的配置文件中已经将 mysql 与 redis 的 IP 进行了硬编码,而使用 Docker Compose 可以解决所有问题
(1).定义 compose.yml
在"/root/ssrm"目录中新建一个文件 compose.yml
[root@docker ~]# vim /root/ssrm/compose.yml
services:
myapp: #指定app包的位置在当前compose.yml同级目录
build: ./
container_name: myapp #指定app容器的名字
ports:
- 9000:8080 #指定app容器的端口号,将宿主机的9000端口映射到容器的8080端口
volumes:
- ./logs:/var/applogs #指定app的日志目录的挂载点为app包所在目录下的logs目录
depends_on: #执行依赖的服务,在指定的服务启动后再启动app服务
- mysql
- redis
mysql:
image: mysql:8.0.32 #执行镜像
environment:
- "MYSQL_ROOT_PASSWORD=root" #设置root用户密码
ports:
- 3306:3306 #指定对外暴露的端口
volumes: #执行数据卷
- /root/ssrm/mysql/log:/var/log/mysql
- /root/ssrm/mysql/data:/var/lib/mysql
- /root/ssrm/mysql/conf:/etc/mysql/conf.d
redis:
image: redis:7.0
ports:
- 6379:6379
volumes:
- /root/ssrm/redis/redis.conf:/etc/redis/redis.conf
- /root/ssrm/redis/data:/data
command: redis-server /etc/redis/redis.conf

(2).修改应用
对于应用程序需要修改其配置文件 application.yml,将 mysql 与 redis 的主机名修改为它们相应服务的名称

(3).上传文件
由于应用程序的配置文件发生了变化,所以需要对应用程序重新进行 package 打包,并将新的 jar 包上传到 Linux 系统中的"/root/ssrm"目录中

将redis.conf文件上传到"/root/ssrm/redis/"目录下
mkdir -p /root/ssrm/redis

(4).启动所有容器
cd /root/ssrm/
docker-compose up -d

查看容器
docker ps

(5).写入 mysql 数据
-
进入 mysq
docker exec -it ssrm-mysql-1 /bin/bash mysql -uroot -p
-
准备数据
复制前面的 sql 文件中的内容,直接粘贴到 mysql 命令行即可
show databases; create database if not exists test; use test; drop table if exists product; CREATE TABLE IF NOT EXISTS `product`( `id` INT(11) not null AUTO_INCREMENT, `name` VARCHAR(100) default NULL, `rate` double default NULL, `amount` double default NULL, `raised` double default NULL, `cycle` int(11) default NULL, `endTime` char(10) default '0', PRIMARY KEY ( `id` ) )ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into product(id,name,rate,amount,raised,cycle,endTime)values(1,'TXTY',2.76,50000,20000,6,'2020-10-10'); insert into product(id,name,rate,amount,raised,cycle,endTime)values(2,'JULY',3.31,20000,40000,7,'2021-11-11'); insert into product(id,name,rate,amount,raised,cycle,endTime)values(3,'LUCY',1.09,2456,4537,3,'2011-11-11'); insert into product(id,name,rate,amount,raised,cycle,endTime)values(4,'TOM' ,8.09,8976,3456,4,'2031-11-11'); SHOW TABLES; select * from product;
-
访问应用
与前面手工启动项目的访问方式相同
192.168.1.11:9000

3.指定各组件名称
前面的 compose.yml 文件中应用生成的镜像采用的是默认名称
mysql 与 redis 生成的容器名称采用的是默认名称,生成并加入的 bridge 网络也称默认名称的网络
这些组件的所使用的默认名称也可以被指定名称所代替
(1).定义 compose2.yml
[root@docker ssrm]# vim /root/ssrm/compose2.yml
services:
myapp: #指定app包的位置在当前compose.yml同级目录
build: ./
container_name: someapp #指定app容器的名字
image: finance:2.0
ports:
- 9000:8080 #指定app容器的端口号,将宿主机的9000端口映射到容器的8080端口
volumes:
- ./logs:/var/applogs #指定app的日志目录的挂载点为app包所在目录下的logs目录
networks:
- ab
depends_on: #执行依赖的服务,在指定的服务启动后再启动app服务
- mysql
- redis
mysql:
image: mysql:8.0.32 #执行镜像
container_name: somemysql
environment:
- "MYSQL_ROOT_PASSWORD=root" #设置root用户密码
ports:
- 3306:3306 #指定对外暴露的端口
networks:
- ab
volumes: #执行数据卷
- /root/ssrm/mysql/log:/var/log/mysql
- /root/ssrm/mysql/data:/var/lib/mysql
- /root/ssrm/mysql/conf:/etc/mysql/conf.d
redis:
image: redis:7.0
container_name: someredis
ports:
- 6379:6379
networks:
- ab
volumes:
- /root/ssrm/redis/redis.conf:/etc/redis/redis.conf
- /root/ssrm/redis/data:/data
command: redis-server /etc/redis/redis.conf
networks:
ab:

(2).启动所有容器
这里通过-f 选项指定要使用的 compose 文件
[root@docker ssrm]# docker rm -f $(docker ps -qa)
[root@docker ssrm]# docker-compose -f /root/ssrm/compose2.yml up -d

(3).查看容器
查看容器可以看到容器名称为指定的名称

(4).查看网络
此时查看网络可以看到又新生成一个网络
对于生成的网络其生成的名称为"当前compose 文件所在目录名_ networks 下的第一级属性"
docker network ls

(5).查看网络详情
通过"docker network inspect ssrm_ab"命令查看该网络的详情
可以看到compose中定义的三个服务容器都在该网络中
docker network inspect ssrm_ab

更多推荐
所有评论(0)