docker-compose : Why agent & app service fail due

2020-04-21 03:13发布

Below is the working docker-compose file in v2 spec:

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


1)

app service fails with below error on using MYSQL_HOST: dbr

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

2)

agent service also fails in below ansible code when PROBE_HOST: "dbr"

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

1)

Why these two services are failing with value dbr?

2)

How to make these two services work with MYSQL_HOST: dbr and PROBE_HOST: "dbr"?

3条回答
不美不萌又怎样
2楼-- · 2020-04-21 03:38

If you want to reference the service by another name you can use network alias. Modified compose file to use network alias

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:
查看更多
叼着烟拽天下
3楼-- · 2020-04-21 03:40

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

查看更多
家丑人穷心不美
4楼-- · 2020-04-21 04:01

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. On plain Linux running hostname dbr won't change an external DNS server or other machines' /etc/hosts files, for example. Setting the hostname might affect a shell prompt, in the unusual case of getting an interactive shell inside a container; 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. In your file, app, nginx, test, dbc, and agent are valid hostnames. If you manually specify a container_name: I believe that will also be reachable; network aliases as suggested in @asolanki's answer give yet another name; and the deprecated links: option would give still another. All of these are in addition to the standard name Compose gives you.

Networking in Compose has some reasonable explanations of all of this.

In your example, dbr is not a valid hostname. dbc is the Compose service name of the container, but nothing from the previous listing causes a hostname dbr to exist. 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.

As a specific corollary to "links: is deprecated", the form of links: you have does absolutely nothing. links: [dbc] makes the container that would otherwise be visible under the name dbc visible to that specific container as that same name. 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. 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].)

查看更多
登录 后发表回答