2

I have this docker-compose configuration in which I want to embed a chrome headless browser to run my e2e tests...

The nginx is configured to reverse proxy a url, let's say foo.bar to somewhere... this works just fine if I use my host browser, and I can test it by exposing the 444:443 ports!

however, it doesn't work when I try to use the chrome-alpine one, I navigate to the debugger localhost:9222, select the instance and then type: http://foo.bar.

How can I configure alpine-chrome to use the nginx container?

services:
  nginx:
    image: nginx:alpine
    command: [nginx-debug, "-g", "daemon off;"]
    volumes:
      - ../../config/nginx/nginx.config.d:/etc/nginx/conf.d/server.conf
      - ../../config/nginx/certs:/etc/nginx/certs
    ports:
      - "444:443"

  chrome:
    image: zenika/alpine-chrome:latest
    command: [chromium-browser, "--headless", "--disable-gpu", "--no-sandbox", "--remote-debugging-address=0.0.0.0", "--remote-debugging-port=9222"]
    ports:
      - "9222:9222"

Expected

  1. Navigate to localhost:9222
  2. Open the Chrome remote debugger
  3. type the url foo.bar
  4. have nginx reverse proxy foo.bar to (e.g.) google.com
Hitmands
  • 13,491
  • 4
  • 34
  • 69
  • You want to access chrome through nginx ? – Mostafa Hussein Jun 26 '19 at 06:55
  • I'd like to type `foo.bar` on the chrome debugger and then have it resolved by `nginx` – Hitmands Jun 26 '19 at 07:04
  • `foo.bar` is in your host's `/etc/hosts` when you do it ok on host chrome? – atline Jun 26 '19 at 07:11
  • yes, exactly... I have it on my `/etc/hosts` on my computer, so from my laptop's chrome it works just fine... the issue arises when I use the chrome-alpine – Hitmands Jun 26 '19 at 07:12
  • i was going to tell the same as @atline mentioned, you need to add it inside /etc/hosts of the container, through docker-compose use `extra_hosts` keyword this will allow the chrome container to resolve the domain name points to the container ip – Mostafa Hussein Jun 26 '19 at 07:13
  • the chrome container? `foo.bar:localhost`? I tried but didn't work out – Hitmands Jun 26 '19 at 07:14
  • I guess your format is wrong. – atline Jun 26 '19 at 07:16
  • yup, I should be typing a ip address but they are dynamically assigned... – Hitmands Jun 26 '19 at 07:16
  • have you tried as 127.0.0.1 ? /etc/hosts expects an ip not something to resolve, what do you mean by dynamically assigned ? – Mostafa Hussein Jun 26 '19 at 07:17
  • I tried it, it didn't work... could you provide an example? – Hitmands Jun 26 '19 at 07:18
  • try this one: https://stackoverflow.com/a/30541426/2336650 , it should be `foobar: 127.0.0.1` – Mostafa Hussein Jun 26 '19 at 07:18
  • What's the `foo.bar` point to in /etc/hosts on hosts? – atline Jun 26 '19 at 07:24
  • just tried, it doesn't work... nginx doesn't receive any request... I added the extra host to the chrome image and by inspecting it I can see `127.0.0.1 foo.bar` I think `127.0.0.1` should be the ip of the nginx container instead... and that's why I said it is dynamic – Hitmands Jun 26 '19 at 07:25
  • Could you try updated answer, add `container_name`, and also add extra hosts, foo.bar points to the container_name? – atline Jun 26 '19 at 07:28

3 Answers3

2

It's a pity I did not find a simple solution after trial, I guess @Mostafa Hussein 's static ip solution is the simplest one to realize the requirement.

The result from my investigation is to alias foo.bar as 127.0.0.1, and let socat to forward 127.0.0.1 network traffic to mynginx, here, socat could use mynginx which could not be used in extra_hosts:

So, my solution is next, ugly but in case anyone need it later:

version: '3'

services:
  nginx:
    image: nginx:alpine
    container_name: mynginx
    command: [nginx-debug, "-g", "daemon off;"]
    ports:
      - "444:443"

  chrome:
    image: zenika/alpine-chrome:latest
    container_name: mychrome
    command: [chromium-browser, "--headless", "--disable-gpu", "--no-sandbox", "--remote-debugging-address=0.0.0.0", "--remote-debugging-port=9222"]
    ports:
      - "9222:9222"
    extra_hosts:
      - "foo.bar:127.0.0.1"

  helper:
    image: ubuntu:16.04
    volumes:
      - /usr/bin/docker:/usr/bin/docker
      - /var/run/docker.sock:/var/run/docker.sock
      - /usr/lib/x86_64-linux-gnu/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7
    tty: true
    command: bash -c "docker exec -u root -it mychrome /bin/sh -c \"apk add socat && socat TCP4-LISTEN:80,reuseaddr,fork TCP4:mynginx:80\""
    depends_on:
      - chrome

And the test:

shubuntu1@shubuntu1:~/99$ docker exec -it mychrome wget -q -O - http://foo.bar
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
atline
  • 28,355
  • 16
  • 77
  • 113
  • it looks like you have to pass valid ips to `add_hosts`: `Cannot create container for service chrome: invalid IP address in add-host: "nginxproxy"` – Hitmands Jun 26 '19 at 07:30
  • If possible we first narrow down issue with `remove extra_hosts related, but set container_name=foo.bar`, and in browser we just input `http://foo.bar` to see if it's ok, then we try to find other solution? – atline Jun 26 '19 at 07:35
  • 1
    Seems an interesting question, I will try in local to simulate your situation. – atline Jun 26 '19 at 07:38
  • A pity I did not find a simple solution, just use `socat` to forward the traffic from `127.0.0.1` to `mynginx` is my result. I think @Mostafa Hussein solution to use static ip is good, also upvote it. – atline Jun 27 '19 at 01:34
2

I was able to make it work by defining a static IP for the nginx container like below:

Note: The purpose of setting a static IP for nginx is to avoid any issue that could happen due to ip changes.

version: "2"
services:
  nginx:
    image: nginx:alpine
    command: [nginx-debug, "-g", "daemon off;"]
    ports:
      - 80:80
    networks:
      nginx-chrome-network:
        ipv4_address: 172.28.1.1

  chrome:
    image: zenika/alpine-chrome:latest
    command: [chromium-browser, "--headless", "--disable-gpu", "--no-sandbox", "--remote-debugging-address=0.0.0.0", "--remote-debugging-port=9222"]
    ports:
      - "9222:9222"
    networks:
      - nginx-chrome-network
    extra_hosts:
      foo.bar: 172.28.1.1


networks:
  nginx-chrome-network:
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16

Then by going to localhost:9222 and opening a new tab then typing foo.bar you will get same as the following screenshot:

enter image description here

Mostafa Hussein
  • 11,063
  • 3
  • 36
  • 61
  • You are welcome @Hitmands, due to ssl issues, is it a self signed certificate ? as it works with google's website correctly, if you are using a self signed certificate you need to `Security.setIgnoreCertificateErrors` in DevTools – Mostafa Hussein Jun 26 '19 at 10:36
  • 1
    yeah, it is self signed, issue solved by starting chrome with `"--ignore-certificate-errors", "--reduce-security-for-testing",` flags – Hitmands Jun 26 '19 at 10:37
1

you need to use links under your chrome container and call nginx by nginx:port :

links:
   - nginx

or you can use network driver host for both container and call each othe by localhos:port

network: host

the network config shoud be under each service, also see this

LinPy
  • 16,987
  • 4
  • 43
  • 57
  • can you add more details? (Especially for the `network` option) since `links` has been deprecated – Hitmands Jun 26 '19 at 07:13
  • I don't think I can use the `host` network since I'd need to override the `/etc/hosts` on the ci then... – Hitmands Jun 26 '19 at 07:17
  • Linking between containers wont solve the issue as generally `foo.bar` wont be identified by the docker network anyway, it works if the container named `foo.bar` inside the docker network itself – Mostafa Hussein Jun 26 '19 at 07:23