行百里er 行百里er
首页
  • 分类
  • 标签
  • 归档
设计模式
  • JVM
  • Java基础
MySQL
Elastic Stack
Redis
  • Kafka
  • RocketMQ
分布式
Spring Cloud Alibaba
云原生
数据结构与算法
关于
GitHub (opens new window)

行百里er

Java程序员一枚
首页
  • 分类
  • 标签
  • 归档
设计模式
  • JVM
  • Java基础
MySQL
Elastic Stack
Redis
  • Kafka
  • RocketMQ
分布式
Spring Cloud Alibaba
云原生
数据结构与算法
关于
GitHub (opens new window)
  • 容器化技术之Docker-从入地到上天
  • 玩转Docker镜像仓库-Docker Registry及Harbor
  • 使用Rancher部署管理K8S集群,真香!
  • 用 docker-compose 部署服务真是好用,根本停不下来!
    • Docker Compose 是个啥?
    • 安装 Docker Compose
    • 使用 Docker Compose 编排应用程序
      • Docker Compose 编排容器的步骤
      • 创建 Spring Boot 项目
      • 编写 web 项目的 Dockerfile 文件
      • 编写 Redis 服务的 Dockerfile 文件
      • 编写 docker-compose.yml 文件
      • 使用 docker-compose up 启动服务
      • 验证服务
    • 小结
  • 云原生
行百里er
2022-08-27
目录

用 docker-compose 部署服务真是好用,根本停不下来!

作者:行百里er

博客:https://chendapeng.cn (opens new window)

提示

这里是 行百里er 的博客:行百里者半九十,凡事善始善终,吾将上下而求索!

# Docker Compose 是个啥?

假设你已经对 Docker 的相关知识已经有所了解,如果不了解可以瞅一眼我的这篇介绍 Docker 的文章:

容器化技术之Docker-从入地到上天 (opens new window)

有了 Docker ,为啥还要 Docker Compose 呢?我们来想想,用容器运行一个服务,需要使用 docker run 命令,但如果我要运行多个服务呢?

比如,我有一个 Web 服务,该服务依赖 Redis 服务的存在,因为需要读取 Redis 中的数据,那么我该用一个容器运行,还是用多个容器运行呢?

一个容器运行多个服务会造成 镜像 的复杂度变高, Docker 倾向于一个容器运行一个应用 。那该如何解决一个应用中需要多个容器,并且容器间需要通信这样的问题呢?

答:使用 容器编排 。Docker Compose 中的 compose 就是 组织、编排 的意思。具体就是可以通过 Docker Compose 对多个容器进行管理。Docker Compose 是一个用于定义和运行多容器 Docker 的应用程序工具。

# 安装 Docker Compose

Docker Compose 的安装极其简单:

1, 下载 Docker Compose 的可执行程序

下载地址:https://github.com/docker/compose/releases (opens new window)

我们把环境放在 Linux 下,所以我们下载这个:

image-20220825161503366.png

下载完了,上传到 Linux 服务器上。或者直接使用如下命令下载:

wget https://github.com/docker/compose/releases/download/v2.10.0/docker-compose-linux-x86_64
1

2, 将下载下来的 docker-compose-linux-x86_64 文件移动到 /user/bin 目录下并命名为 docker-compose

mv docker-compose-linux-x86_64 /usr/bin/docker-compose
1

3, 增加 docker-compose 文件的可执行权限

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

4, 验证

[root@docker ~]# docker-compose version
Docker Compose version v2.10.0
1
2

安装完成。

# 使用 Docker Compose 编排应用程序

# Docker Compose 编排容器的步骤

1, 定义应用的 Dockerfile 文件,为了在任何地方都能构建

2, 通过 docker-compose.yml 定义一套服务 services ,这些服务可以在一个隔离的环境中一起运行,并能相互通信

3, docker-compose up 启动一整套服务

就用文章开始说的那个例子,写一个 web 程序,提供接口,该接口返回访问服务的次数,而这个次数需要从 Redis 中读取。

# 创建 Spring Boot 项目

我们来创建一个 Spring Boot 的 web 程序,访问 http://ip:port/hits 时读取 Redis 中的值,返回这是第几次访问。

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

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new StringRedisSerializer());
        template.setHashValueSerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }

    @RestController
    public class TestController {
        @Autowired
        private StringRedisTemplate redisTemplate;

        @GetMapping("/hits")
        public String test() {
            redisTemplate.opsForValue().increment("hits");
            return "哥们,这是你第 " + redisTemplate.opsForValue().get("hits") + " 次来我的瓜摊了!";
        }
    }
}
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

pom.xml 依赖咱就不说了,添加 spring-boot-starter-web 、spring-boot-starter-data-redis 。

application.properties 配置文件:

# 应用名称
spring.application.name=demo-app
# 应用服务 WEB 访问端口
server.port=8080

spring.redis.host=redis
spring.redis.port=16379
spring.redis.password=123456
1
2
3
4
5
6
7
8

这里先不管我的 Redis 的 host 为什么这样配置,而不是配置 IP 地址,下面会说到。

打包后得到 demo-app-0.0.1-SNAPSHOT.jar 文件,并将其上传到 Linux 服务器的 /usr/local/demoapp/app 目录下,注意这个目录有讲究,后面编写 Dockerfile 以及 docker-compose.yml 文件的时候注意目录之间的层级关系。

# 编写 web 项目的 Dockerfile 文件

Dockerfile 文件的介绍这里就不多说了,请看这里:

https://juejin.cn/post/6901079628828377101#heading-22 (opens new window)

我们直接来编写,在 /usr/local/demoapp/app 目录下,创建 Dockerfile 文件,内容如下:

FROM openjdk:8u222-jre
WORKDIR /usr/local/apphouse
ADD demo-app-0.0.1-SNAPSHOT.jar .
EXPOSE 8080
CMD ["java", "-jar", "demo-app-0.0.1-SNAPSHOT.jar"]
1
2
3
4
5

因为咱们是通过运行 jar 包的方式启动项目,所以依赖 Java 运行环境,从 Docker 仓库中找到一个 JDK 8 的镜像:

https://hub.docker.com/search?q=jdk

image-20220825151615680.png

# 编写 Redis 服务的 Dockerfile 文件

在 /usr/local/demoapp/redis 目录下,编写 Dockerfile 文件:

FROM redis:5.0.14
MAINTAINER chendapeng.cn
COPY redis.conf /usr/local/etc/redis/redis.conf
EXPOSE 16379
CMD [ "redis-server", "/usr/local/etc/redis/redis.conf" ]
1
2
3
4
5

这里选择的Redis版本是 5.0.14, 其中 redis.conf 是提前从 Redis 的官方 Github 上下载对应版本的 conf 文件,该文件的 Github 地址: https://github.com/redis/redis/blob/5.0.14/redis.conf

下载到本地放到 /usr/local/demoapp/redis 目录下,并修改其中几项的内容:

# 这一句注释掉,使其可以被外部访问
# bind 127.0.0.1

# protected-mode 设置为 no
protected-mode no

# 修改端口
port 16379

# 设置密码
requirepass 123456
1
2
3
4
5
6
7
8
9
10
11

# 编写 docker-compose.yml 文件

将 web 容器和 redis 容器组织编排起来,使用 docker-compose.yml 进行定义:

version: '3'
services:
  redis:
    build: ./redis/
    restart: always
  demoapp:
    build: ./app/
    depends_on:
      - redis
    ports:
      - "8080:8080"
    restart: always
1
2
3
4
5
6
7
8
9
10
11
12

这里一定要注意每个服务 build 字段的配置,一定要设置为该服务 Dockerfile 文件所在的文件路径。当前所有文件都准备好了,每个文件的位置如图所示:

image-20220825170438505.png

这里可以解释一下前面的关于 Spring Boot 项目中配置文件:

spring.redis.host=redis
spring.redis.port=16379
spring.redis.password=123456
1
2
3

为什么 Redis 的 host 直接使用 redis 这个字符串而不是 IP 地址了,因为 docker-compose.yml 中定义了名为 redis 的服务,并且 demoapp 项目依赖(depends_on)该服务,那么在容器中就可以直接使用服务名称进行访问 Redis 了。

# 使用 docker-compose up 启动服务

先来看一下,目前我的环境中什么容器和镜像都没有:

image-20220825171521296.png

进入到 /usr/local/demoapp ,使用命令启动服务:

docker-compose up
1

第一次启动,需要下载一些镜像:

image-20220825171655317.png

然后就可以看到,首先是 Redis 服务先起来了:

image-20220825171752547.png

然后我们的 web 项目也起来了:

image-20220825171839675.png

现在我们再来看一下容器和镜像情况:

image-20220825171929834.png

# 验证服务

服务既然已经起来了,我们来运行一下,访问 http://192.168.242.8080/hits :

screenshots.gif

牛逼,访问没有问题!

# 小结

Docker Compose 在单机编排多个容器的时候时是常方便的,比如本文的例子中就一键启动了 Redis 和 Spring Boot 项目,实际上我们还可以加上 MySQL, ES 等其他服务,这样服务多起来更能显示 Docker Compose 的威力。

另外,Docker Compose 在安装一些软件的时候也是相当的省事的,强烈建议大家学习一波。


首发公众号 行百里er ,欢迎老铁们关注阅读指正。

#Docker
上次更新: 2022/10/04, 18:14:30
使用Rancher部署管理K8S集群,真香!

← 使用Rancher部署管理K8S集群,真香!

最近更新
01
重要数据不能丢!MySQL数据库定期备份保驾护航!
05-22
02
分布式事务解决方案之 Seata(二):Seata AT 模式
09-09
03
Seata 番外篇:使用 docker-compose 部署 Seata Server(TC)及 K8S 部署 Seata 高可用
09-05
更多文章>
Theme by Vdoing | Copyright © 2020-2023 行百里er | MIT License | 豫ICP备2022020385号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式