Reputation: 2984
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
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