用 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 下,所以我们下载这个:
下载完了,上传到 Linux 服务器上。或者直接使用如下命令下载:
wget https://github.com/docker/compose/releases/download/v2.10.0/docker-compose-linux-x86_64
2, 将下载下来的 docker-compose-linux-x86_64
文件移动到 /user/bin
目录下并命名为 docker-compose
mv docker-compose-linux-x86_64 /usr/bin/docker-compose
3, 增加 docker-compose
文件的可执行权限
chmod +x /usr/bin/docker-compose
4, 验证
[root@docker ~]# docker-compose version
Docker Compose version v2.10.0
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") + " 次来我的瓜摊了!";
}
}
}
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
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"]
2
3
4
5
因为咱们是通过运行 jar
包的方式启动项目,所以依赖 Java 运行环境,从 Docker 仓库中找到一个 JDK 8 的镜像:
https://hub.docker.com/search?q=jdk
# 编写 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" ]
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
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
2
3
4
5
6
7
8
9
10
11
12
这里一定要注意每个服务 build
字段的配置,一定要设置为该服务 Dockerfile 文件所在的文件路径。当前所有文件都准备好了,每个文件的位置如图所示:
这里可以解释一下前面的关于 Spring Boot 项目中配置文件:
spring.redis.host=redis
spring.redis.port=16379
spring.redis.password=123456
2
3
为什么 Redis 的 host
直接使用 redis
这个字符串而不是 IP 地址了,因为 docker-compose.yml
中定义了名为 redis
的服务,并且 demoapp
项目依赖(depends_on)该服务,那么在容器中就可以直接使用服务名称进行访问 Redis 了。
# 使用 docker-compose up 启动服务
先来看一下,目前我的环境中什么容器和镜像都没有:
进入到 /usr/local/demoapp
,使用命令启动服务:
docker-compose up
第一次启动,需要下载一些镜像:
然后就可以看到,首先是 Redis 服务先起来了:
然后我们的 web 项目也起来了:
现在我们再来看一下容器和镜像情况:
# 验证服务
服务既然已经起来了,我们来运行一下,访问 http://192.168.242.8080/hits
:
牛逼,访问没有问题!
# 小结
Docker Compose 在单机编排多个容器的时候时是常方便的,比如本文的例子中就一键启动了 Redis 和 Spring Boot 项目,实际上我们还可以加上 MySQL, ES 等其他服务,这样服务多起来更能显示 Docker Compose 的威力。
另外,Docker Compose 在安装一些软件的时候也是相当的省事的,强烈建议大家学习一波。
首发公众号 行百里er ,欢迎老铁们关注阅读指正。