Pascal
Pascal

Reputation: 2984

Executing a python3 script with TCP Server on Docker startup though shell script throws [Errno 111] Connection refused

I've developed some Python3 scripts to run on top of the Standalone Selenium Chrome image with a TCP Server to execute some process that collects some information created during testing, and that are inside the container. Whenever I need to start the python3 process, I connect to it through a TCP Client, send some commands, and the python3 script does what I need it to do.
On my dockerfile, I install pip3 and everything I need, and I copy over all the scripts that I need, and everything works perfectly if I manually access the docker container, and I start the python3 script manually, like this:

docker exec -it selc bash
cd /home/seluser/python/
sudo nohup python3 myscript.py &

This successfully start my python3 script on the background, and it runs great

seluser@24d2713db5f1:~/python$ sudo nohup python3 myscript.py &
[1] 71
seluser@24d2713db5f1:~/python$ nohup: ignoring input and appending output to 'nohup.out'

However, I would like to execute this script automatically whenever I start my container, and I haven't being able to do this successfully. I get a ConnectionRefusedError: [Errno 111] Connection refused error in the container logs when I run the container. Below is my dockerfile

FROM selenium/standalone-chrome-debug

USER root

RUN apt-get update &&\
    apt-get upgrade -y &&\
    apt-get install python3-pip -y &&\
    apt-get install dos2unix -y &&\
    pip3 install pynput &&\
    pip3 install azure.storage.blob &&\
    apt-get install vim -y

USER seluser

EXPOSE 9871

RUN mkdir -p /home/seluser/upload &&\
    mkdir -p /home/seluser/python &&\
    mkdir -p /home/seluser/logs &&\
    mkdir -p /home/seluser/debug

ADD /python /home/seluser/python

USER root

COPY entry_point.sh /opt/bin/entry_point.sh

RUN dos2unix /opt/bin/entry_point.sh &&\
    chmod a+x /opt/bin/entry_point.sh

USER seluser

Below is the shell script entry_point.sh that I got from the selenium github, with just a modification to run my script

#!/usr/bin/env bash

if ! whoami &> /dev/null; then
  if [ -w /etc/passwd ]; then
    echo "${USER_NAME:-default}:x:$(id -u):0:${USER_NAME:-default} user:${HOME}:/sbin/nologin" >> /etc/passwd
  fi
fi

/usr/bin/supervisord --configuration /etc/supervisord.conf &

SUPERVISOR_PID=$!

function shutdown {
    echo "Trapped SIGTERM/SIGINT/x so shutting down supervisord..."
    kill -s SIGTERM ${SUPERVISOR_PID}
    wait ${SUPERVISOR_PID}
    echo "Shutdown complete"
}

echo "Starting script PYTHON3"
nohup python3 /home/seluser/python/myscript.py &
echo "script PYTHON3 started"

trap shutdown SIGTERM SIGINT
wait ${SUPERVISOR_PID}

This is the myscript.py that I start

import asyncio
import logging
import time

from servico.myserver import myServer
from auxiliar.objlog import ObjLog
from auxiliar.objip import ObjIp

logger = ObjLog().executar()

logger.debug("Starting execution")

time.sleep(3)

logger.debug("Getting connection")

loop = asyncio.get_event_loop()
stream_server = myServer(loop)
# ip = ObjIp().executar()
# logger.debug('IP:' + ip)

coro_server = asyncio.start_server(
    stream_server.server_handler,
    '0.0.0.0',
    9871,
    loop=stream_server.loop
)

server = loop.run_until_complete(coro_server)

logger.debug('Pre-execution')
logger = ObjLog().executar()
logger.debug('Listening:' + str(server.sockets[0].getsockname()))

try:
    loop.run_forever()
except KeyboardInterrupt:
    pass

print('Closing Server')
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()

I start the container using this docker run command

docker run --name selc --detach --rm -p 4444:4444 -p 5900:5900 -p 9871:9871 mydocker/selenium-debug-chrome:latest

The log that I get when I start then container is below

λ  docker logs selc                                                                                                     
Iniciando script PYTHON3                                                                                                
script PYTHON3 iniciado                                                                                                 
Traceback (most recent call last):                                                                                      
  File "/usr/local/lib/python3.6/dist-packages/Xlib/support/unix_connect.py", line 119, in get_socket                   
    s = _get_unix_socket(address)                                                                                       
  File "/usr/local/lib/python3.6/dist-packages/Xlib/support/unix_connect.py", line 98, in _get_unix_socket              
    s.connect(address)                                                                                                  
ConnectionRefusedError: [Errno 111] Connection refused                                                                  

During handling of the above exception, another exception occurred:                                                     

Traceback (most recent call last):                                                                                      
  File "/usr/local/lib/python3.6/dist-packages/Xlib/support/unix_connect.py", line 123, in get_socket                   
    s = _get_tcp_socket(host, dno)                                                                                      
  File "/usr/local/lib/python3.6/dist-packages/Xlib/support/unix_connect.py", line 93, in _get_tcp_socket               
    s.connect((host, 6000 + dno))                                                                                       
ConnectionRefusedError: [Errno 111] Connection refused                                                                  

During handling of the above exception, another exception occurred:                                                     

Traceback (most recent call last):                                                                                      
  File "/home/seluser/python/my.py", line 5, in <module>                                                      
    from servico.myserver import myServer                                                           
  File "/home/seluser/python/servico/myserver.py", line 7, in <module>                                        
    from servico.tarefas.download_pdf import DownloadPdf                                                                
  File "/home/seluser/python/servico/tarefas/download_pdf.py", line 5, in <module>                                      
    from pynput.keyboard import Key, Controller                                                                         
  File "/usr/local/lib/python3.6/dist-packages/pynput/__init__.py", line 23, in <module>                                
    from . import keyboard                                                                                              
  File "/usr/local/lib/python3.6/dist-packages/pynput/keyboard/__init__.py", line 49, in <module>                       
    from ._xorg import KeyCode, Key, Controller, Listener                                                               
  File "/usr/local/lib/python3.6/dist-packages/pynput/keyboard/_xorg.py", line 39, in <module>                          
    from pynput._util.xorg import (                                                                                     
  File "/usr/local/lib/python3.6/dist-packages/pynput/_util/xorg.py", line 40, in <module>                              
    _check()                                                                                                            
  File "/usr/local/lib/python3.6/dist-packages/pynput/_util/xorg.py", line 38, in _check                                
    display = Xlib.display.Display()                                                                                    
  File "/usr/local/lib/python3.6/dist-packages/Xlib/display.py", line 89, in __init__                                   
    self.display = _BaseDisplay(display)                                                                                
  File "/usr/local/lib/python3.6/dist-packages/Xlib/display.py", line 71, in __init__                                   
    protocol_display.Display.__init__(self, *args, **keys)                                                              
  File "/usr/local/lib/python3.6/dist-packages/Xlib/protocol/display.py", line 89, in __init__                          
    self.socket = connect.get_socket(name, protocol, host, displayno)                                                   
  File "/usr/local/lib/python3.6/dist-packages/Xlib/support/connect.py", line 87, in get_socket
    return mod.get_socket(dname, protocol, host, dno)
  File "/usr/local/lib/python3.6/dist-packages/Xlib/support/unix_connect.py", line 127, in get_socket
    raise error.DisplayConnectionError(dname, str(val))
Xlib.error.DisplayConnectionError: Can't connect to display ":99.0": [Errno 111] Connection refused
2019-03-16 14:00:59,881 INFO Included extra file "/etc/supervisor/conf.d/selenium-debug.conf" during parsing
2019-03-16 14:00:59,881 INFO Included extra file "/etc/supervisor/conf.d/selenium.conf" during parsing
2019-03-16 14:00:59,885 INFO supervisord started with pid 7
2019-03-16 14:01:00,887 INFO spawned: 'xvfb' with pid 13
2019-03-16 14:01:00,888 INFO spawned: 'fluxbox' with pid 14
2019-03-16 14:01:00,890 INFO spawned: 'vnc' with pid 15
2019-03-16 14:01:00,891 INFO spawned: 'selenium-standalone' with pid 16
2019-03-16 14:01:01,016 INFO success: xvfb entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)2019-03-16 14:01:01,016 INFO success: fluxbox entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
2019-03-16 14:01:01,016 INFO success: vnc entered RUNNING state, process has stayed up for > than 0 seconds (startsecs) 2019-03-16 14:01:01,017 INFO success: selenium-standalone entered RUNNING state, process has stayed up for > than 0 seconds (startsecs)
14:01:01.332 INFO [GridLauncherV3.parse] - Selenium server version: 3.141.59, revision: e82be7d358
14:01:01.429 INFO [GridLauncherV3.lambda$buildLaunchers$3] - Launching a standalone Selenium Server on port 4444
2019-03-16 14:01:01.489:INFO::main: Logging initialized @570ms to org.seleniumhq.jetty9.util.log.StdErrLog
14:01:01.822 INFO [WebDriverServlet.<init>] - Initialising WebDriverServlet
14:01:01.941 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444    

If I connect to it manually though bash, and start it the same way I've pointed out, it works fine. It just won't work on startup.

Why am I getting this error? Is there other way to start my python3 script automatically after my container starts? Thank you very much for any help.

EDIT

Based on the base image, it already has an entry point to the shell script. Looking at docker inspect I can see it.

λ  docker inspect selc
[
    {
        "Id": "24d2713db5f13be0c69479a27f6ea4c943d194edbe3b2fa303aaac966639694e",
        "Created": "2019-03-16T14:31:43.6236537Z",
        "Path": "/opt/bin/entry_point.sh",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 34191,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2019-03-16T14:31:44.2388239Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },

I preferred not to change the mechanics of how to base image works, just tuned it a bit to try to execute my script using the existing code. But I'm open to ideas, since I don't know what to do.

Upvotes: 1

Views: 717

Answers (1)

Mostafa Hussein
Mostafa Hussein

Reputation: 11980

Since you are having supervisord a better approach would be running the python script through it instead of using nohup. So create a file like myscript.conf

[program:myscript]
command=/usr/bin/python3 /home/seluser/python/myscript.py
autostart=true
autorestart=true
startretries=3
user=seluser

And in your Dockerfile Replace the following lines:

COPY entry_point.sh /opt/bin/entry_point.sh

RUN dos2unix /opt/bin/entry_point.sh &&\
    chmod a+x /opt/bin/entry_point.sh

With this one below:

According to the main configuration file of docker-selenium, any additional config should be add to /etc/supervisor/conf.d/

COPY myscript.conf /etc/supervisor/conf.d/

And there is no need to modifying the entrypoint script since we replace nohup with supervisord config file

Upvotes: 2

Related Questions