Files
Cloud-book/Docker/Docker容器编排.md
2025-08-27 17:10:05 +08:00

519 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Docker compose单机编排
## Docker Compose 简介
当在宿主机上启动多个容器时,手动操作会比较繁琐,且容易出错。在这种情况下,推荐使用 Docker 单机编排工具 **Docker Compose**。Docker Compose 是 Docker 官方提供的一个开源工具,用于管理和编排多个容器。它可以解决容器之间的依赖关系,简化容器的创建、启动和停止操作。
例如,启动一个 Nginx 前端服务时,可能需要调用后端的 Tomcat 服务,而 Tomcat 容器又依赖于数据库。在这种嵌套依赖关系中Docker Compose 可以按照正确的顺序启动这些容器确保每个容器在启动时都能正确依赖所需的其他容器。因此Docker Compose 完全可以替代 `docker run` 来创建和管理容器。
## Docker Compose 项目结构
Docker Compose 项目将所管理的容器分为三层,分别是:
- **工程Project**:工程是 Docker Compose 管理的最高层级,通常对应一个包含多个服务的应用场景。一个工程可以包含多个服务,这些服务通过 `docker-compose.yml` 文件进行定义。
- **服务Service**:服务是工程中的一个逻辑单元,通常对应一个容器模板。服务定义了容器的镜像、环境变量、端口映射等配置。一个服务可以启动多个容器实例。
- **容器Container**容器是服务的具体运行实例。Docker Compose 会根据服务的定义创建并管理容器。
通过这种分层结构Docker Compose 能够高效地管理和编排多个容器,简化复杂的容器依赖关系,提高开发和部署效率。
# 基础环境准备
## Docker compose部署
yum安装docker-compese
从 Docker 20.10 版本开始Docker Compose 被集成到了 Docker 中作为插件使用而不是独立的命令行工具所以说在20以后的版本中我们直接使用docker compose(中间用空格隔开)即可
```bash
# 旧版本中安装docker-compose的方式
[root@localhost ~]# yum install -y epel-release
[root@localhost ~]# yum install docker-compose.noarch -y
[root@localhost ~]# docker-compose version
docker-compose version 1.18.0, build 8dd22a9
docker-py version: 2.6.1
CPython version: 3.6.8
OpenSSL version: OpenSSL 1.0.2k-fips 26 Jan 2017
```
## 相关参数
```bash
# docker-compose --help
Define and run multi-container applications with Docker.
## Usage
```bash
docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...]
docker-compose -h|--help
```
### 选项说明
- `-f`, `--file FILE`:指定 Compose 模板文件,默认为 `docker-compose.yml`
- `-p`, `--project-name NAME`:指定项目名称,默认将使用当前所在目录名称作为项目名。
- `--verbose`:显示更多输出信息。
- `--log-level LEVEL`:定义日志级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL)。
- `--no-ansi`:不显示 ANSI 控制字符。
- `-v`, `--version`:显示版本。
### 命令选项
以下命令需要在 `docker-compose.yml``yaml` 文件所在目录里执行。
- `build`:构建或重新构建服务中定义的镜像。
- `bundle`:从当前 `docker-compose` 文件生成一个以 `<当前目录>` 为名称的 JSON 格式的 Docker Bundle 文件,用于离线部署。
- `config -q`:验证 Compose 文件格式是否正确,若无错误则不输出任何内容。
- `create`:创建服务所需的所有容器,但不启动它们。
- `down`:停止和删除所有容器、网络、卷,以及由 `docker-compose up` 创建的镜像(可选)。
- `events`:实时显示容器的日志事件,支持指定日志格式(如 JSON
- `exec`:在指定的容器中运行一个命令。
- `help`:显示指定命令的帮助信息。
- `images`:列出所有由 `docker-compose` 创建的镜像。
- `kill`:强制终止正在运行的容器。
- `logs`:查看容器的日志输出。
- `pause`:暂停服务中的所有容器。
- `port`:查看服务的端口映射情况。
- `ps`:列出所有由 `docker-compose` 管理的容器。
- `pull`:从镜像仓库拉取服务中定义的镜像。
- `push`:将服务中定义的镜像推送到镜像仓库。
- `restart`:重启服务中的所有容器。
- `rm`:删除所有已停止的容器。
- `run`:在指定服务中运行一个命令,创建一个临时容器。
- `scale`:设置指定服务运行的容器数量。
- `start`:启动已创建但未运行的服务。
- `stop`:停止正在运行的服务。
- `top`:显示正在运行的容器的进程信息。
- `unpause`:恢复之前暂停的服务。
- `up`:构建、创建并启动所有服务,如果服务已存在则重新启动。
### 示例 `docker-compose.yml` 文件
以下是一个详细的 `docker-compose.yml` 文件示例,包含注释和可能用到的所有指令。这个示例展示了如何定义一个包含多个服务(如 Nginx、Tomcat 和 MySQL的 Docker Compose 项目。
```yaml
# docker-compose.yml
# 定义版本,指定 Compose 文件的格式版本
version: '3.8'
# 定义服务
services:
# 定义 MySQL 服务
mysql:
# 使用的镜像名称
image: mysql:5.7
# 容器的名称
container_name: mysql_container
# 环境变量,用于设置 MySQL 的 root 密码
environment:
MYSQL_ROOT_PASSWORD: mypassword
MYSQL_DATABASE: mydb
# 持久化数据卷
volumes:
- mysql_data:/var/lib/mysql
# 端口映射,将宿主机的 3306 端口映射到容器的 3306 端口
ports:
- "3306:3306"
# 重启策略,始终重启
restart: always
# 网络配置,连接到默认网络
networks:
- my_network
# 定义 Tomcat 服务
tomcat:
# 使用的镜像名称
image: tomcat:9.0
# 容器的名称
container_name: tomcat_container
# 环境变量,设置 Tomcat 的一些配置
environment:
- CATALINA_OPTS=-Xms512M -Xmx1024M
# 持久化 Tomcat 的 webapps 目录
volumes:
- tomcat_webapps:/usr/local/tomcat/webapps
# 端口映射,将宿主机的 8080 端口映射到容器的 8080 端口
ports:
- "8080:8080"
# 依赖关系,确保 MySQL 服务先启动
depends_on:
- mysql
# 重启策略,始终重启
restart: always
# 网络配置,连接到默认网络
networks:
- my_network
# 定义 Nginx 服务
nginx:
# 使用的镜像名称
image: nginx:1.19
# 容器的名称
container_name: nginx_container
# 持久化 Nginx 的配置文件和静态资源
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./html:/usr/share/nginx/html
# 端口映射,将宿主机的 80 端口映射到容器的 80 端口
ports:
- "80:80"
# 依赖关系,确保 Tomcat 服务先启动
depends_on:
- tomcat
# 重启策略,始终重启
restart: always
# 网络配置,连接到默认网络
networks:
- my_network
# 定义卷
volumes:
# 定义 MySQL 数据卷
mysql_data:
driver: local
# 定义 Tomcat webapps 卷
tomcat_webapps:
driver: local
# 定义网络
networks:
# 定义默认网络
my_network:
driver: bridge
```
### 文件说明
1. **版本**
- `version: '3.8'`:指定 Compose 文件的格式版本。不同的版本支持不同的功能和语法。
2. **服务**
- `services`:定义项目中包含的所有服务。
- 每个服务(如 `mysql``tomcat``nginx`)都有自己的配置,包括:
- `image`:指定使用的 Docker 镜像。
- `container_name`:指定容器的名称。
- `environment`:设置环境变量。
- `volumes`:定义数据卷,用于持久化数据或挂载本地文件。
- `ports`:定义端口映射。
- `depends_on`:定义服务之间的依赖关系。
- `restart`:设置重启策略。
- `networks`:定义服务所属的网络。
3. **卷**
- `volumes`:定义数据卷,用于持久化数据。这里定义了两个卷:`mysql_data``tomcat_webapps`
4. **网络**
- `networks`:定义网络,用于服务之间的通信。这里定义了一个默认的桥接网络 `my_network`
### 可能用到的 Docker Compose 命令
以下是在 `docker-compose.yml` 文件所在目录中可以执行的常用命令:
- **`docker-compose up`**:构建、创建并启动所有服务。如果服务已存在,则重新启动。
- **`docker-compose down`**:停止并删除所有容器、网络、卷以及由 `docker-compose up` 创建的镜像(可选)。
- **`docker-compose build`**:构建或重新构建服务中定义的镜像。
- **`docker-compose create`**:创建服务所需的所有容器,但不启动它们。
- **`docker-compose start`**:启动已创建但未运行的服务。
- **`docker-compose stop`**:停止正在运行的服务。
- **`docker-compose restart`**:重启服务中的所有容器。
- **`docker-compose kill`**:强制终止正在运行的容器。
- **`docker-compose rm`**:删除所有已停止的容器。
- **`docker-compose logs`**:查看容器的日志输出。
- **`docker-compose exec`**:在指定的容器中运行一个命令。
- **`docker-compose ps`**:列出所有由 `docker-compose` 管理的容器。
- **`docker-compose config`**:验证 Compose 文件格式是否正确,若无错误则不输出任何内容。
- **`docker-compose bundle`**:从当前 `docker-compose` 文件生成一个 JSON 格式的 Docker Bundle 文件,用于离线部署。
- **`docker-compose pull`**:从镜像仓库拉取服务中定义的镜像。
- **`docker-compose push`**:将服务中定义的镜像推送到镜像仓库。
- **`docker-compose scale`**:设置指定服务运行的容器数量。
# 实战案例
## 启动单个容器
一、编写docker-compose文件
```yaml
[root@localhost ~]# mkdir -pv docker-compose/nginx
[root@localhost ~]# cd docker-compose/nginx
[root@localhost nginx]# pwd
/root/docker-compose/nginx
[root@localhost nginx]# vim docker-compose.yml
# docker-compose.yml
services:
nginx:
image: nginx
container_name: nginx_web1
restart: always
ports:
- "80:80"
volumes:
- /data/web:/usr/share/nginx/html
```
二、启动容器
```bash
[root@localhost nginx]# docker compose up -d
[+] Running 2/2
✔ Network nginx_default Created 0.0s
✔ Container nginx_web1 Started 0.2s
[root@localhost nginx]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
09d091a0c1a1 nginx "/docker-entrypoint.…" 29 seconds ago Up 28 seconds 0.0.0.0:80->80/tcp, [::]:80->80/tcp nginx_web1
# 不指定网络的话会默认创建一个类型为bridge的网络
[root@localhost nginx]# docker network ls
NETWORK ID NAME DRIVER SCOPE
36f9c2f8e090 bridge bridge local
93ffe4510dd0 host host local
d0456365c64d nginx_default bridge local
61f0d0d9b051 none null local
```
三、访问测试
## 启动多个容器
一、编辑docker-compose文件
```bash
[root@localhost docker]# cat docker-compose.yml
service-nginx:
image: nginx
container_name: nginx_web1
ports:
- "80:80"
service-tomcat:
image: tomcat
container_name: tomcat_web1
ports:
- "8080:8080"
[root@localhost docker]# docker-compose up -d
nginx_web1 /docker-entrypoint.sh ngin ... Up 0.0.0.0:80->80/tcp,:::80->80/tcp
tomcat_web1 catalina.sh run Up 0.0.0.0:8080->8080/tcp,:::8080-
>8080/tcp
```
## 定义数据卷挂载
- 创建数据卷目录和文件
```bash
[root@localhost docker]# mkdir -p /data/nginx
[root@localhost docker]# echo 'docker nginx' > /data/nginx/index.html
```
- 编辑配置文件
```bash
[root@localhost docker]# cat docker-compose.yml
service-nginx:
image: nginx
container_name: nginx_web1
volumes:
- /data/nginx/:/usr/share/nginx/html
ports:
- "80:80"
service-tomcat:
image: tomcat
container_name: tomcat_web1
ports:
- "8080:8080"
```
- 访问测试
```bash
[root@localhost docker]# curl localhost
docker nginx
```
# Docker Compose部署LNMP实战
## 部署LNMP环境
- 使用docker-compose实现编排nginx+phpfpm+mysql容器
- 部署一个博客系统
- 首先编写一个如下的配置文件
```yaml
services:
web:
image: nginx:latest
restart: always
ports:
- 80:80
volumes:
- /data/lnmp/nginx/conf.d:/etc/nginx/conf.d
- /data/lnmp/nginx/html:/usr/share/nginx/html
- /data/lnmp/nginx/log:/var/log/nginx
depends_on:
- php
- mysql
networks:
- lnmp-network
php:
image: php:7.4-fpm
restart: always
volumes:
- /data/lnmp/nginx/html:/usr/share/nginx/html
networks:
- lnmp-network
depends_on:
- mysql
mysql:
image: mysql:5.7
restart: always
volumes:
- /data/lnmp/dbdata:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: "123456"
MYSQL_DATABASE: login
networks:
- lnmp-network
networks:
lnmp-network:
driver: bridge
volumes:
dbdata: null
```
运行docker-compose.yml
```bash
[root@localhost lnmp]# docker compose up -d
[root@localhost lnmp]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
825b8630de47 nginx:latest "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp, [::]:80->80/tcp lnmp-web-1
d1d6339ba0d7 lnmp-php "docker-php-entrypoi…" 4 minutes ago Up 4 minutes 9000/tcp lnmp-php-1
109672c0b1f0 mysql:5.7 "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 3306/tcp, 33060/tcp lnmp-mysql-1
```
`/data/lnmp/nginx/conf.d/default.conf` 中写入nginx 的配置文件
```shell
server {
listen 80;
root /usr/share/nginx/html;
location / {
index index.php index.html;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
```
准备探针测试
`/data/lnmp/nginx/html/info.php` 中准备php探针
```shell
<?php
phpinfo();
?>
```
测试数据库连接
`/data/lnmp/nginx/html/mysql.php`中准备php探针
```shell
<?php
$dbhost = "mysql";
$dbuser = "root";
$dbpass = "123456";
$db = "login";
$conn = mysqli_connect($dbhost, $dbuser, $dbpass, $db) or exit("数据库连接失败!");
echo "数据库连接成功";
?>
```
访问测试后发现连接mysql报错提示找不到mysqli_connect()看来是官方构建的php没有mysqli模块
所以我们需要定制带有mysqli模块的php编写如下dockerfile
```shell
FROM php:7.4-fpm
ENV TZ=Asia/Shanghai
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \
&& sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list \
&& sed -i -e 's|security.debian.org/\? |security.debian.org/debian-security |g' \
-e 's|security.debian.org|mirrors.ustc.edu.cn|g' \
-e 's|deb.debian.org/debian-security|mirrors.ustc.edu.cn/debian-security|g' \
/etc/apt/sources.list \
&& apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
&& docker-php-ext-configure gd -with-freetype -with-jpeg \
&& docker-php-ext-install -j$(nproc) gd mysqli && docker-php-ext-enable mysqli
```
然后修改 docker-compose.yml 文件如下
```yaml
# docker-compose build lnmp
services:
web:
image: nginx:latest
restart: always
ports:
- 80:80
volumes:
- /data/lnmp/nginx/conf.d:/etc/nginx/conf.d
- /data/lnmp/nginx/html:/usr/share/nginx/html
- /data/lnmp/nginx/log:/var/log/nginx
depends_on:
- php
- mysql
networks:
- lnmp-network
php:
# image: dockerfile:php:7.4-fpm
# 这里来让compose自动构建指定dockerfile的文件位置即可
build:
context: .
dockerfile: dockerfile
restart: always
volumes:
- /data/lnmp/nginx/html:/usr/share/nginx/html
networks:
- lnmp-network
depends_on:
- mysql
mysql:
image: mysql:5.7
restart: always
volumes:
- /data/lnmp/dbdata:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: "123456"
MYSQL_DATABASE: login
networks:
- lnmp-network
networks:
lnmp-network:
driver: bridge
volumes:
dbdata: null
```
测试验证
```shell
[root@localhost lnmp]# docker compose up -d
[root@localhost lnmp]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
825b8630de47 nginx:latest "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp, [::]:80->80/tcp lnmp-web-1
d1d6339ba0d7 lnmp-php "docker-php-entrypoi…" 4 minutes ago Up 4 minutes 9000/tcp lnmp-php-1
109672c0b1f0 mysql:5.7 "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 3306/tcp, 33060/tcp lnmp-mysql-1
```