编写redis的docker-compose.yml配置文件,参数含义参考注释
不同的编排文件建议放到单独的文件夹中,比如单独新建一个redis目录,mysql的就创建mysql目录,依次类推
version: "3"
services:
redis:
container_name: redis
image: redis:latest
ports:
- "6379:6379"
volumes:
- /root/docker/compose/redis/redis.conf:/etc/redis/redis.conf
- /root/docker/compose/redis/data:/data
networks:
- my_network
command: redis-server /etc/redis/redis.conf
networks:
my_network:
2.2 运行配置文件
在docker-compose.yml所在文件夹通过docker-compose up运行,也可以添加-d参数在后台运行
此处docker-compose.yml所在文件夹:/root/docker/compose
# docker-compose up
Creating network "compose_my_network" with the default driver
Creating redis ... done
Attaching to redis
redis | 1:C 24 Mar 2022 00:13:38.331 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis | 1:C 24 Mar 2022 00:13:38.331 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=1, just started
redis | 1:C 24 Mar 2022 00:13:38.332 # Configuration loaded
redis | 1:M 24 Mar 2022 00:13:38.332 * monotonic clock: POSIX clock_gettime
查看docker实例
进入容器内部,可以执行redis的客户端工具
# docker-compose exec redis bash
root@f5865bc42306:/data# redis-cli
查看网络,发现compose会自动创建在编排文件中的配置文件
# docker network ls
NETWORK ID NAME DRIVER SCOPE
012d4d17c012 bridge bridge local
# 默认将会创建为 docker-compose.yml所在文件夹名_my_network 网络名称
88c54133c87a compose_my_network bridge local
1524da0505ee host host local
f4cbc4779eaf none null local
查看网络细节
docker network inspect compose_my_network
"Name": "compose_my_network",
"Id": "88c54133c87a04cc8c86a55c240d2ccafb9bfb456b8e7d185a9a246b5d274025",
"Created": "2022-03-24T00:13:37.623603357Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
"Subnet": "172.20.0.0/16",
"Gateway": "172.20.0.1"
"Internal": false,
"Attachable": true,
"Ingress": false,
"ConfigFrom": {
"Network": ""
"ConfigOnly": false,
"Containers": {
"f5865bc42306380b1bd72690d6f67d8abdd46a240a96ea5f9bcfee412fe76c17": {
"Name": "redis",
"EndpointID": "8638b4c9850e533778d331bfd916b120f8a1ac59a9f547763c5e352df93ed897",
"MacAddress": "02:42:ac:14:00:02",
"IPv4Address": "172.20.0.2/16",
"IPv6Address": ""
"Options": {},
"Labels": {
# 内部实际名称还是my_network
"com.docker.compose.network": "my_network",
# 容器编排项目名称
"com.docker.compose.project": "compose",
"com.docker.compose.version": "1.29.2"
docker-compose stop:停止但不删除
docker-compose down:停止并且删除网络等一些列配置
# docker-compose down
Removing redis ... done
Removing network compose_my_network
三、MySQL编排
3.1 编写配置文件
注意这里只贴出了compose的构建配置,等同的docker命令参考redis部分,只是内容变了,但是等级等价的命令并没有太大差异
version: "3"
services:
mysql:
container_name: mysql
image: mysql:5.7
ports:
- "33306:3306"
environment:
MYSQL_ROOT_PASSWORD: 'tianxin'
MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
MYSQL_DATABASE: 'docker'
MYSQL_USER: 'docker'
MYSQL_PASSWORD: '123456'
volumes:
- /root/docker/compose/mysql/data:/var/lib/mysql
- /root/docker/compose/mysql/conf/my.cnf:/etc/my.cnf
- /root/docker/compose/mysql/init:/docker-entrypoint-initdb.d
networks:
- my_network
command: --default-authentication-plugin=mysql_native_password
networks:
my_network:
3.2 运行配置文件
在mysql docker-compose.yml所在文件夹通过docker-compose up运行,也可以添加-d参数在后台运行
运行之后养成随手就是 docker ps 查看容器是否启动的好习惯
进入容器内容,通过指定的密码登录
# docker-compose exec mysql bash
root@6cb40ff45da5:/# mysql -uroot -ptianxin
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.36 MySQL Community Server (GPL)
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
# 这里可以看到,自动创建了docker数据库
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| docker |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> use docker;
Database changed
mysql> show tables;
Empty set (0.00 sec)
四、微服务编排
tip:MySQL和Redis相对于独立,但是对于服务而言,依赖于Redis和MySQL,所以在服务启动前需要先启动Redis和MySQL,如果依赖服务较多,人工管理是一件比较麻烦的事情。通过docker-compose的编排可以指定依赖关系等等
4.1 编写服务
创建SpringBoot服务,采用SpringBoot+MyBatis+MySQL+Redis完成简单的SpringBoot应用
maven的pom.xml依赖如下
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/>
</parent>
<groupId>com.codecoord</groupId>
<artifactId>docker</artifactId>
<version>1.0</version>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<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>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
应用配置文件
特别说明:服务依赖的容器服务,使用容器服务名称,比如 jdbc:mysql://mysql:3306/docker,不要通过IP。端口号是容器内部端口,不是外部端口号!比如 -p 13306:3306,13306是对外端口,3306才是容器内部服务端口,服务依赖时不要指定为外部端口,生产中也不建议除了服务外的容器直接对外提供访问
server:
port: 80
spring:
redis:
port: 6379
host: redis
datasource:
url: jdbc:mysql://mysql:3306/docker?userSSL=false
username: root
password: tianxin
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
import com.codecoord.docker.domain.User;
import com.codecoord.docker.service.UserService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.*;
@RestController
@RequestMapping("/docker")
public class DockerController {
@Resource
private UserService userService;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@RequestMapping("/list")
public List<User> list() {
return userService.list();
@RequestMapping("/add")
public boolean add() {
return userService.save(new User() {{
setName(UUID.randomUUID().toString());
@RequestMapping("/get/{id}")
public Object get(@PathVariable("id") Long id) {
Map<String, Object> returnMap = new HashMap<>();
Object cache = redisTemplate.opsForValue().get(id);
if (Objects.nonNull(cache)) {
returnMap.put("data", cache);
returnMap.put("cache", "缓存命中");
return returnMap;
User user = userService.getById(id);
returnMap.put("data", user);
returnMap.put("cache", "缓存未命中");
redisTemplate.opsForValue().set(id.toString(), user);
return returnMap;
其他DAO层的按照MP格式搭建接口,注意实体类需要序列化
Redis的序列化按照自己的需要配置
4.2 服务构建
先安装java:8镜像,参考Docker-高级篇(1)-Dockerfile(核心&构建Redis&构建JDK8) - 掘金 (juejin.cn)
编写Dockerfile,将服务项目打成jar包(普通的springboot使用maven package打包后的jar包)之后和Dockerfile放于同一个文件文件夹下
# 基础镜像使用java8,需要先构建
FROM java:8
MAINTAINER tianxincoord@163.com
# 容器卷,指定临时文件的目录为/tmp
VOLUME /tmp
# 指定工作目录
WORKDIR /tmp
# 重命名可选操作,方便docker ps查看
add docker-1.0.jar core_service.jar
# 运行jar包
ENTRYPOINT ["java", "-jar", "core_service.jar"]
# 暴露30001端口作为服务端口
EXPOSE 30001
# 构建镜像
# docker build -t core_service:1.0 .
Sending build context to Docker daemon 245.5MB
Step 1/7 : FROM java:8
---> 95064f52c03b
Step 2/7 : MAINTAINER tianxincoord@163.com
---> Running in 4e2fe1672499
Removing intermediate container 4e2fe1672499
---> e17943871098
Step 3/7 : VOLUME /tmp
---> Running in b7f7d56bc0cf
Removing intermediate container b7f7d56bc0cf
---> 7b67adbb7378
Step 4/7 : WORKDIR /tmp
---> Running in 973e07d965cb
Removing intermediate container 973e07d965cb
---> 70f5211073eb
Step 5/7 : add docker-1.0.jar core_service.jar
---> 5015d0feafeb
Step 6/7 : ENTRYPOINT ["java", "-jar", "core_service.jar"]
---> Running in a8b45a171493
Removing intermediate container a8b45a171493
---> 0e9ea7fb43c7
Step 7/7 : EXPOSE 30001
---> Running in 01e5efc042a6
Removing intermediate container 01e5efc042a6
---> af170edd9100
Successfully built af170edd9100
Successfully tagged core_service:1.0
查看构建完成后的镜像
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
core_service 1.0 af170edd9100 58 seconds ago 648MB
java 8 95064f52c03b 8 minutes ago 610MB
centos 7 eeb6ee3f44bd 6 months ago 204MB
4.3 服务编排(redis&mysql&服务)
编写compose配置文件
version: "3"
services:
macro_server:
image: core_service:1.0
container_name: core_service
ports:
- "80:80"
volumes:
- /root/docker/compose/app:/data
networks:
- my_network
depends_on:
- redis
- mysql
redis:
container_name: redis
image: redis:latest
ports:
- "6379:6379"
volumes:
- /root/docker/compose/redis/redis.conf:/etc/redis/redis.conf
- /root/docker/compose/redis/data:/data
networks:
- my_network
command: redis-server /etc/redis/redis.conf
mysql:
container_name: mysql
image: mysql:5.7
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: 'tianxin'
MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
MYSQL_DATABASE: 'docker'
MYSQL_USER: 'docker'
MYSQL_PASSWORD: '123456'
volumes:
- /root/docker/compose/mysql/data:/var/lib/mysql
- /root/docker/compose/mysql/conf/my.cnf:/etc/my.cnf
- /root/docker/compose/mysql/init:/docker-entrypoint-initdb.d
networks:
- my_network
command: --default-authentication-plugin=mysql_native_password
networks:
my_network:
启动compose
# docker-compose up
Creating network "compose_my_network" with the default driver
Creating redis ... done
Creating mysql ... done
Creating core_service ... done
进入服务内部,ping一下服务名,看一下是否网络连接成功,只有这里ping得通,服务才会调用得通
4.5 服务测试
进入MySQL服务中,创建对应的库和表
docker exec -it mysql bash
use docker;
create table user
id int primary key auto_increment,
name varchar(50),
create_time datetime not null default current_timestamp,
modify_time datetime not null default current_timestamp on update current_timestamp
访问接口是否正常
http://192.168.33.10:80/docker:未配置的路径,正常抛出404
5.1 自愈性
服务容器化之后可以比普通jar部署方式拥有更高自愈性,比如原来普通jar部署当服务挂了之后,必须要重新处理启动服务,此时也可以通过一个看门狗程序当发现进程挂了之后自动重启,但是当服务多了,管理起来是一个比较麻烦的时候
而对于容器来说,就是docker kill/stop和docker run就可以快速淘汰老的服务启动新服务
5.2 调度性
传统jar部署方式最大的问题在于环境的一致性,比如现在A服务器上的服务能力不够了,需要在B服务器上部署一个新服务,那么安装环境是一个很麻烦的事情,特别是对于配置项目较多的服务来说进行大规模的快速调度基本上是一个很麻烦且费力的操作
对于容器化服务来说,所有的依赖服务在一个镜像完成后就可以以此进行为模板快速docker run很多很多的相同配置环境的服务
那么在弹性扩缩容上,通过容器可以很方便达到这个目标,服务容器话是一个服务用户到了一定规模之后不得不考虑的问题
TianXinCoord
TianXinCoord
粉丝