Docker Compose全解析:概念、安装、命令与文件指令解析

笔记哥 / 04-19 / 19点赞 / 0评论 / 613阅读
## 什么是Docker Compose Docker Compose 是 Docker 的一个编排管理工具,它允许你使用一个 YAML 文件来配置应用程序的服务。通过这个文件,你可以定义多个容器如何通过网络相互连接,以及如何配置它们的环境变量、卷挂载、端口映射等。这使得在单个主机上运行复杂的多容器应用程序变得非常简单和直观。 Docker Compose主要解决了`docker run`指令以及`docker build`后需要手动运行docker run的问题。 ## Docker Compose主要概念 - 服务(Services):在 Docker Compose 文件中,一个服务通常指的是一个容器。你可以定义多个服务,每个服务都运行一个或多个容器实例。例如,你的应用程序可能包含一个 Web 服务和一个数据库服务。 - 网络(Networks):Docker Compose 可以创建和管理 Docker 网络,以便服务之间可以相互通信。默认情况下,Docker Compose 会为每个服务创建一个网络,但你也可以定义跨多个服务的自定义网络。 - 卷(Volumes):卷是 Docker 中用于持久化数据的一种机制。在 Docker Compose 中,你可以定义卷,并将卷挂载到容器内的特定路径上,这样即使容器被删除,数据也不会丢失。 - 环境变量(Environment Variables):你可以为服务定义环境变量,这些变量可以在容器内部被读取和使用。这对于配置应用程序的设置非常有用。 - 依赖(Dependencies):你可以在 Docker Compose 文件中定义服务的依赖关系,确保在启动服务时按照正确的顺序进行。例如,你可能希望先启动数据库服务,然后再启动依赖于数据库的服务。 ## 安装Docker Compose Docker Compose项目地址:![](https://cdn.res.knowhub.vip/c/2504/20/330b6da4?GyAAAES3eZ77%2fc5MMiImuUohpGKNlKoNWFv5h8GPST%2fx4LzFDg%3d%3d) 安装环境信息 | IP | 系统 | 规格 | | --- | --- | --- | | 10.0.0.10 | Ubuntu22.04 | 2c4g | **安装前置准备:需要安装Docker** 安装步骤: ```csharp # 下载Docker Compose [root@lb ~]# wget [root@lb ~]# ll docker-compose-linux-x86_64 -rw-r--r-- 1 root root 73664588 Apr 19 14:42 docker-compose-linux-x86_64 # 移动至/usr/bin/docker-compose [root@lb ~]# mv docker-compose-linux-x86_64 /usr/bin/docker-compose # 授予权限 [root@lb ~]# chmod +x /usr/bin/docker-compose [root@lb ~]# ll /usr/bin/docker-compose -rwxr-xr-x 1 root root 73664588 Apr 19 14:42 /usr/bin/docker-compose* # 检查 [root@lb ~]# docker-compose version Docker Compose version v2.35.0 ``` ## Docker Compose常用命令 Docker Compose的命令非常多,下面列举几个常用的,后文遇到新的命令继续讲解 ### 容器相关 - docker-compose up -d:相当于`docker run -d`,创建并后台运行容器 - docker-compose ps:查看容器运行情况,只有`-q`选项 - docker-compose down:删除容器,删除所有容器的所有内容(网络、数据卷) - docker-compose start:启动容器 - docker-compose stop:容器关闭 - docker-compose restart:重启容器 - docker-compose top:查看容器进程信息 - docker-compose logs:查看容器日志 - docker-compose rm:删除容器 - docker-compose exec:进入容器 ### 镜像相关 - docker-compose pull:拉取服务的镜像 - docker-compose push:推送服务的镜像 - docker-compose build:构建服务镜像 ## Docker Compose文件中常用指令 官网文章:![](https://cdn.res.knowhub.vip/c/2504/20/d5639f8e?GzcAAET1PC%2f6%2b96uQmCLaUMUuQgqeaLrMf6PbIA5s5pz6b3wkx8PuhToJzxV%2btwCahA%3d) Docker Compose文件是一个yaml文件,且运行docker-compose命令时,所在的目录下必须有一个`docker-compose.yaml`或者`compose.yaml`文件。 ### services Compose 文件必须将services设置为顶级元素,`services`指定运行容器的相关信息,可以理解成`docker run`指令的集合 示例: ```csharp # docker-compose文件 [root@lb ~/services]# cat docker-compose.yaml services: # 服务名称 web: image: nginx:latest ports: - "8080:80" # 运行容器 [root@lb ~/services]# docker-compose up -d [+] Running 1/1 ✔ Container services-web-1 Started # 查看运行的容器 [root@lb ~/services]# docker-compose ps NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS services-web-1 nginx:latest "/docker-entrypoint.…" web About a minute ago Up About a minute 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp ``` ### image 指定容器运行时的基础镜像 ### ports 指定容器运行时的端口号,可以写多个 ### container\_name 指定容器的名字,没有`container_name`标签时,会以`services-[services_name]-[services_num]`为容器名称 示例: ```csharp [root@lb ~/container_name]# cat docker-compose.yaml services: web: image: nginx:latest # 指定容器名称 container_name: nginx_1 ports: - "8081:80" [root@lb ~/container_name]# docker-compose up -d [+] Running 2/2 ✔ Network container_name_default Created 0.1s ✔ Container nginx_1 Started 0.2s [root@lb ~/container_name]# docker-compose ps -a NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS nginx_1 nginx:latest "/docker-entrypoint.…" web 5 seconds ago Up 5 seconds 0.0.0.0:8081->80/tcp, [::]:8081->80/tcp ``` ### build 运行Dockerfile,构建镜像使用,有几个子标签 #### context 指定Dockerfile所在的目录 #### dockerfile 指定Dockerfile的文件名,同`docker build -f`指令,该指令可以不写,默认是Dockerfile 示例: ```csharp [root@lb ~/build]# cat compose.yaml services: zrlog: container_name: zrlog # build指令使用 build: context: ./zrlog dockerfile: Dockerfile ports: - "8082:8080" # 构建镜像 [root@lb ~/build]# docker-compose build Compose can now delegate builds to bake for better performance. To do so, set COMPOSE_BAKE=true. [+] Building 6.5s (9/9) FINISHED docker:default => [zrlog internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 409B 0.0s => [zrlog internal] load metadata for docker.io/library/tomcat:9.0.87-jdk8-corretto 6.3s => [zrlog internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [zrlog internal] load build context 0.1s => => transferring context: 10.80MB 0.1s => [zrlog 1/3] FROM docker.io/library/tomcat:9.0.87-jdk8-corretto@sha256:6928733a4f4c15d61c45a14b0197fe9a160f49f6f13b1b0b06310561cb320ef0 => => writing image sha256:0d6bbaa1db8bf9d30e976c17f2991aca20e6b6e070be646b85240e1ec0ffdc71 0.0s => => naming to docker.io/library/build-zrlog 0.0s => [zrlog] resolving provenance for metadata file 0.0s [+] Building 1/1 ✔ zrlog Built 0.0s # 启动镜像 [root@lb ~/build]# docker-compose up -d [+] Running 2/2 ✔ Network build_default Created 0.1s ✔ Container build-zrlog-1 Started [root@lb ~/build]# docker-compose ps NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS zrlog build-zrlog "catalina.sh run" zrlog About a minute ago Up About a minute (healthy) 0.0.0.0:8082->8080/tcp, [::]:8082->8080/tcp ``` ### environment `docker run -e`选项,指定容器运行后的环境变量 示例: ```csharp [root@lb ~/environment]# cat compose.yaml services: db: image: mysql:5.7 container_name: mysql_db ports: - "3306:3306" environment: # 指定MySQL root的密码 - "MYSQL_ROOT_PASSWORD=root123" # 指定创建一个zrlog的数据库 - "MYSQL_DATABASE=zrlog" # 运行 [root@lb ~/environment]# docker-compose up -d [+] Running 2/2 ✔ Network environment_default Created 0.1s ✔ Container mysql_db Started # check [root@lb ~/environment]# docker-compose ps -a NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS mysql_db mysql:5.7 "docker-entrypoint.s…" db 14 seconds ago Up 14 seconds 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp ``` ### restart 指定容器的重启方式,和`docker run --restart`选项一致 重启方式: - always:自动重启 - unless-stopped:只在容器关闭,停止的时候重启 - on-failure:只在失败的时候重启 示例: ```csharp services: db: # 指定重启策略 restart: always image: mysql:5.7 container_name: mysql_db ports: - "3306:3306" environment: # 指定MySQL root的密码 - "MYSQL_ROOT_PASSWORD=root123" # 指定创建一个zrlog的数据库 - "MYSQL_DATABASE=zrlog" ``` ### volumes 官网文章:![](https://cdn.res.knowhub.vip/c/2504/20/f08dc80d?GzYAAET1PC%2f6%2b96pEKgY0hCNoCp0Peq92xOQZR6zrPNc%2bPHjgcsI09xyhtIG8TXepAM%3d) volumes指令在Compose文件中有两个作用,作为顶级元素时,volume会创建一个数据卷,作为子级元素时,会为容器挂载数据卷。 示例: ```csharp [root@lb ~/volumes]# cat compose.yaml services: db: # 指定重启策略 restart: always image: mysql:5.7 container_name: mysql_db_1 ports: - "3307:3306" environment: # 指定MySQL root的密码 - "MYSQL_ROOT_PASSWORD=root123" # 指定创建一个zrlog的数据库 - "MYSQL_DATABASE=zrlog" volumes: - mysql_data:/var/lib/mysql # 创建mysql_data的数据卷 volumes: mysql_data: # 启动容器 [root@lb ~/volumes]# docker-compose up -d [+] Running 1/1 ✔ Container mysql_db_1 Started # 检查 0.3s [root@lb ~/volumes]# docker-compose ps -a NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS mysql_db_1 mysql:5.7 "docker-entrypoint.s…" db 4 seconds ago Up 4 seconds 33060/tcp, 0.0.0.0:3307->3306/tcp, [::]:3307->3306/tcp # 检查数据卷 [root@lb ~/volumes]# docker inspect mysql_data [ { "CreatedAt": "2025-04-12T15:42:17+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/mysql_data/_data", "Name": "mysql_data", "Options": null, "Scope": "local" } ] ``` #### 当需要挂载到本机宿主机时,仅使用次级元素的volumes即可 示例: ```csharp services: web: image: nginx:latest volumes: - ./html:/usr/share/nginx/html ``` #### 可以使用外部存储卷 示例: ```csharp services: web: image: nginx:latest volumes: - web_data:/usr/share/nginx/html volumes: web_data: #external指定此卷已存在于平台上,并且其生命周期由应用程序之外的生命周期管理。如果卷不存在,Compose 将不会创建该卷并返回错误。 external: true ``` ### healthcheck `healthcheck`用于定义服务的健康检查机制。通过健康检查,可以确保容器在启动后能够正常运行,并且在容器不可用时自动重启或重新调度. 其子元素有: - test:定义健康检查的命令。可以是一个命令或一个脚本。 - interval:两次健康检查之间的间隔时间(默认单位为秒)。 - timeout:单次健康检查的超时时间。 - retries:健康检查失败后重试的次数。 - start\_period:容器启动后开始健康检查的延迟时间。 示例: ```csharp services: web: image: nginx:latest ports: - "80:80" healthcheck: test: ["CMD", "curl", "-f", "http://localhost"] interval: 30s timeout: 10s retries: 3 start_period: 5s ``` ### depends\_on `depends_on`用于控制服务之间的启动顺序。它确保在启动某个服务之前,其依赖的服务已经启动。例如web服务依赖数据库服务,需要数据库服务先启动时可以使用depends\_on。 虽然`depends_on`确保了服务的启动顺序,但它不会等待服务完全启动后再启动依赖的服务,例如,数据库服务可能还在初始化过程中,而web服务已经启动了,这可能会导致web应用程序无法连接到数据库服务,这个时候需要使用`healthcheck` `depends_on`只会影响容器的启动顺序,不会影响容器的停止顺序 示例: ```csharp services: web: image: nginx:latest ports: - "80:80" # 指定依赖db服务 depends_on: db: condition: service_healthy db: image: mysql:latest environment: - "MYSQL_ROOT_PASSWORD=root123" # 健康检查 healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 5s retries: 5 ``` ### links(在Docker Compose版本3以上已被废弃) `links` 是一个用于定义服务之间网络连接的指令。它允许一个服务访问另一个服务的容器,并通过服务名称进行通信。虽然 links 在 Docker Compose 的早期版本中非常常用,但在 Docker Compose 版本 3 及以上中,`links` 已被废弃,推荐使用默认的网络功能来实现服务之间的通信。 links的作用: - 建立网络连接:links 用于在服务之间建立网络连接,允许一个服务访问另一个服务的容器。 - 环境变量和 /etc/hosts:当使用 links 时,Docker 会自动设置环境变量和 /etc/hosts 条目,使得服务之间可以通过服务名称进行通信。 示例: ```csharp [root@lb ~/links]# cat compose.yaml services: web1: container_name: nginx1 image: nginx:latest links: - web2:nginx ports: - "81:80" web2: container_name: nginx2 image: nginx:latest ports: - "82:80" # 运行容器 [root@lb ~/links]# docker-compose up -d [+] Running 3/3 ✔ Network links_default Created 0.1s ✔ Container nginx2 Started 0.4s ✔ Container nginx1 Started 0.6s # 检查 [root@lb ~/links]# docker-compose ps -a NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS nginx1 nginx:latest "/docker-entrypoint.…" web1 13 seconds ago Up 11 seconds 0.0.0.0:81->80/tcp, [::]:81->80/tcp nginx2 nginx:latest "/docker-entrypoint.…" web2 13 seconds ago Up 12 seconds 0.0.0.0:82->80/tcp, [::]:82->80/tcp ###### 测试,进入nginx1的容器内部 [root@lb ~/links]# docker exec -it nginx1 bash # 查看hosts解析 root@12b2517e712e:/# cat /etc/hosts 127.0.0.1 localhost ... # web2的hosts解析 172.24.0.3 12b2517e712e root@12b2517e712e:/# curl curl: try 'curl --help' or 'curl --manual' for more information root@12b2517e712e:/# curl # 网页内容 ``` 在 Docker Compose 版本 3 及以上中,推荐使用默认网络功能来实现服务之间的通信。 示例: ```csharp services: web1: container_name: nginx1 image: nginx:latest ports: - "81:80" web2: container_name: nginx2 image: nginx:latest ports: - "82:80" ``` 在这个示例中,web1和web2默认连接到同一个网络中,web1可以通过web2服务名称直接访问web2服务 ### networks `networks`用于定义和管理服务之间的网络通信,通过`networks`可以创建自定义网络,将服务连接到这些网络中,从而实现灵活的网络结构。 在 Docker Compose 中,如果没有显式定义网络,Docker Compose 会自动为每个项目创建一个默认网络,并将所有服务连接到该网络。默认网络是**桥接网络**(bridge network),服务之间可以通过服务名称直接通信。 也可以自定义网络,并将服务连接到这些网络中,自定义网络可以是桥接网络(bridge)、主机网络(host)或覆盖网(overlay)。 示例: ```csharp services: web: image: nginx:latest ports: - "80:80" networks: - my_network db: image: mysql:latest environment: MYSQL_ROOT_PASSWORD: my-secret-pw networks: - my_network networks: my_network: driver: bridge ``` ### deploy `deploy` 配置项用于定义服务在部署时的行为,包括资源限制、副本数量、更新策略、重启策略等 这里以资源限制为例 ```csharp services: web: image: nginx:latest ports: - "80:80" deploy: resources: limits: cpus: '0.5' # 限制 CPU 使用量为 0.5 个核心 memory: 50M # 限制内存使用量为 50MB reservations: cpus: '0.2' # 保留 0.2 个核心 memory: 20M # 保留 20MB 内存 ``` limits:定义容器可以使用的最大资源量。 - cpus:浮点数,表示 CPU 核心数。例如,0.5 表示限制为 0.5 个核心。 - memory:字符串,表示内存限制,单位可以是 B(字节)、K(千字节)、M(兆字节)、G(吉字节)。 reservations:定义容器启动时保留的资源量。 - cpus:浮点数,表示 CPU 核心数。 - memory:字符串,表示内存大小。 ## Docker Compose变量文件 Compose变量文件是在`compose.yaml`同级目录中创建`.env`文件,在`.env`文件中写入`key=value`的形式,然后在`compose.yaml`文件中以`${key}`的形式进行使用 示例: ```csharp [root@lb ~/var]# ll total 16 ## .env是变量文件 -rw-r--r-- 1 root root 8 Apr 19 21:25 .env -rw-r--r-- 1 root root 73 Apr 19 21:26 compose.yaml [root@lb ~/var]# cat .env PORT=83 [root@lb ~/var]# cat compose.yaml services: web: image: nginx:latest ports: ## ${PORT}取值 - "${PORT}:80" [root@lb ~/var]# docker-compose up -d [+] Running 2/2 ✔ Network var_default Created 0.1s ✔ Container var-web-1 Started 0.4s [root@lb ~/var]# docker-compose ps NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS var-web-1 nginx:latest "/docker-entrypoint.…" web 7 seconds ago Up 6 seconds 0.0.0.0:83->80/tcp, [::]:83->80/tcp ``` ## 使用多个compose文件 当我们具有多个compose文件时,我们应该怎么运行呢? ### 方式一:使用`-f`选项进行合并构建 当有多个 Docker Compose 文件时,可以使用 docker-compose 命令的 `-f`选项来指定多个 Compose 文件,并一起构建和管理服务。这种方式允许你将配置拆分到多个文件中,然后组合使用它们。 例如我们有以下两个compose文件: docker-compose.yaml ```csharp services: web: image: nginx:latest ports: - "80:80" ``` docker-compose.admin.yaml ```csharp version: '3.8' services: web: environment: - NGINX_ENV=prod db: image: mysql:latest environment: MYSQL_ROOT_PASSWORD: my-secret-pw ``` 我们可以使用下面的命令来进行构建 ```csharp docker-compose -f docker-compose.yml -f docker-compose.override.yml up -d ``` 文件合并规则: Docker Compose 会按顺序加载指定的文件,并将它们的内容合并。合并规则如下: - 服务(Services):如果多个文件中定义了相同的服务,后者的配置会覆盖前者的配置。 - 网络(Networks):如果多个文件中定义了相同的网络,后者的配置会覆盖前者的配置。 - 卷(Volumes):如果多个文件中定义了相同的卷,后者的配置会覆盖前者的配置。 我们可以使用使用可以使用 docker-compose config 命令查看合并后的配置。这个命令会输出最终的配置内容,帮助你确认配置是否正确。 ```csharp docker-compose -f docker-compose.yml -f docker-compose.override.yml config ``` ### 方式二:使用`include`元素来引用其它的compose文件 `include` 指令可以在主 Compose 文件中引用其他 Compose 文件,从而实现配置的模块化和重用。被引用的文件可以定义服务、网络、卷等,主文件会将这些内容合并到最终的配置中。 示例: ```csharp include: - my-compose-include.yaml services: serviceA: build: . depends_on: - serviceB ``` 也支持从远程URL加载Compose文件 ```csharp include: - - services: serviceA: build: . depends_on: - serviceB ``` **文件合并规则** - Docker Compose 会按顺序加载 include 中指定的文件,并将它们的内容合并到主文件中。合并规则如下: - 服务(Services):如果多个文件中定义了相同的服务,后者的配置会覆盖前者的配置。 - 网络(Networks):如果多个文件中定义了相同的网络,后者的配置会覆盖前者的配置。 - 卷(Volumes):如果多个文件中定义了相同的卷,后者的配置会覆盖前者的配置。 **注意事项** - 文件顺序:include 中文件的加载顺序很重要,后加载的文件会覆盖前加载的文件中的配置。 - 本地优先:如果本地和远程文件有相同的路径或 URL,Docker Compose 会优先使用本地文件。