1. 简介
在本篇中,我们将深入探讨如何在 docker-compose.yml
文件中为同一个服务配置不同的名称。我们会先回顾 Docker 网络的基础知识,然后构建一个包含自定义配置的 Docker Compose 文件,最后通过一个实际案例验证配置是否生效。
如果你正在搭建多个容器服务,并希望它们之间可以通过更灵活的名称互相访问,这篇内容将对你非常有帮助。
2. Docker 网络基础回顾
Docker Compose 默认会为你的服务创建一个内部网络(通常是 bridge 类型),每个容器在这个网络中拥有自己的 IP 地址、网关、路由表以及 DNS 配置。
默认情况下,Docker 会将服务名自动注册为该容器的主机名(hostname),并将其添加到 Docker 内部的 DNS 服务中。这意味着其他容器可以通过服务名来访问该容器。
举个例子:
services:
web:
image: nginx
其他容器可以通过 http://web
来访问这个服务。
⚠️ 但要注意的是,容器内的 localhost
指向的是容器本身,而不是宿主机。所以在多个容器之间通信时,不能依赖 localhost
来访问其他服务。
3. 自定义容器的主机名
虽然服务名可以作为默认的主机名,但我们也可以通过 hostname
显式指定:
services:
app:
image: my-app
hostname: myapp-host
这样,容器内部和同一网络中的其他容器都可以通过 myapp-host
来访问它。
⚠️ 注意:hostname
不会影响容器的名称(即 container_name
),后者需要单独配置。
4. 为容器设置别名(Alias)
除了自定义主机名,我们还可以通过设置别名来让服务被其他容器用不同的名字访问。
别名是通过在 networks
中定义的,格式如下:
services:
mock_api:
image: kennethreitz/httpbin
networks:
custom_network:
aliases:
- prod_api
✅ 这样,其他容器就可以通过 prod_api
来访问这个服务。
别名的作用域是在网络级别的,也就是说:
- 同一个服务可以在不同网络中使用不同的别名
- 同一个服务可以在同一个网络中拥有多个别名
自定义网络配置
要使用别名,我们还需要先定义一个自定义网络:
networks:
custom_network:
driver: bridge
Docker 支持多种网络驱动,常见如下:
Driver | 说明 |
---|---|
bridge |
默认网络驱动,适合大多数容器通信场景 |
host |
容器与主机共享网络栈,无网络隔离 |
none |
容器无网络连接 |
overlay |
用于跨多个 Docker 主机通信 |
ipvlan |
可精细控制 IPv4/IPv6 地址分配 |
macvlan |
为容器分配 MAC 地址,使其看起来像物理设备 |
5. 实战验证配置
为了更直观地演示,我们构建一个包含三个服务的 Docker Compose 文件:
mock_db
:使用 Redis 镜像,设置主机名为prod_db
mock_api
:使用 httpbin 镜像,设置别名为prod_api
mock_nginx
:使用 Nginx 镜像,设置容器名为prod_nginx
所有服务都连接到一个名为 custom_network
的自定义桥接网络。
version: '3.8'
services:
mock_db:
image: redis
hostname: prod_db
networks:
- custom_network
mock_api:
image: kennethreitz/httpbin
networks:
custom_network:
aliases:
- prod_api
mock_nginx:
image: nginx:latest
container_name: prod_nginx
networks:
- custom_network
networks:
custom_network:
driver: bridge
启动服务
$ docker-compose up -d
输出如下:
[+] Running 3/3
✔ Container alias-mock_db-1 Started 0.0s
✔ Container alias-mock_api-1 Started 0.0s
✔ Container prod_nginx Started 0.0s
查看容器状态
$ docker ps
输出如下:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ae860f1b9764 kennethreitz/httpbin "gunicorn -b 0.0.0.0…" About a minute ago Up About a minute 80/tcp alias-mock_api-1
63cdc9e7f086 nginx:latest "/docker-entrypoint.…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp, :::80->80/tcp prod_nginx
d28b8b141c9f redis "docker-entrypoint.s…" About a minute ago Up About a minute 6379/tcp alias-mock_db-1
可以看到,mock_nginx
的容器名确实为 prod_nginx
,而其他服务使用默认命名规则。
测试通信
进入 prod_nginx
容器并尝试 ping 其他服务:
$ docker exec -it prod_nginx ping prod_db
PING prod_db (172.23.0.2) 56(84) bytes of data.
64 bytes from alias-mock_db-1.alias_custom_network (172.23.0.2): icmp_seq=1 ttl=64 time=0.364 ms
...
也可以使用服务名访问:
$ docker exec -it prod_nginx ping mock_db
PING mock_db (172.23.0.2) 56(84) bytes of data.
64 bytes from alias-mock_db-1.alias_custom_network (172.23.0.2): icmp_seq=1 ttl=64 time=0.182 ms
...
对于 API 服务,我们也可以通过别名访问:
$ docker exec -it prod_nginx ping prod_api
PING prod_api (172.23.0.3) 56(84) bytes of data.
64 bytes from alias-mock_api-1.alias_custom_network (172.23.0.3): icmp_seq=1 ttl=64 time=0.129 ms
...
或者使用服务名:
$ docker exec -it prod_nginx ping mock_api
PING mock_api (172.23.0.3) 56(84) bytes of data.
64 bytes from alias-mock_api-1.alias_custom_network (172.23.0.3): icmp_seq=1 ttl=64 time=0.085 ms
...
✅ 结果表明:在自定义网络中,服务可以通过服务名、主机名或别名进行访问,非常灵活。
6. 小结
通过本文我们掌握了以下内容:
- Docker 默认会将服务名作为主机名并注册到内部 DNS
- 可通过
hostname
显式指定容器的主机名 - 使用
networks
和aliases
可为服务设置别名,方便其他容器访问 - 别名是网络级别的,不同网络中可以不同
- 容器间通信时,可以使用服务名、主机名或别名互换使用
这种机制非常适合用于模拟生产环境的命名结构,避免在应用中硬编码 URL,从而提升开发与测试的灵活性。