域名中使用下划线的问题

7
让我先描述一下我的原始问题和解决方案:
我有几个描述应用程序不同部分的docker-compose文件。这些部分是独立开发和部署的,因此它们不能集成到单个compose文件中。但是这些组件需要相互通信,目前我使用的解决方案是拥有一个外部网络(桥接),所有服务都连接到该网络。到目前为止,一切都很好,只要我连接到自定义桥接网络,我确实可以连接到任何使用docker compose文件启动的服务:
$ docker run --network=mynet --rm --name ping_test -it xenial-networking bash

root@0319469f7951:/# ping -c 1 proj_web_1
PING proj_web_1 (172.30.0.3) 56(84) bytes of data.
64 bytes from 172.30.0.3: icmp_seq=1 ttl=64 time=0.071 ms

--- proj_web_1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.071/0.071/0.071/0.000 ms

我为什么要使用proj_web_1?因为这是Docker Compose创建的DNS条目。

这很好用,没有人关心下划线在域名中并不那么好

没有人……除了django似乎还真在意:

ERROR Invalid HTTP_HOST header: 'proj_web_1:8000'. The domain name provided is not valid according to RFC 1034/1035.
172.30.0.5 - admin [07/May/2018:05:41:53 +0000] "OPTIONS /api/v1/expansions/ HTTP/1.1" 400 58663 "-" "python-requests/2.18.4"

看起来 docker-compose 不支持 使用连字符代替下划线。

可能我可以通过在我的 Django 服务中启用 DEBUG解决这个问题

有没有更干净的方法来启用它,而不是运行在 Django 调试模式下? 有没有办法告诉 Docker Compose 停止使用下划线?


另请参见:https://code.djangoproject.com/ticket/18517 - Timir
请注意,Docker Compose 还允许您使用服务名称(在您的情况下只需使用 web)在同一堆栈中的服务之间进行通信(这也是建议的做法,因为它不会使它们依赖于用于部署堆栈的项目名称)。 - thaJeztah
相关链接:https://github.com/docker/compose/issues/472#issuecomment-63514093 - Sraw
DNS中的主机名(hostname)和域名(domain name)不能包含下划线。这是根据DNS标准规定的,详见RFC1034(第3.5节)。 - Patrick Mevzek
@thaJeztah 这正是我在寻找的 - 与我在下面回答中提到的类似,但使用内置功能(无需定义别名)。我可以接受那个作为答案。 - blueFast
显示剩余8条评论
2个回答

6

跨组合网络连接

运行组合项目时,服务可以通过其完整名称(包括项目名称前缀,例如myproject_web_1)和服务名称(在组合文件中指定)进行访问,例如web。短名称是网络范围别名,这意味着任何连接到同一网络的容器都可以通过此名称访问容器。

默认情况下,docker-compose为每个组合项目创建一个网络(projectname_default),以便组合项目中的所有服务可以通信。由于该网络为每个项目单独创建,因此两个组合项目不共享相同的网络,它们的服务与其他组合项目隔离。

然而,可以使组合项目(或组合项目中的单个服务)共享相同的网络。

示例1 - 使用共享网络整个项目

以下组合文件指定默认网络的自定义名称; 两个组合文件都使用sharednet网络作为默认网络,这意味着两个组合项目的服务将连接到同一个网络:

组合文件1 (compose1.yml):

version: '3.5'
services:
  compose1service:
    image: busybox
    tty: true

networks:
  default:
    name: sharednet

Compose文件V2(compose2.yml):

version: '3.5'
services:
  compose2service:
    image: busybox
    tty: true

networks:
  default:
    name: sharednet

为了说明这一点:
启动两个组合文件:
docker-compose -f compose1.yml --project-name=compose1 up -d
docker-compose -f compose2.yml --project-name=compose2 up -d

使用短名称 (compose2service) 在 compose1service 容器内部从服务中ping通compose2service是可行的;

docker exec compose1_compose1service_1 ping -c1 compose2service
PING compose2service (172.20.0.3): 56 data bytes
64 bytes from 172.20.0.3: seq=0 ttl=64 time=0.134 ms

--- compose2service ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.134/0.134/0.134 ms

反之亦然:

docker exec compose2_compose2service_1 ping -c1 compose1service
PING compose1service (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.151 ms

--- compose1service ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.151/0.151/0.151 ms

和项目前缀一样,全名也需要包含;

docker exec compose2_compose2service_1 ping -c1 compose1_compose1service_1
PING compose1_compose1service_1 (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.151 ms

--- compose1_compose1service_1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.151/0.151/0.151 ms

示例 2 - 在项目中使用共享网络提供某些服务

在这个示例中,两个Compose项目都有自己的(“默认”)网络,但是另外添加了一个共享网络,以允许一些服务连接到其他Compose项目中的服务。

Compose文件1(compose3.yml):

version: '3.5'
services:
  compose3service:
    image: busybox
    tty: true
    networks:
      - default
      - sharednet

  compose3otherservice:
    image: busybox
    tty: true

networks:
  sharednet:
    name: mysharednetwork

注意: 如果您指定了服务应连接到哪些网络,则会覆盖默认设置,这意味着该服务不再自动连接到default网络。请将default网络包含在网络列表中,以允许服务与组成项目中的其他服务通信。

Compose文件2(compose4.yml):

version: '3.5'
services:
  compose4service:
    image: busybox
    tty: true
    networks:
      - default
      - sharednet

  compose4otherservice:
    image: busybox
    tty: true

networks:
  sharednet:
    name: mysharednetwork

启动两个Compose文件:

docker-compose -f compose3.yml --project-name=compose3 up -d
docker-compose -f compose4.yml --project-name=compose4 up -d

再次提醒,从compose3service向另一个compose项目中的compose4service服务进行ping测试是有效的(可以使用简称或全名);

docker exec compose3_compose3service_1 ping -c1 compose4service
PING compose4service (172.22.0.3): 56 data bytes
64 bytes from 172.22.0.3: seq=0 ttl=64 time=0.110 ms

--- compose4service ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.110/0.110/0.110 ms


docker exec compose3_compose3service_1 ping -c1 compose4_compose4service_1
PING compose4_compose4service_1 (172.22.0.3): 56 data bytes
64 bytes from 172.22.0.3: seq=0 ttl=64 time=0.093 ms

--- compose4_compose4service_1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.093/0.093/0.093 ms

然而,尝试连接到compose4otherservice将失败,因为该服务未连接到mysharednetwork网络:
docker exec compose3_compose3service_1 ping -c1 compose4otherservice
ping: bad address 'compose4otherservice'

docker exec compose3_compose3service_1 ping -c1 compose4_compose4otherservice_1
ping: bad address 'compose4_compose4otherservice_1'

注意:

如果两个Compose项目中有相同名称的服务(例如,都有一个名为web的服务),则需要小心处理。在这种情况下,web可能随机解析为任一项目中的web服务。


1
我可以通过使用网络别名来解决问题,避免使用下划线:
  web:
    restart: always
    environment:
      - DJANGO_SECRET_KEY=local
      - DJANGO_CONFIGURATION=Develop
    build:
      context: ./
      args:
        - REGISTRY
    image: web
    command: ./run-gunicorn.sh
    volumes:
      - ./:/code
    depends_on:
      - postgres
    networks:
      spp:
        aliases:
          - projweb

现在我可以访问它:

root@a9c0fde612a1:/# ping -c 1 projweb
PING projweb (172.30.0.4) 56(84) bytes of data.
64 bytes from svc_web_1.spp (172.30.0.4): icmp_seq=1 ttl=64 time=0.082 ms

--- projweb ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.082/0.082/0.082/0.000 ms

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接