简体   繁体   English

docker-compose:为什么代理和应用服务因主机名而失败?

[英]docker-compose : Why agent & app service fail due to hostname?

Below is the working docker-compose file in v2 spec:以下是 v2 规范中的工作 docker-compose 文件:

version: '2'

volumes:
  webroot:
    driver: local


services:
  app: # Launch uwsgi application server
    build:
      context: ../../
      dockerfile: docker/release/Dockerfile
    links:
      - dbc
    volumes:
      - webroot:/var/www/someapp
    environment:
      DJANGO_SETTINGS_MODULE: someapp.settings.release
      MYSQL_HOST: dbc
      MYSQL_USER: todo
      MYSQL_PASSWORD: passwd
    command:
      - uwsgi
      - "--socket /var/www/someapp/someapp.sock"
      - "--chmod-socket=666"
      - "--module someapp.wsgi"
      - "--master"
      - "--die-on-term"

  test: # Run acceptance test cases
    image: shamdockerhub/someapp-specs
    links:
      - nginx
    environment:
      URL: http://nginx:8000/todos
      JUNIT_REPORT_PATH: /reports/acceptance.xml
      JUNIT_REPORT_STACK: 1
    command: --reporter mocha-jenkins-reporter

  nginx: # Start nginx web server that forwards https packets to uwsgi server
    build:
      context: .
      dockerfile: Dockerfile.nginx
    ports:
      - "8000:8000"
    links:
      - app
    volumes:
      - webroot:/var/www/someapp

  dbc: # Launch MySQL server
    image: mysql:5.6
    hostname: dbr
    expose:
      - "3306"
    environment:
      MYSQL_DATABASE: someapp
      MYSQL_USER: todo
      MYSQL_PASSWORD: passwd
      MYSQL_ROOT_PASSWORD: passwd

  agent: # Ensure DB server is runnin
    image: shamdockerhub/ansible
    links:
      - dbc
    environment:
      PROBE_HOST: "dbc"
      PROBE_PORT: "3306"
    command: ["probe.yml"]

where entries条目在哪里

  MYSQL_HOST: dbc

  PROBE_HOST: "dbc"

does not look intuitive, because the hostname is set to dbr in dbc service看起来不直观,因为在dbc服务中hostname设置为dbr


1) 1)

app service fails with below error on using MYSQL_HOST: dbr app服务在使用MYSQL_HOST: dbr

   django.db.utils.OperationalError: (2005, "Unknown MySQL server host 'dbr' (0)")

2) 2)

agent service also fails in below ansible code when PROBE_HOST: "dbr"PROBE_HOST: "dbr"时, agent服务在 ansible 代码下也会失败

set_fact:
      probe_host: "{{ lookup('env', 'PROBE_HOST') }}"
local_action: >
      wait_for host={{ probe_host }}

1) 1)

Why these two services are failing with value dbr ?为什么这两项服务因价值dbr而失败?

2) 2)

How to make these two services work with MYSQL_HOST: dbr and PROBE_HOST: "dbr" ?如何使这两个服务与MYSQL_HOST: dbrPROBE_HOST: "dbr"一起工作?

that is how Docker works because the hostname is not unique and that will lead to a problem if you give two containers the same hostname therefore compose will always use the service name for DNS resolution这就是 Docker 的工作方式,因为hostname不是唯一的,如果给两个容器提供相同的主机名,这将导致问题,因此 compose 将始终使用服务名称进行 DNS 解析

Setting hostname: is equivalent to the hostname (8) command on plain Linux: it changes what the container thinks its own hostname is, but doesn't affect anything outside the container that might try to reach it.设置hostname:等效于普通 Linux 上的主机名(8) 命令:它会更改容器认为自己的主机名是什么,但不会影响容器外部可能试图访问它的任何内容。 On plain Linux running hostname dbr won't change an external DNS server or other machines' /etc/hosts files, for example.例如,在普通 Linux 上运行hostname dbr dbr 不会更改外部 DNS 服务器或其他机器的/etc/hosts文件。 Setting the hostname might affect a shell prompt, in the unusual case of getting an interactive shell inside a container;设置主机名可能会影响 shell 提示,在容器内获取交互式 shell 的异常情况下; it has no effect on networking.它对网络没有影响。

Within a single Docker Compose file, if you have no special configuration for networks: , any container can reach any other container using the name of its block in the YAML file.在单个 Docker Compose 文件中,如果您没有特殊的networks: ,任何容器都可以使用 YAML 文件中的块名称访问任何其他容器。 In your file, app , nginx , test , dbc , and agent are valid hostnames.在您的文件中, appnginxtestdbcagent是有效的主机名。 If you manually specify a container_name: I believe that will also be reachable;如果你手动指定一个container_name:我相信这也是可以访问的; network aliases as suggested in @asolanki's answer give yet another name; @asolanki 的回答中建议的网络别名给出了另一个名称; and the deprecated links: option would give still another.和不推荐使用的links:选项会给出另一个。 All of these are in addition to the standard name Compose gives you.所有这些都是 Compose 为您提供的标准名称的补充

Networking in Compose has some reasonable explanations of all of this. Compose 中的网络对所有这些都有一些合理的解释。

In your example, dbr is not a valid hostname.在您的示例中, dbr不是有效的主机名。 dbc is the Compose service name of the container, but nothing from the previous listing causes a hostname dbr to exist. dbc是容器的 Compose 服务名称,但上一个列表中的任何内容都不会导致主机名dbr存在。 It happens to be the name you'll see in the prompt if you docker-compose exec dlc sh but nobody else thinks that container has that name.如果您docker-compose exec dlc sh ,它恰好是您将在提示中看到的名称,但没有其他人认为该容器具有该名称。

As a specific corollary to " links: is deprecated", the form of links: you have does absolutely nothing.作为“ links:已弃用”的特定推论,链接的形式links:您拥有绝对没有任何作用。 links: [dbc] makes the container that would otherwise be visible under the name dbc visible to that specific container as that same name. links: [dbc]使原本在名称dbc下可见的容器对于该特定容器可见为相同的名称。 You could use it to give an alternate name to a container from the point of view of a client, but I wouldn't.从客户端的角度来看,您可以使用它为容器提供替代名称,但我不会。

Your docker-compose.yml file doesn't have any networks: blocks, and so Compose will create a default network and attach all of the containers to it.您的docker-compose.yml文件没有任何networks:块,因此 Compose 将创建一个default网络并将所有容器附加到它。 This is totally fine and I would not recommend changing it.这完全没问题,我不建议更改它。 If you do declare multiple networks, the other requirement here is that the client and server need to be on the same network to reach each other.如果您确实声明了多个网络,这里的另一个要求是客户端和服务器需要在同一网络上才能相互访问。 (Containers without a networks: block implicitly have networks: [default] .) (没有networks:块隐式有networks: [default] 。)

If you want to reference the service by another name you can use network alias .如果你想用另一个名字来引用服务,你可以使用网络别名 Modified compose file to use network alias修改 compose 文件以使用网络别名

version: '2'

volumes:
  webroot:
    driver: local


services:
  app: # Launch uwsgi application server
    build:
      context: ../../
      dockerfile: docker/release/Dockerfile
    links:
      - dbc
    volumes:
      - webroot:/var/www/someapp
    environment:
      DJANGO_SETTINGS_MODULE: someapp.settings.release
      MYSQL_HOST: dbc
      MYSQL_USER: todo
      MYSQL_PASSWORD: passwd
    command:
      - uwsgi
      - "--socket /var/www/someapp/someapp.sock"
      - "--chmod-socket=666"
      - "--module someapp.wsgi"
      - "--master"
      - "--die-on-term"
    networks:
      new:
        aliases:
          - myapp  

  test: # Run acceptance test cases
    image: shamdockerhub/someapp-specs
    links:
      - nginx
    environment:
      URL: http://nginx:8000/todos
      JUNIT_REPORT_PATH: /reports/acceptance.xml
      JUNIT_REPORT_STACK: 1
    command: --reporter mocha-jenkins-reporter
    networks:
      - new


  nginx: # Start nginx web server that forwards https packets to uwsgi server
    build:
      context: .
      dockerfile: Dockerfile.nginx
    ports:
      - "8000:8000"
    links:
      - app
    volumes:
      - webroot:/var/www/someapp
    networks:
      - new 

  dbc: # Launch MySQL server
    image: mysql:5.6
    hostname: dbr
    expose:
      - "3306"
    environment:
      MYSQL_DATABASE: someapp
      MYSQL_USER: todo
      MYSQL_PASSWORD: passwd
      MYSQL_ROOT_PASSWORD: passwd
    networks:
      new:
        aliases:
          - dbr  

  agent: # Ensure DB server is runnin
    image: shamdockerhub/ansible
    links:
      - dbc
    environment:
      PROBE_HOST: "dbc"
      PROBE_PORT: "3306"
    command: ["probe.yml"]
    networks:
      - new

networks:
  new:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM