一、Compose 介绍
1.1 基础知识
思考: 现有 docker 进行项目部署存在的问题?
对于现代应用来说,大多都是通过很多的微服务互相协同组成的一个完整应用。
例如,订单管理、用户管理、品类管理、缓存服务、数据库服务等,它们构成了一个电商平台的应用。
而部署和管理大量的服务容器是一件非常繁琐的事情。而 Docker Compose 就是解决这类问题的。
docker 容器提供了一种封装格式,可以将应用和其运行环境封装在一起,但是在线上实践过程中,应用和应用之间难免要产生依赖,一个上游的应用,可能会依赖于下游的一个或者几个应用给其提供数据。
正所谓一个好汉三个帮,现实情况中,一个服务部署完成之后,对外不产生依赖的情况还是比较少的,但是 docker 在开始设计的时候没有过多考虑到容器之间依赖关系的处理。
1、为了完成一个完整项目势必用到N多个容器(一个容器只运行一个进程)配合完成项目中业务开发。
一旦引入N多个容器,容器之间就会形成某种依赖,也就意味某个容器或某些容器的运行需要其他容器优先启动之后才能正常运行。
容器的编排显得至关重要,容器的运行一定要有先后顺序。
2、现在这种方式使用容器,没有办法站在项目的角度将一个项目用到的一组容器划分到一起,日后难点在于项目的多服务器部署。
比如项目在当前服务器上运行成功,需要将项目再部署到另一台服务器上,但我们不清楚哪组容器是项目引用的,哪组容器是别的引用的。
Docker Compose 是一个需要在 Docker 主机上进行安装的 Docker 容器编排外部工具。
其并不是通过脚本或各种冗长的 Docker 命令来将应用组件组织起来,而是通过一个声明式的配置文件描述整个应用,然后通过一条命令完成应用部署。
部署成功后,还可通过一系列简单命令实现对其完整生命周期的管理。
1.2 Compose 安装
注意:只有 Linux 平台上在安装docker时没有安装docker-compose,windows、macos平台安装docker时会自动安装docker-compose。
下载 docker-compose文件:
官网下载地址:
wget https://github.com/docker/compose/releases/download/v2.36.2/docker-compose-linux-x86_64
更改名字将其放入进bin目录中,使用时就不用全路径
mv docker-compose-linux-x86_64 docker-compose
mv docker-compose /usr/local/bin/docker-compose
赋予执行权限:
sudo chmod +x /usr/local/bin/docker-compose
使用命令 docker-compose -v 查看 compose 版本:

1.3 Compose 文件内容
文件简介
Docker Compose 使用 YAML 文件来定义服务。官方推荐的默认文件名为 compose.yml ,但同时也支持 docker-compose.yml。
由于一个 compose 文件中定义的为一个项目的所有服务,所以一般为在创建 compose 文件之前先新建一个目录,目录名称一般为项目名称,然后再将项目所需的所有镜像、微服务的 Dockerfile 放入该目录,并在该目录中新建 compose 文件。
docker-compose.yml
│
├── version: '指定文件格式版本'
│
├── services:
│ │
│ ├── service_name_1:
│ │ ├── build: ./dir_or_dockerfile_details
│ │ ├── image: "镜像名或路径"
│ │ ├── ports:
│ │ │ └── "主机端口:容器端口"
│ │ ├── networks:
│ │ │ └── network_name
│ │ ├── volumes:
│ │ │ └── "/宿主机路径:/容器内路径"
│ │ ├── environment:
│ │ │ └── ["环境变量名=值", ...]
│ │ └── deploy: (仅适用于 Docker Swarm)
│ │ ├── replicas: 数量
│ │ └── mode: 设置模式(global/replicated)
│ │
│ └── service_name_2:
│
├── networks:
│ ├── network_name_1:
│ └── network_name_2:
│
└── volumes:
├── volume_name_1:
└── volume_name_2:
version
用于指定 Docker Compose 文件格式的版本。不同的版本可能支持不同的特性集。
选择合适的版本可以确保使用到特定的功能或语法。
用于指定当前 docker-compose 文件遵循的规范版本。这决定了哪些功能和配置选项是可用的。
version: '3'
version: '2.4'
从 Docker Compose v2 开始(尤其是 v2.20+),官方已经 不再推荐使用 version:
字段。
因为这个字段现在已经被 Compose CLI 插件自动处理,不再是必须的了。
services
定义了应用服务的集合。
每个服务都代表了一个容器,这些服务可以通过 Docker Compose 来管理它们的生命周期、网络、存储等。
用于定义一个或多个服务,每个服务对应于一个独立运行的容器。
services:
web:
image: "nginx"
services:
db:
build: ./dir
build
用于指定一个 Dockerfile 的路径。
而该 Dockerfile 则是用于创建当前服务镜像的。
这个路径可以是以斜杠(/)开头的绝对路径,也可以是相对于当前 compose 文件的、以点(.)号开头的相对路径。
如果 Dockerfile 文件名不是默认名称,则需要通过 build 下的 context 属性指定路径,dockerfile 属性指定文件名。
build: /test
build:context: /test
dockerfile: a.dockerfile
image
用于指定要使用的 Docker 镜像。
这个镜像可以是从本地获取的,也可以是从远程仓库拉取的。
使用已经构建好的镜像能够快速部署服务。
如果使用现成的镜像(通过
image
指定),而不需要从 Dockerfile 构建镜像,那么不需要写build
这个属性。
image: "ubuntu"
image: "myregistry.com/myapp/myimage:v1"
ports
用于映射端口,使得容器内的服务可以通过主机访问。
这种映射允许外部流量到达容器内部的服务。
ports: - "5000:5000"
ports:
- "8000-8010:9000-9010"
networks
用于定义服务所属的网络。
这允许不同的服务相互通信,同时也控制了服务之间的可见性和隔离性。
networks:
some-network
networks:front-tier
back-tier
volumes
用于挂载路径作为卷,使得数据持久化或者在不同容器间共享数据。
这种方式对于保存数据库或者其他需要长期保存的数据特别有用。
volumes:
/var/lib/mysql:/data
volumes:./cache:/tmp/cache
environment
用于设置环境变量,可以用来配置应用程序的行为而不必修改代码。
这对于根据不同的部署环境调整配置非常有用。
environment:
- MYSQL_ROOT_PASSWORD=my-secret-pw
environment:POSTGRES_USER: user
POSTGRES_PASSWORD: pass
deploy
仅适用于使用 docker stack deploy
命令的情况,它配置了服务如何在 swarm 集群中部署。
这包括副本数量、更新策略等高级配置。
deploy:
replicas: 5
deploy:mode: global
depends_on
它确保某些服务在其他服务启动之前已经被启动。
启动顺序:Docker Compose 会按照 depends_on
中指定的顺序来启动服务。
不等待就绪状态:仅保证被依赖的服务先启动,但不会等待该服务的应用程序完全就绪(如数据库服务完全初始化完成)。
这意味着如果一个服务依赖于另一个服务的数据准备情况,需要使用其他机制来确保服务间的正确性,比如健康检查或自定义脚本。
version: '3'
services:
web:
build: .
depends_on:
- db
ports:
- "80:80"
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: example
volumes
volumes
元素用于定义 Docker 卷。
使用卷可以让你的数据持久化,并且可以在多个容器之间共享或重用这些数据。
此外,卷还可以帮助你绕过 Union File System 的文件系统层限制,从而提高性能。
version: '3'
services:
db:
image: "mysql:5.7"
volumes:
- db-data:/var/lib/mysql
volumes:
db-data: # 命名卷
这里我们定义了一个名为 db-data
的命名卷,并将其挂载到容器的 /var/lib/mysql
路径下。
networks
networks
元素用于定义自定义网络,使得服务能够通过网络相互通信。
默认情况下,Docker Compose 自动创建一个网络来允许你的服务互相通信,在这种情况下,所有服务都将加入到默认网络中,并且可以通过服务名称相互访问。
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
networks:
default:
但是有时可能想要更多控制或者创建多个隔离的网络。
version: '3'
services:
proxy:
build: ./proxy
networks:
- frontend
app:
build: ./app
networks:
frontend
backend
db:
image: "mysql:5.7"
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
1.4 Compose 命令
常用命令
创建一个test文件夹,在里面vim一个docker-compose.yml文件
services:
web1:
image: nginx:latest
container_name: web1
ports:
- "8080:80"
volumes:
- ./web1/html:/usr/share/nginx/html
networks:
- app-network
web2:
image: nginx:latest
container_name: web2
ports:
- "8081:80"
volumes:
- ./web2/html:/usr/share/nginx/html
networks:
- app-network
db1:
image: mysql:8.0
container_name: db1
environment:
MYSQL_ROOT_PASSWORD: 123456
ports:
- "3306:3306"
volumes:
- db1_data:/var/lib/mysql
networks:
- app-network
db2:
image: mysql:8.0
container_name: db2
environment:
MYSQL_ROOT_PASSWORD: 123456
ports:
- "3307:3306"
volumes:
- db2_data:/var/lib/mysql
networks:
- app-network
volumes:
db1_data:
db2_data:
networks:
app-network:
driver: bridge
创建并启动容器
docker-compose up
使用 docker-compose.yml
文件中的配置创建并启动所有服务。加上 -d
参数可以在后台运行。
docker-compose up -d
停止服务
docker-compose stop
停止正在运行的服务而不删除它们。
停止并移除容器、网络
docker-compose down
停止并移除由 docker-compose.yml
定义的所有容器、网络以及默认情况下不会移除卷。
查看服务状态
docker-compose ps
显示由 docker-compose.yml
文件定义的所有服务的状态。
列出镜像
docker-compose images
列出 Compose 文件中服务使用的镜像。
日志相关命令
docker-compose run [SERVICE] [COMMAND]
查看服务日志
docker-compose logs <服务名>
显示由 docker-compose.yml
文件定义的所有服务的日志输出。加上 -f
参数可以实时跟踪日志更新。
docker-compose logs -f
运行一次性命令
docker-compose run [SERVICE] [COMMAND]
在服务的容器内执行一个命令。这对于调试非常有用。
docker-compose run web bash
网络与卷管理
创建网络
docker-compose create
只创建网络和卷,但不启动服务。
重启服务
docker-compose restart
高级命令
拉取服务镜像
docker-compose pull
拉取服务依赖的所有镜像。
执行命令
docker-compose exec [SERVICE] [COMMAND]
进入正在运行的服务容器,并执行命令。这类似于 docker exec
命令。
示例:
docker-compose exec web sh
检查配置
docker-compose config
验证并查看 docker-compose.yml
文件的有效配置。
指定文件:使用 -f
参数指定不同的 Compose 文件名。
docker-compose -f alternate-compose.yml up
1.5 配置一主两从架构
services:
master:
image: mysql:8.0
container_name: mysql_master
environment:
MYSQL_ROOT_PASSWORD: 123456
volumes:
- /data/mysql/master/conf/my.cnf:/etc/my.cnf
- /data/mysql/master/data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- mysql-network
slave1:
image: mysql:8.0
container_name: mysql_slave1
environment:
MYSQL_ROOT_PASSWORD: 123456
volumes:
- /data/mysql/slave1/conf/my.cnf:/etc/my.cnf
- /data/mysql/slave1/data:/var/lib/mysql
ports:
- "3307:3306"
depends_on:
- master
networks:
- mysql-network
slave2:
image: mysql:8.0
container_name: mysql_slave2
environment:
MYSQL_ROOT_PASSWORD: 123456
volumes:
- /data/mysql/slave2/conf/my.cnf:/etc/my.cnf
- /data/mysql/slave2/data:/var/lib/mysql
ports:
- "3308:3306"
depends_on:
- master
networks:
- mysql-network
networks:
mysql-network:
driver: bridge
1.6 配置nginx与后端集群
我们使用 Docker Compose 来实现以下架构:
-
1 个 Nginx 容器:负责反向代理和负载均衡;
-
3 个 Java 后端服务容器(
backend1
,backend2
,backend3
); -
所有服务都在同一个自定义 Docker 网络中通信;
-
不需要构建自定义 Nginx 镜像,直接使用官方镜像 + 挂载配置文件;
-
使用
openjdk:8
构建后端服务镜像。
文件结构:
test/
├──
docker-compose.yml
├── dockerfile
├── html
├── java
│ └── msg.jar
└── nginx
└── default.conf
可以先将80端口的防火墙打开或者直接关闭防火墙
第一步:将前端压缩包解压到html文件夹中
unzip html.zip -d ./html
第二步:创建文件夹java,进入 java 文件夹
将后端文件放到 java 文件夹中
第三步:创建nginx文件夹,进入nginx文件夹
vim default.comf
-- 放入下面的
upstream tomcatList {
server backend1:8081 weight=1;
server backend2:8081 weight=1;
server backend3:8081 weight=1;
}
server {
listen 80;
server_name localhost;
location / {
root /etc/nginx/html/;
index index.html index.htm;
}
location ~^/api/ {
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://tomcatList;
proxy_redirect default;
}
}
第四步:在 test 文件夹,编辑vim dockerfile
FROM openjdk:8-jdk-alpine
WORKDIR /app
COPY ./java/msg.jar app.jar
-- 这句可以删掉
EXPOSE 8081
ENTRYPOINT ["java", "-jar", "app.jar"]
第五步:编写docker-compose.yml,在test文件夹中
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
volumes:
- /test/nginx/default.conf:/etc/nginx/conf.d/default.conf
- /test/html:/etc/nginx/html
depends_on:
- backend1
- backend2
- backend3
networks:
- app-network
backend1:
build:
context: .
dockerfile: dockerfile
container_name: backend1
networks:
- app-network
backend2:
build:
context: .
dockerfile: dockerfile
container_name: backend2
networks:
- app-network
backend3:
build:
context: .
dockerfile: dockerfile
container_name: backend3
networks:
- app-network
networks:
app-network:
driver: bridge
第六步:启动容器
docker-compose up -d
第七步:查看创建的网络
docker network ls

第八步:查看该网络的详情信息
docker inspect 【网络name】

第九步:访问nginx
curl 【ip】

1.7 compose重启策略
Docker Compose 支持几种不同的重启策略,可以根据的需求选择合适的策略。
常用的重启策略
-
no:默认策略,不自动重启容器。
-
always:无论退出状态如何,总是尝试重启容器。如果 Docker 守护进程重启,也会尝试重启容器。
-
on-failure:仅当容器以非零退出代码终止时才重启容器。可以指定最大重试次数,例如
on-failure:5
。 -
unless-stopped:总是重启容器,除非容器被手动停止(使用
docker stop
或通过 Docker API 停止)。services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
volumes:
- /data/project/nginx/default.conf:/etc/nginx/conf.d/default.conf
- /data/project/html:/etc/nginx/html
depends_on:
- backend1
- backend2
- backend3
networks:
- app-network
restart: always # 设置重启策略backend1: build: context: . dockerfile: java.Dockerfile container_name: backend1 expose: - "8081" networks: - app-network restart: unless-stopped # 另一种重启策略 backend2: build: context: . dockerfile: java.Dockerfile container_name: backend2 expose: - "8081" networks: - app-network restart: unless-stopped backend3: build: context: . dockerfile: java.Dockerfile container_name: backend3 expose: - "8081" networks: - app-network restart: unless-stopped
networks:
app-network:
driver: bridge