Docker进阶:Docker Compose(容器编排) 管理多容器应用—实战案例演示
💖The Begin💖点点关注,收藏不迷路💖
**
在开始之前,我们需要确保已经安装了 Docker
。**
一、Docker Compose简介
前面我们使用 Docker 的时候,定义 Dockerfile 文件,然后使用 docker build、docker run 等命令操作容器。然而微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而知。
使用 Docker Compose 可以轻松、高效的管理容器,它是一个用于定义和运行多容器 Docker 的应用程序工具。它通过一个简单易懂的 YAML 文件来定义应用程序的各个服务(只需一个命令、即可启动、关闭这些容器),并提供了简洁的命令行界面来管理这些容器。
下面是一个简单的示例来说明Docker Compose的工作原理:
假设我们有一个Web应用程序,它由两个容器组成:一个是运行Web服务器的容器,另一个是运行数据库的容器。使用Docker Compose,我们可以将这两个容器的配置定义在一个YAML文件中,例如docker-compose.yml:
version:'3'
services:
web:
image: nginx
ports:-80:80
depends_on:- db
db:
image: mysql
environment:- MYSQL_ROOT_PASSWORD=secret
在上面的示例中,我们定义了两个服务:web和db。每个服务都指定了所使用的镜像和一些配置。例如,web服务使用了nginx镜像,并将主机的端口80映射到容器的端口80。db服务使用了mysql镜像,并设置了一个环境变量。
要启动这个应用程序,我们只需在命令行中运行docker-compose up命令。Docker Compose将根据docker-compose.yml文件的定义,下载所需的镜像并创建和启动相应的容器。这两个容器将会自动建立网络连接,并按照定义的依赖关系来启动。
通过使用Docker Compose,我们可以轻松地定义、启动和管理多个容器组成的应用程序。这使得开发、测试和部署复杂的多容器应用程序变得更加简单和可靠。
二、Docker Compose安装
官网:https://docs.docker.com/compose/install/standalone/
1、查看系统架构:
[root@zyl-server ~]# uname -s
Linux
[root@zyl-server ~]# uname -m
x86_64
[root@zyl-server ~]#2、将Docker Compose的二进制文件下载到/usr/local/bin/docker-compose
# 官网安装
sudo curl -L "https://github.com/docker/compose/releases/download/<VERSION>/docker-compose-$(uname -s)-$(uname -m)"-o /usr/local/bin/docker-compose
--将<VERSION>替换为实际的版本号,$(uname -s)-$(uname -m) 为实际系统架构。
下载命令:
curl -L "https://github.com/docker/compose/releases/download/v2.20.2/docker-compose-linux-x86_64"-o /usr/local/bin/docker-compose
3、授予docker-compose二进制文件可执行权限:
sudo chmod +x /usr/local/bin/docker-compose
4、验证Docker Compose是否安装成功,运行以下命令:
docker-compose --version
如果一切顺利,将看到Docker Compose的版本信息。
如:
Docker Compose version v2.20.2
现在,已经成功地安装了Docker Compose。即可使用docker-compose命令管理和部署Docker容器。
三、Docker Compose卸载
卸载Docker Compose,如果是⼆进制包⽅式安装的,删除⼆进制⽂件即可。
sudo rm /usr/local/bin/docker-compose
如果使用了非二进制方式安装Docker Compose,例如使用包管理器或其他安装方法,可以根据具体使用的方法来卸载Docker Compose。
以下是一些常见的卸载方法:
1、如果使用pip安装了Docker Compose,请使用以下命令卸载:
pip uninstall docker-compose
2、如果使用包管理器(如apt、yum或dnf)安装了Docker Compose,使用包管理器的相应命令来卸载。例如,在Ubuntu上,可以运行以下命令:
sudo apt remove docker-compose
在CentOS上,可以运行以下命令:
sudo yum remove docker-compose
确认已成功卸载后,可以通过运行docker-compose --version命令来验证Docker Compose是否已完全卸载。
四、Docker Compose核心概念
4.1、一文件原则(docker-compose.yml)
Docker Compose的核心理念是使用一个YAML格式的Compose文件来定义容器化应用的结构和配置信息。这个Compose文件可以包含多个服务以及它们相关的配置项,例如镜像、环境变量、网络设置等。通过这个一文件原则,我们可以将应用的整体结构和配置信息集中地进行管理和维护。
4.2、服务(service)
服务的定义
服务(service)是Compose文件中的一个关键概念,它代表了一个个容器化的应用。每个服务可以包括一个或多个容器,共同完成特定的功能。比如,一个Web应用可能包含一个Web服务器容器和一个数据库容器。
服务的配置
在Compose文件中,我们可以为每个服务指定以下配置项:
镜像(image):用于指定服务所使用的Docker镜像。
环境变量(environment):用于设置服务容器的环境变量。
端口映射(ports):用于将容器内的端口映射到主机上。
依赖关系(depends_on):用于指定服务之间的依赖关系,确保它们按照正确的顺序启动。
服务的启动和管理 通过执行docker-compose up命令,我们可以启动Compose文件中定义的所有服务。
Docker Compose会自动创建和管理相关的容器。同时,我们还可以使用其他命令来管理服务,如docker-compose stop停止服务、docker-compose restart重启服务等。
4.3、工程(project)
工程的定义
工程(project)是Docker Compose中的另一个核心概念,它代表了一个Compose文件所定义的完整应用。一个工程可以包含多个服务,通过Compose文件统一管理和部署。
多工程支持
Docker Compose不仅支持单一工程,还可以同时管理多个工程。通过指定不同的Compose文件,我们可以轻松地定义和管理多个应用。
多环境支持
在实际开发和部署中,我们通常会有不同的环境(如开发、测试、生产环境)需要支持。Docker Compose通过使用不同的Compose文件,可以方便地适配不同的环境配置。
五、Docker Compose使用步骤
使用Docker Compose编排微服务的步骤
1、编写Compose文件:使用YAML语法编写一个Compose文件,定义每个微服务及其相关配置,如镜像、端口映射和环境变量等。
2、定义服务之间的依赖关系:使用depends_on关键字定义每个服务之间的依赖关系,以确保它们按正确的顺序启动。
3、运行Compose文件:使用docker-compose命令运行Compose文件,Docker Compose将会自动创建和管理所需的容器,并启动微服务。
4、监控和扩展:使用Docker Compose可以轻松监控和扩展微服务。通过添加新的服务实例或增加容器数量,可以根据应用程序的需求进行快速扩展。
六、Docker Compose编排微服务
6.1、实战-改造升级微服务project(常规部署微服务项目)
第一版(无mysql、redis数据库,无swagger-ui、无业务类):
改造升级:
1、建库建表
##建库
CREATE DATABASE demo1;##建表
CREATE TABLE `t_user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL DEFAULT '' COMMENT '用户名',
`password` varchar(50) NOT NULL DEFAULT '' COMMENT '密码',
`sex` tinyint(4) NOT NULL DEFAULT '0' COMMENT '性别 0=女 1=男 ',
`deleted` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '删除标志,默认0不删除,1删除',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户表'
2、启动mysql,redis,这里使用docker部署
docker run -d -p 3306:3306--name mysql-5.7-e MYSQL_ROOT_PASSWORD=123456-v /mysql/data:/var/lib/mysql mysql:5.7
docker run -d -p 6379:6379--privileged=true --name my-redis -v /apps/redis/redis.conf:/etc/redis/redis.conf -v /apps/redis/data:/data -d redis:7.0.9 redis-server /etc/redis/redis.conf
3、微服务project修改
swagger测试:http://http://localhost:你的微服务端口/swagger-ui.html
4、打包
源码及jar下载地址:https://download.csdn.net/download/qq_41840843/88332778
5、上传jar至/root/my-projects,并编写Dockerfile
vi Dockerfile,文件内容:
# 基础镜像使用java
FROM java:8# 作者
MAINTAINER zyl
# VOLUME 指定临时文件目录为/tmp,在主机/var/lib/docker目录下创建了一个临时文件并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名为zzyy_docker.jar
ADD demo2-0.0.1-SNAPSHOT.jar zyl_docker.jar
# 运行jar包
RUN bash -c 'touch /zyl_docker.jar'
ENTRYPOINT ["java","-jar","/zyl_docker.jar"]#暴露6001端口作为微服务
EXPOSE 6001
6、构建镜像
docker build -t zyl_docker:1.0.[root@zyl-server my-projects]# docker build -t zyl_docker:1.0 .
DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
BuildKit is currently disabled; enable it by removing the DOCKER_BUILDKIT=0
environment-variable.
Sending build context to Docker daemon 54.53MB
Step 1/7: FROM java:8---> d23bdf5b1b1b
Step 2/7: MAINTAINER zyl
---> Running in 0b94bf865db4
Removing intermediate container 0b94bf865db4
---> 7047fae445bc
Step 3/7: VOLUME /tmp
---> Running in 0c1f38b522a5
Removing intermediate container 0c1f38b522a5
---> 4a2014520455
Step 4/7: ADD demo2-0.0.1-SNAPSHOT.jar zyl_docker.jar
---> 32de0000fc4c
Step 5/7: RUN bash -c 'touch /zyl_docker.jar'---> Running in ec844531707c
Removing intermediate container ec844531707c
---> 15c50c6da487
Step 6/7: ENTRYPOINT ["java","-jar","/zyl_docker.jar"]---> Running in 1c76fb58c562
Removing intermediate container 1c76fb58c562
---> d3f63fdf430e
Step 7/7: EXPOSE 6001---> Running in e9ef4587e5ba
Removing intermediate container e9ef4587e5ba
---> 6a1e2c0365fd
Successfully built 6a1e2c0365fd
Successfully tagged zyl_docker:1.0[root@zyl-server my-projects]#
7、列出本地主机上的Docker镜像
[root@zyl-server my-projects]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
zyl_docker 1.0 6a1e2c0365fd 18 seconds ago 752MB
my-spring-boot-app latest 0e110c7ac812 12 days ago 490MB
mytomcat latest 7b01ac741538 13 days ago 838MB
8、运行 zyl_docker 镜像
报错:
[root@zyl-server my-projects]# docker run -d -p 6001:6001 6a1e2c0365fd 24f5aff8de0a4ebd2446e4f325dfff908e506e6280eb7b5ecd0ca1578cdc3833 docker: Error response from daemon: driver failed programming external connectivity on endpoint musing_ardinghelli (9d7e940750a0890604a234d2c1b3c7cc2dca2004a66184aee3120e2f9b7ce5ab): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 6001 -j DNAT --to-destination 172.17.0.4:6001 ! -i docker0: iptables: No chain/target/match by that name. (exit status 1)).
[root@zyl-server my-projects]#
解决:
在我们启动了Docker后,我们再对防火墙firewalld进行操作,就会发生上述报错。
**
systemctl restart docker 重启docker服务即可。
**
再次运行:
[root@zyl-server my-projects]# docker run -d -p 6379:6379 --privileged=true --name my-redis -v /apps/redis/redis.conf:/etc/redis/redis.conf -v /apps/redis/data:/data -d redis:7.0.9 redis-server /etc/redis/redis.conf
79a615e1c6f7fdc06a03a75969e00c49dc932c3f384ca4a7441b006107ae09da
[root@zyl-server my-projects]# docker run -d -p 3306:3306 --name mysql-5.7 -e MYSQL_ROOT_PASSWORD=123456 -v /mysql/data:/var/lib/mysql mysql:5.7 00412323842df42e7cab5da36c419d872b94f5a7b145c73886693fb1a2fe2f5e[root@zyl-server my-projects]# docker run -d -p 6001:6001 6a1e2c0365fd
6c6c33d4cf0800c9977750d00bb3a5614269136803a93c74d8710d74488495ee
[root@zyl-server my-projects]#
swagger测试:
**
不用Docker Compose,需要按顺序启动:
**
**1、单独的mysql容器
2、实例单独的redis容器实例
3、微服务project**
**
上面不用Docker Compose情况,有哪些问题?
**
**1、先后顺序要求固定,先mysql+redis才能微服务访问成功,需要确保mysql容器和redis容器在启动微服务之前已经处于运行状态。
2、多个run命令…,需要手动运行适当的docker run命令来启动每个容器。
3、容器间的启停或宕机,有可能导致IP地址对应的容器实例变化,映射出错要么生产IP写死(可以但是不推荐),要么通过服务调用,增加了管理和可伸缩性方面的复杂性。**
6.2、实战-改造升级微服务project(使用Docker Compose编排微服务)
1、第二次修改微服务工程project
修改数据库IP地址为服务名:
## spring.datasource.url=jdbc:mysql://192.168.234.10:3306/demo1?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.url=jdbc:mysql://mysql:3306/demo1?useUnicode=true&characterEncoding=utf-8&useSSL=false
## spring.redis.host=192.168.234.10
spring.redis.host=redis
2、重新打包项目,替换旧版demo2-0.0.1-SNAPSHOT.jar
1、删除旧版demo2-0.0.1-SNAPSHOT.jar
[root@zyl-server my-projects]# rm -rf demo2-0.0.1-SNAPSHOT.jar[root@zyl-server my-projects]#2、重新打包上传demo2-0.0.1-SNAPSHOT.jar
3、在/root/my-projects下,编写docker-compose.yml文件
文件内容:
version:"3"
services:
microService:
image: zyl_docker:1.0
container_name: demo2
ports:-"6001:6001"
volumes:-/app/microService:/data
networks:- zyl_network
depends_on:- redis
- mysql
redis:
image: redis:7.0.9
ports:-"6379:6379"
volumes:-/app/redis/redis.conf:/etc/redis/redis.conf
-/app/redis/data:/data
networks:- zyl_network
command: redis-server /etc/redis/redis.conf
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD:'123456'
MYSQL_ALLOW_EMPTY_PASSWORD:'no'
MYSQL_DATABASE:'demo1'
MYSQL_USER:'zyl'
MYSQL_PASSWORD:'123456'
ports:-"3306:3306"
volumes:-/app/mysql/db:/var/lib/mysql
-/app/mysql/conf/my.cnf:/etc/my.cnf
-/app/mysql/init:/docker-entrypoint-initdb.d
networks:- zyl_network
command:--default-authentication-plugin=mysql_native_password #解决外部无法访问
networks:
zyl_network:
文件解读:
这个配置文件。定义了三个服务:
microService、redis和mysql,并在zyl_network网络上进行通信。
1、microService服务使用自定义的zyl_docker:1.0镜像,容器名称为demo2,将主机的6001端口映射到容器的6001端口。将/app/demo2目录挂载到容器的/data目录。
2、redis服务使用redis:7.0.9镜像,将主机的6379端口映射到容器的6379端口。
还将/app/redis/redis.conf挂载到容器的/etc/redis/redis.conf,并将/app/redis/data挂载到容器的/data目录。
通过redis-server /etc/redis/redis.conf命令启动。
3、mysql服务使用mysql:5.7镜像,并设置了一些环境变量来配置MySQL实例。
将主机的3306端口映射到容器的3306端口。
将/app/mysql/db挂载到容器的/var/lib/mysql,并将/app/mysql/conf/my.cnf挂载到容器的/etc/my.cnf。
还有/app/mysql/init目录挂载到容器的/docker-entrypoint-initdb.d目录,以便在初始化数据库时运行脚本。
4、使用--default-authentication-plugin=mysql_native_password命令解决外部无法访问的问题。
5、最后,该配置文件定义了一个名为zyl_network的网络,用于连接这三个服务。
4、构建镜像
先删除之前运行的mysql容器、redis容器、微服务镜像和容器实例。
**
---这里是测试环境,非测试环境慎用该批量操作!!!!
**
[root@zyl-server my-projects]# docker stop $(docker ps -aq)
863016411ded
b5293f455952
0068f033e4e8
[root@zyl-server my-projects]# docker rm $(docker ps -aq)[root@zyl-server my-projects]# docker rmi zyl_docker:1.0
重新构建镜像:
docker build -t zyl_docker:1.0.
5、验证和显示Docker Compose配置文件的有效性
docker-compose config -q命令用于验证和显示Docker Compose配置文件的有效性,并以安静模式输出配置文件。它会检查配置文件的语法错误和格式问题,并验证所使用的镜像是否可用。
如果配置文件有效且正确,该命令不会产生任何输出。如果存在错误或问题,它将显示相关的错误消息。
[root@zyl-server my-projects]# docker-compose config -q[root@zyl-server my-projects]#
6、执行 docker-compose up 或者 执行 docker-compose up -d
使用docker-compose up命令启动这三个服务,这将在终端窗口中显示服务的日志输出。如果不希望在终端中查看日志输出,并且希望以后台模式启动服务,则可以使用docker-compose up -d命令。
这将以守护进程模式启动服务,并在后台运行。如果使用后台模式,则可以使用docker-compose logs命令来查看服务的日志输出。
1、当前没有正在运行的容器
[root@zyl-server my-projects]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@zyl-server my-projects]#2、执行docker-compose up -d
[root@zyl-server my-projects]# docker-compose up -d[+] Running 4/4
✔ Network my-projects_zyl_network Created 0.0s
✔ Container my-projects-mysql-1 Started 0.4s
✔ Container my-projects-redis-1 Started 0.4s
✔ Container demo2 Started 0.6s
[root@zyl-server my-projects]#
7、验证服务
1、列出Docker中的网络列表
[root@zyl-server my-projects]# docker network ls
NETWORK ID NAME DRIVER SCOPE
5a594d4c92e7 bridge bridge local
fe8aa9233f89 host host local
80480229149d my-projects_zyl_network bridge local
da1bb471897e mynetwork bridge local
7ae86ca33507 none null local
e1aea82ce159 redis-network bridge local
[root@zyl-server my-projects]#
2、再次列出正在运行的容器(mysql、redis、zyl_docker已启动运行)
[root@zyl-server my-projects]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d10f1034b7a7 zyl_docker:1.0"java -jar /zyl_dock…"4 seconds ago Up 3 seconds 0.0.0.0:6001->6001/tcp,:::6001->6001/tcp demo2
5a174e725026 redis:7.0.9"docker-entrypoint.s…"4 seconds ago Up 3 seconds 0.0.0.0:6379->6379/tcp,:::6379->6379/tcp my-projects-redis-1
009428bcad42 mysql:5.7"docker-entrypoint.s…"4 seconds ago Up 3 seconds 0.0.0.0:3306->3306/tcp,:::3306->3306/tcp,33060/tcp my-projects-mysql-1[root@zyl-server my-projects]#
3、进入mysql容器,新建库、建表
docker exec-it 009428bcad42 /bin/bash
[root@zyl-server my-projects]# docker exec -it 009428bcad42 /bin/bash
root@009428bcad42:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with;or \g.
Your MySQL connection idis2
Server version:5.7.36 MySQL Community Server (GPL)
Copyright (c)2000,2021, Oracle and/or its affiliates.
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'forhelp. Type '\c' to clear the current input statement.
mysql> show databases
->;+--------------------+| Database |+--------------------+| information_schema || demo1 || mysql || performance_schema || sys |+--------------------+5 rows inset(0.00 sec)
mysql> use demo1
Database changed
mysql> show tables;
Empty set(0.00 sec)
mysql>##建表:
CREATE TABLE `t_user` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '用户名',
`password` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '密码',
`sex` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '性别 0=女 1=男 ',
`deleted` TINYINT(4) UNSIGNED NOT NULL DEFAULT '0' COMMENT '删除标志,默认0不删除,1删除',
`update_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`)) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';##当前t_user为空表
mysql> select *from t_user;
Empty set(0.00 sec)
mysql>
8、swagger测试:http://http://ip:你的微服务端口/swagger-ui.html
mysql数据库验证:
mysql> select *from t_user;+----+----------+----------+-----+---------+---------------------+---------------------+|id| username | password | sex | deleted | update_time | create_time |+----+----------+----------+-----+---------+---------------------+---------------------+|1| zyl1 | 18746a |0|0|2023-09-1216:26:14|2023-09-1216:26:14||2| zyl2 | 434f8c |0|0|2023-09-1216:26:14|2023-09-1216:26:14||3| zyl3 | c8ce19 |0|0|2023-09-1216:26:14|2023-09-1216:26:14|+----+----------+----------+-----+---------+---------------------+---------------------+3 rows inset(0.00 sec)
mysql>
测试成功!!!
6.3、总结-Docker Compose的优点
在现代应用程序开发中,微服务架构已经成为一种非常流行的架构模式。然而,微服务的管理和部署通常会面临一些挑战,例如网络通信和协调。为了解决这些问题,Docker Compose作为一个强大的工具应运而生,它能够帮助开发者轻松地编排和管理微服务。
1、简化部署:Docker Compose允许您使用简单的YAML文件定义应用程序的组成部分,并将它们统一地部署为容器。不再需要手动操作每个容器,大大简化了部署过程。
2、管理复杂网络:微服务通常由多个容器组成,它们需要相互通信。Docker Compose可以自动创建和管理容器之间的网络,使得服务之间的通信变得更加便捷。
3、扩展性:Docker Compose允许您根据需要轻松地扩展微服务。通过添加新的服务实例或增加容器数量,可以快速响应应用程序的需求变化。
4、避免依赖冲突:不同的微服务可能依赖于不同版本的软件或库。Docker Compose可以确保每个服务都在自己的容器中运行,避免了依赖冲突的问题。
5、简化本地开发环境:使用Docker Compose可以轻松创建本地开发环境,不再需要为每个服务手动安装和配置依赖项。
**
Docker Compose为我们提供了一个简单且强大的工具,用于编排和管理微服务。它简化了部署过程,提高了扩展性,并避免了依赖冲突的问题。通过使用Docker Compose,我们可以更加轻松地构建、部署和管理基于微服务架构的应用程序。
**
七、Docker Compose常用命令
docker-compose -h # 查看帮助
docker-compose up # 启动所有docker-compose服务
docker-compose up -d # 启动所有docker-compose服务并后台运行
docker-compose down # 停止并删除容器、网络、卷、镜像。
docker-compose exec yml里面的服务id# 进入容器实例内部 docker-compose exec docker-compose.yml文件中写的服务id /bin/bash
docker-compose ps # 展示当前docker-compose编排过的运行的所有容器
docker-compose top # 展示当前docker-compose编排过的容器进程
docker-compose logs yml里面的服务id# 查看容器输出日志
dokcer-compose config # 检查配置
dokcer-compose config -q # 检查配置,有问题才有输出
docker-compose restart # 重启服务
docker-compose start # 启动服务
docker-compose stop # 停止服务
💖The End💖点点关注,收藏不迷路💖
版权归原作者 醉颜凉 所有, 如有侵权,请联系我们删除。