django - Docker、Django 和 Selenium - Selenium 无法连接

标签 django selenium docker docker-compose

我将 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呢?

我已经研究这个好几天了 - 非常感谢任何帮助。

更多信息

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

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

最佳答案

我最终想出了一个更好的解决方案,不需要我对 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

关于django - Docker、Django 和 Selenium - Selenium 无法连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35143927/

相关文章:

selenium - 如何将参数从 Selenium Webdriver 传递到 JMeter?

javascript - 如何使用 Protractor 测试比较具有 getSize() 函数的元素的宽度和高度?

nginx - 如何在 Docker 镜像中使用 Nginx 连接到我的应用程序?

sql - 如果值为null则Postgresql忽略过滤条件

django - 如何将 timedelta 放入 django 模型中?

java - Selenium webdriver 显式等待警报抛出 UnhandledAlertException

python - Flask CLI 在通过 docker-compose 运行时抛出 'OSError: [Errno 8] Exec format error'

docker - Composer 网络启动命令失败

javascript - 将 JSON 字符串传递给 Django 模板

在第三方网站的 iframe 中访问时,未为子域设置 Django csrf cookie