docker-compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。在之前的文章中已经介绍了 Docker 和 docker-compose 的区别,以及 dockerfile 和 docker-compose.yml 对项目的简单封装,而这里主要介绍 docker-compose 中的网络配置和交互方式。

交互方式

expose 和 ports

首先说一下端口的问题,docker-compose.yml 中有两个参数可以用来配置端口,分别是 expose 和 ports,这两个参数的区别在于:

  • expose:仅暴露端口,但不映射到宿主机,其他容器可以访问通过 links 参数访问该容器;
  • ports:将 docker 容器端口映射到宿主机端口,外部可以通过宿主机的端口访问容器的端口;

这里的 expose 和 Dockerfile 中的 expose 实际上是相同的。但要注意的是,如果 Dockerfile 中通过 expose 暴露了端口,那么 docker-compose 服务中也会自动暴露该端口;如果 Dockerfile 中没有暴露端口,那么 docker-compose 服务中可以通过 expose 暴露端口。

ports

ports 参数有多种配置方式,主要有以下几种:

  • 端口映射:[host]:[container],例如 8080:80,表示将宿主机的 8080 端口映射到容器的 80 端口,这样外部就可以通过宿主机的 8080 端口访问容器的 80 端口;
  • 地址映射:[host-ip]:[host-port]:[container-port],例如 10.16.1.1:8080:80,表示将宿主机的 10.16.1.1 的 8080 端口映射到容器的 80 端口。
  • 随机端口:[container-port],例如 80,表示将容器的 80 端口映射到宿主机的一个随机端口,这样外部就可以通过宿主机的随机端口访问容器的 80 端口;
version: "3.9"
services:
web:
image: nginx
ports:
- "8080:80" # 端口映射
- "10.16.1.1:8080:80" # 地址映射
- "80" # 随机端口

expose

expose 参数的配置方式和 ports 参数类似,通常如下:

version: "3.9"
services:
web:
image: nginx
expose:
- "80"

links 参数用于连接多个服务,将服务名称通过别名的方式映射到容器中,例如:

version: "3.9"
services:
web:
image: nginx
expose:
- "80"
db:
image: mysql
expose:
- "3306"
links:
- web:web # 将 web 服务映射到 db 容器中的 web 别名

external_links 参数用于连接外部服务,例如:

version: "3.9"
services:
web:
image: nginx
expose:
- "80"
external_links:
- mysql:db # 将外部的 mysql 服务映射到 web 容器中的 db 别名
networks:
- my-network

这里 mysql 服务需要和 web 服务在同一个网络(例如 my-network)中,否则会报错。例如我们可以这样启动一个 mysql 服务:

docker run -d --name mysql --network my-network mysql

depends_on

depends_on 参数用于定义服务之间的依赖关系,当 A 服务依赖于 B 服务时,B 服务会先于 A 服务启动,例如:

version: "3.9"
services:
web:
image: nginx
expose:
- "80"
depends_on:
- db # web 服务依赖于 db 服务
db:
image: mysql
expose:
- "3306"

网络配置

网络模式介绍

  1. host

host 模式表示容器和宿主机共享网络,容器将不会虚拟出网卡,而是使用宿主 IP,只是端口会不一样。

host

  1. bridge

bridge 模式表示使用 docker0 网桥,这是 docker 默认的网络模式,容器将会虚拟出网卡,通过网桥和宿主机通信,通过 NAT 的方式和外部通信。

bridge

  1. none

none 模式表示不使用网络,容器将不会虚拟出网卡,也不会和宿主机通信,也无法和外部通信。

none

  1. container

container 模式表示和指定的容器共享网络,容器将不会虚拟出网卡,而是和指定的容器共享网卡,这样两个容器就可以通过 localhost 来通信。

container

网络配置

当我们使用 docker-compose 启动一个服务时,docker-compose 会自动创建一个默认的网络,一般会自动命名为项目名称加上一个后缀,例如 my-project_default,这个网络的模式为 bridge,这样我们就可以通过服务名称来访问其他服务;然而为了有固定的 ip 地址,我们可以通过 networks 参数来配置网络。

networks 参数

networks 参数用于配置网络,可以配置多个网络,常用的配置参数有:

  • external:是否使用外部网络;
  • driver:网络模式,例如 bridge、overlay、host、none 等;
  • ipam:ipam 模式,例如 default、host、config 等;
  • config:ipam 模式为 config 时,用于配置 IP 地址,其中还包括了子参数:
    • subnet:子网地址;
    • gateway:网关地址;
    • ip_range:IP 地址范围;
    • aux_addresses:辅助 IP 地址;

首先给出一个简单的项目配置示例:

version: "3.9"
services:
web:
image: nginx
expose:
- "80"
networks:
my-network: # 将 web 服务加入到 my-network 网络中
ipv4_address: 172.19.0.5 # 指定 IP 地址

db:
image: mysql
expose:
- "3306"
networks:
my-network:
ipv4_address: 172.19.0.6 # 指定 IP 地址

networks:
my-network: # 定义一个网络,名称为 my-network(自己随意)
driver: bridge # 网络模式为 bridge
ipam: # ipam 用于配置网络的 IP 地址
driver: default # ipam 模式为默认模式
config: # config 用于配置 IP 地址
- subnet: 172.19.0.0/16 # 子网

这样我们就可以在容器里通过 IP 地址来访问其他容器了,这个就是本次介绍的内容啦,也希望这个 ip 配置方式可以适用于你的项目。除此之外,docker-compose 还有很多的配置参数,可以参考下面的参考资料。

其他参考资料