写在前面

在前面我们已经学会了如何通过使用Maven插件或者Dockerfile的方式,来将SpringBoot应用构建为Docker镜像并运行,但是当我们的应用数量较多时,上述两种方式似乎变得很不友好。

此时可以使用Docker Compose来解决上述问题,Docker Compose是一个用于定义和运行多个docker容器应用的工具。使用Compose允许开发者使用YAML文件来配置应用服务,之后使用一个命令,就可以部署配置的所有服务。

安装Docker Compose

下载Docker Compose

使用如下命令来下载Docker Compose:

1
curl -L https://get.daocloud.io/docker/compose/releases/download/1.24.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

修改下载文件的权限

将下载文件的权限设置为可执行:

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

确认Docker Compose安装成功

可使用如下命令来确认Docker Compose已经安装成功:

1
docker-compose --version

如果输出Docker Compose的版本则说明它已经安装成功了。

Docker Compose使用步骤

一般来说,Docker Compose的使用分为三个步骤:
(1)使用Dockerfile来定义应用的程序环境,注意此步只有在需要修改初始化镜像时,才执行;
(2)使用docker-compose.yml文件来定义需要部署的应用程序服务,以便后续可通过执行脚本来一次性部署服务;
(3)使用docker-compose up命令一次性将所有应用服务部署起来。

docker-compose.yml配置文件常用命令

Docker Compose将所管理的容器分为三层,即工程、服务及容器。docker-compose.yml中定义的所有服务组成了一个工程,services节点下即为服务,服务之下为容器。容器与容器之间可通过以服务名称为域名来进行访问。举个例子,在shop-docker-compose服务中可通过jdbc:mysql://db:3306这个地址来访问db这个mysql服务。

version

version用于指定docker-compose的版本号,目前使用值都是3。

services

services是一系列服务的集合,该节点下定义具体的服务。

image

image用于指定服务所使用的镜像,举个例子如使用的是mysql5.7的镜像:

1
image: mysql:5.7

container_name

container_name用于设置容器的名称,举个例子如指定容器名称为mysql:

1
container_name: mysql

ports

ports用于设置宿主机和容器的端口映射,注意格式为(HOST:CONTAINER),举个例子将宿主机的3306端口映射到容器的3306端口:

1
2
ports:
- 3306:3306

volumes

volumes用于将宿主机的文件或者目录挂载到容器中,注意格式为(HOST:CONTAINER),举个例子将宿主机的如下文件挂载到容器中:

1
2
3
4
volumes:
- /mydata/mysql/log:/var/log/mysql
- /mydata/mysql/data:/var/lib/mysql
- /mydata/mysql/conf:/etc/mysql

environment

environment用于设置环境变量,举个例子设置MySQL初始化时root账户的密码:

1
2
environment:
- MYSQL_ROOT_PASSWORD=envy123

links用于连接其他的容器服务,注意格式为(SERVICE:ALIAS),举个例子以database为域名来访问服务名称为db的容器:

1
2
links:
- db:database

Docker Compose常用命令

构建、创建、启动相关容器

1
docker-compose up -d

其中的-d表示在后台运行。

指定文件启动

1
docker-compose -f docker-compose.yml up -d

停止所有相关容器

1
docker-compose stop

列出所有容器信息

1
docker-compose ps

使用Dockerfile构建SpringBoot应用镜像

复制一个Module

开发者可以复制一份shop-swagger-ui源码,将其名字修改为shop-docker-compose,然后对应包和文件中的信息也记得修改,本篇后续所有操作均在shop-docker-compose这一Module中进行。

编写Dockerfile文件

我们在项目的src/main目录中新建一个名为docker的目录,然后在docker目录中新建一个名为Dockerfile的文件,里面的内容如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
# 指定该镜像所依赖的基础镜像
FROM openjdk:8u102
# 指定镜像的维护人
MAINTAINER kenbings
# 将当前目录下的jar包复制到docker容器中的/目录下
ADD shop-docker-compose-0.0.1-SNAPSHOT.jar /shop-docker-compose.jar
# 容器在运行过程中创建一个名为shop-docker-compose.jar的文件
RUN bash -c 'touch /shop-docker-compose.jar'
# 声明服务暴露在8080端口
EXPOSE 8080
# 指定容器启动时执行的命令
ENTRYPOINT ["java","-jar","/shop-docker-compose.jar"]

使用maven打包应用

接下来我们按照图示操作进行打包:

可以看到镜像构建成功:

1
2
3
4
5
6
7
8
9
10
[INFO] Building jar: E:\MyShop\myshop-all\shop-docker-compose\target\shop-docker-compose-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.3.RELEASE:repackage (repackage) @ shop-docker-compose ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.948 s
[INFO] Finished at: 2021-12-13T16:47:42+08:00
[INFO] ------------------------------------------------------------------------

接着我们新建/mydata/app/shop-docker-compose目录,然后将打包生成的jar包以及Dockerfile文件上传到该目录中。

在Linux系统上构建Docker镜像

/mydata/app/shop-docker-compose目录下,执行如下命令来构建docker镜像:

1
docker build -t myshop-all/shop-docker-compose:0.0.1-SNAPSHOT .

其中-t表示指定镜像仓库名称/镜像名称:镜像标签,.表示使用当前目录下的Dockerfile文件。

使用Docker Compose部署应用

编写docker-compose.yml文件

我们在项目的src/main目录中新建一个名为docker的目录,然后在docker目录中新建一个名为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
version: '3'
services:
# 指定服务名称
db:
# 指定服务使用的镜像
image: mysql:5.7
# 指定容器的名称
container_name: mysql
# 指定服务运行的端口
ports:
- 3306:3306
# 指定容器中需要挂载的文件目录
volumes:
- /mydata/mysql/log:/var/log/mysql
- /mydata/mysql/data:/var/lib/mysql
- /mydata/mysql/conf:/etc/mysql
# 指定容器的环境变量
environment:
- MYSQL_ROOT_PASSWORD=envy123
# 指定服务名称
shop-docker-compose:
# 指定服务使用的镜像
image: myshop-all/shop-docker-compose:0.0.1-SNAPSHOT
# 指定容器的名称
container_name: shop-docker-compose
# 指定服务运行的端口
ports:
- 8080:8080
# 指定容器中需要挂载的文件目录
volumes:
- /etc/localtime:/etc/localtime
- /mydata/app/shop-docker-compose/logs:/var/logs

运行Docker Compose命令启动所有服务

将上面定义的docker-compose.yml文件上传至/mydata/app/shop-docker-compose目录中,然后在该目录中执行如下命令:

1
docker-compose up -d

查看一下服务是否已经启动:

1
2
3
4
5
[root@kenbings shop-docker-compose]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
252d6d043a3d myshop-all/shop-docker-compose:0.0.1-SNAPSHOT "java -jar /shop-doc…" 3 minutes ago Up 3 minutes 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp shop-docker-compose
3c1f3944c4ca registry:2 "/entrypoint.sh /etc…" 7 hours ago Up 7 hours 0.0.0.0:5000->5000/tcp, :::5000->5000/tcp registry2
1f83ff04b145 mysql:5.7 "docker-entrypoint.s…" 25 hours ago Up 2 minutes 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql

接着我们需要进入到运行MySQL服务的docker容器中:

1
docker exec -it mysql /bin/bash

使用MySQL命令进入客户端:

1
mysql -uroot -penvy123 --default-character-set=utf8

然后创建shop数据库:

1
create database shop character set utf8;

接着打开一个新的终端,安装上传下载插件,将shop.sql文件上传到Linux服务器上,可指定目录为/mydata

1
yum -y install lrzsz

然后将shop.sql文件拷贝到mysql容器的/目录下:

1
docker cp /mydata/shop.sql mysql:/

接着进入到之前的sql命令环境,将shop文件导入到数据库:

1
2
use shop;
source /shop.sql;

修改root的账号的权限,使得任何ip都能访问到:

1
grant all privileges on *.* to 'root'@'%';

接着我们开放8080端口(注意只有当防火墙是运行状态下才需要进行此操作):

1
2
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload

然后打开浏览器,访问http://宿主机IP:8080/swagger-ui.html连接,查看shop-docker-compose服务是否已经正常启动:

接着我们测试一下“获取所有的品牌信息”的接口,可以看到数据是可以正常返回的:

这样我们就完成了使用Docker Compose部署SpringBoot应用,并运行项目这一功能。