【问题标题】:Docker, Django and Selenium - Selenium unable to connectDocker、Django 和 Selenium - Selenium 无法连接
【发布时间】:2016-05-10 16:40:36
【问题描述】:

我已将 Docker 配置为使用 docker-compose.yml 运行 Postgres 和 Django,它运行良好。

我遇到的问题是 Selenium 无法连接到 Django liveserver。

现在(至少对我而言)django 必须访问 selenium 来控制浏览器而 selenium 必须访问 django 才能访问服务器是有道理的。

我已经尝试使用 docker 'ambassador' 模式,并使用以下 docker-compose.yml 配置从这里开始:https://github.com/docker/compose/issues/666

postgis:
  dockerfile: ./docker/postgis/Dockerfile
  build: .
  container_name: postgis

django-ambassador:
  container_name: django-ambassador
  image: cpuguy83/docker-grand-ambassador
  volumes:
    - "/var/run/docker.sock:/var/run/docker.sock"
  command: "-name django -name selenium"

django:
  dockerfile: ./docker/Dockerfile-dev
  build: .
  command: python /app/project/manage.py test my-app
  container_name: django
  volumes:
    - .:/app
  ports:
    - "8000:8000"
    - "8081:8081"
  links:
    - postgis
    - "django-ambassador:selenium"
  environment:
    - SELENIUM_HOST=http://selenium:4444/wd/hub

selenium:
  container_name: selenium
  image: selenium/standalone-firefox-debug
  ports:
    - "4444:4444"
    - "5900:5900"
  links:
    - "django-ambassador:django"

当我检查http://DOCKER-MACHINE-IP:4444/wd/hub/static/resource/hub.html 我可以看到 firefox 启动了,但是所有测试都失败了,因为 firefox 无法连接到 django

'Firefox can't establish a connection to the server at localhost:8081'

我也在这里尝试过这个解决方案https://github.com/docker/compose/issues/1991 但这不起作用,因为我无法让 django 同时连接到 postgis 和 selenium

'django.db.utils.OperationalError: could not translate host name "postgis" to address: Name or service not known'

我尝试使用下面列出的网络功能

postgis:
  dockerfile: ./docker/postgis/Dockerfile
  build: .
  container_name: postgis
  net: appnet

django:
  dockerfile: ./docker/Dockerfile-dev
  build: .
  command: python /app/project/manage.py test foo
  container_name: django
  volumes:
    - .:/app
  ports:
    - "8000:8000"
    - "8081:8081"
  net: appnet
  environment:
    - SELENIUM_HOST=http://selenium:4444/wd/hub

selenium:
  container_name: selenium
  image: selenium/standalone-firefox-debug
  ports:
    - "4444:4444"
    - "5900:5900"
  net: appnet

但结果是一样的

'Firefox can't establish a connection to the server at localhost:8081'

那么我怎样才能让 selenium 连接到 django?

我已经玩了几天了 - 非常感谢任何帮助。

更多信息

另一个奇怪的事情是,当测试服务器运行 not 使用 docker(使用我的 virtualenv 等旧配置)如果我运行 ./manage.py test foo 我可以通过任何http://localhost:8081 的浏览器并获取网页,但如果我在 docker 下运行等效命令,则无法访问测试服务器。这很奇怪,因为我正在映射端口 8081:8081 - 这有关系吗?

注意:我使用的是 OSX 和 Docker v1.9.1

【问题讨论】:

    标签: django selenium docker docker-compose


    【解决方案1】:

    每当您看到 localhost 时,首先尝试端口转发该端口(在 VM 级别)

    见“Connect to a Service running inside a docker container from outside

    VBoxManage controlvm "default" natpf1 "tcp-port8081,tcp,,8081,,8081"
    VBoxManage controlvm "default" natpf1 "udp-port8081,udp,,8081,,8081"
    

    (将 default 替换为您的 docker 机器的名称:参见 docker-machine ls

    这与 docker 主机级别的端口映射不同(这是您的基于 boot2docker 的 Linux 主机)

    OP luke-aus 确认in the comments

    输入网络的 IP 地址即可解决问题!

    【讨论】:

    • 我尝试了这个解决方案,还在这里阅读了您更长的答案stackoverflow.com/a/33827463/3003438 - 不幸的是,这对我不起作用。还有其他想法吗?
    • @luke_aus 您需要检查localhost:8081 来自什么设置。如果从一个容器访问另一个容器,'localhost' 不是指实际主机,而是应更改为 'django'(因为它是暴露 8081 的容器)django:8081 会起作用。
    • 所以 django 启动了一个 livetestserver,默认情况下它位于 localhost:8081。您可以使用 ./manage.py test myapp --liveserver=django:8081 更改此设置,但 django 抱怨 gaierror: [Errno -2] Name or service not known
    • 在正在运行的 django 容器上运行 curl -I http://localhost:8081 返回状态“HTTP/1.0 200 OK”。在正在运行的 selenium 容器上运行 curl -I http://localhost:8081 返回 curl: (7) Failed to connect to localhost port 8081: Connection refused
    • 输入网络IP地址即可解决问题!
    【解决方案2】:

    我最终想出了一个更好的解决方案,它不需要我对 IP 地址进行硬编码。下面是我使用 docker 在 django 中运行测试的配置。

    Docker 编写文件

    # docker-compose base file for everything
    version: '2'
    
    services:
      postgis:
        build:
          context: .
          dockerfile: ./docker/postgis/Dockerfile
        container_name: postgis
        volumes:
          # If you are using boot2docker, postgres data has to live in the VM for now until #581 fixed
          # for more info see here: https://github.com/boot2docker/boot2docker/issues/581
          - /data/dev/docker_cookiecutter/postgres:/var/lib/postgresql/data
    
      django:
        build:
          context: .
          dockerfile: ./docker/django/Dockerfile
        container_name: django
        volumes:
          - .:/app
        depends_on:
          - selenium
          - postgis
        environment:
          - SITE_DOMAIN=django
          - DJANGO_SETTINGS_MODULE=settings.my_dev_settings
        links:
          - postgis
          - mailcatcher
    
      selenium:
        container_name: selenium
        image: selenium/standalone-firefox-debug:2.52.0
        ports:
          - "4444:4444"
          - "5900:5900"
    

    Dockerfile(用于 Django)

    ENTRYPOINT ["/docker/django/entrypoint.sh"]
    

    在入口点文件中

    #!/bin/bash
    set -e
    
    # Now we need to get the ip address of this container so we can supply it as an environmental
    # variable for django so that selenium knows what url the test server is on
    # Use below or alternatively you could have used
    # something like "$@ --liveserver=$THIS_DOCKER_CONTAINER_TEST_SERVER"
    
    if [[ "'$*'" == *"manage.py test"* ]]  # only add if 'manage.py test' in the args
    then
      # get the container id
      THIS_CONTAINER_ID_LONG=`cat /proc/self/cgroup | grep 'docker' | sed 's/^.*\///' | tail -n1`
      # take the first 12 characters - that is the format used in /etc/hosts
      THIS_CONTAINER_ID_SHORT=${THIS_CONTAINER_ID_LONG:0:12}
      # search /etc/hosts for the line with the ip address which will look like this:
      #     172.18.0.4    8886629d38e6
      THIS_DOCKER_CONTAINER_IP_LINE=`cat /etc/hosts | grep $THIS_CONTAINER_ID_SHORT`
      # take the ip address from this
      THIS_DOCKER_CONTAINER_IP=`(echo $THIS_DOCKER_CONTAINER_IP_LINE | grep -o '[0-9]\+[.][0-9]\+[.][0-9]\+[.][0-9]\+')`
      # add the port you want on the end
      # Issues here include: django changing port if in use (I think)
      # and parallel tests needing multiple ports etc.
      THIS_DOCKER_CONTAINER_TEST_SERVER="$THIS_DOCKER_CONTAINER_IP:8081"
      echo "this docker container test server = $THIS_DOCKER_CONTAINER_TEST_SERVER"
      export DJANGO_LIVE_TEST_SERVER_ADDRESS=$THIS_DOCKER_CONTAINER_TEST_SERVER
    fi
    
    
    eval "$@"
    

    在你的 django 设置文件中

    SITE_DOMAIN = 'django'
    

    然后运行你的测试

    docker-compose run django ./manage.py test
    

    【讨论】:

    • 比我的回答更准确。良好的反馈。 +1
    • 为什么不在 docker-compose 文件中设置 DJANGO_LIVE_TEST_SERVER_ADDRESS?那是你必须指定容器名称的地方,它是进行此类设置的地方
    【解决方案3】:

    我也一直在努力解决这个问题,我终于找到了一个适合我的解决方案。你可以试试这样的:

    postgis:
      dockerfile: ./docker/postgis/Dockerfile
      build: .
    
    django:
      dockerfile: ./docker/Dockerfile-dev
      build: .
      command: python /app/project/manage.py test my-app
      volumes:
        - .:/app
      ports:
        - "8000:8000"
      links:
        - postgis
        - selenium  # django can access selenium:4444, selenium can access django:8081-8100
      environment:
        - SELENIUM_HOST=http://selenium:4444/wd/hub
        - DJANGO_LIVE_TEST_SERVER_ADDRESS=django:8081-8100  # this gives selenium the correct address
    
    selenium:
      image: selenium/standalone-firefox-debug
      ports:
        - "5900:5900"
    

    我认为您不需要在 selenium 配置中包含端口 4444。该端口默认公开,无需将其映射到主机,因为 django 容器可以通过其与 selenium 容器的链接直接访问它。

    [编辑] 我发现您也不需要显式公开 django 容器的 8081 端口。此外,我为测试服务器使用了一系列端口,因为如果测试并行运行,您可能会收到“地址已在使用中”错误,如 here 所述。

    【讨论】:

      猜你喜欢
      • 2023-03-19
      • 2016-12-31
      • 2013-01-14
      • 2015-12-16
      • 2013-10-26
      • 1970-01-01
      • 1970-01-01
      • 2019-01-04
      • 1970-01-01
      相关资源
      最近更新 更多