# 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 ...] [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 ``` 测试数据库连接 在`/data/lnmp/nginx/html/mysql.php`中准备php探针 ```shell ``` 访问测试后发现,连接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 ```