Connecting from Another Application

Attempting to connect to quantrocket-client from another docker container and I am unable to establish a connection.

I added my container to the docker-compose.override.yml file
image

I expose port 80, set HOUSTON_URL environment variable, and install quantrocket-client in the docker image.


Processing: qr_ping_output.txt...

Verified the variable took:
image

I am running Quantrocket in WSL2 and the container I am trying to connect with Houston is local, so I should only need to set the environment variable:
image

I am still pretty new to programming, so maybe I am missing something obvious. Below I include the Output from a 'ping' to Houston. Below the long output is the Houston container log.

Running the following in the new container:
from quantrocket.houston import ping
ping()

Output:

ConnectionRefusedError Traceback (most recent call last)
File /usr/local/lib/python3.9/dist-packages/urllib3/connection.py:203, in HTTPConnection._new_conn(self)
202 try:
--> 203 sock = connection.create_connection(
204 (self._dns_host, self.port),
205 self.timeout,
206 source_address=self.source_address,
207 socket_options=self.socket_options,
208 )
209 except socket.gaierror as e:

File /usr/local/lib/python3.9/dist-packages/urllib3/util/connection.py:85, in create_connection(address, timeout, source_address, socket_options)
84 try:
---> 85 raise err
86 finally:
87 # Break explicitly a reference cycle

File /usr/local/lib/python3.9/dist-packages/urllib3/util/connection.py:73, in create_connection(address, timeout, source_address, socket_options)
72 sock.bind(source_address)
---> 73 sock.connect(sa)
74 # Break explicitly a reference cycle

ConnectionRefusedError: [Errno 111] Connection refused

The above exception was the direct cause of the following exception:

NewConnectionError Traceback (most recent call last)
File /usr/local/lib/python3.9/dist-packages/urllib3/connectionpool.py:790, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw)
789 # Make the request on the HTTPConnection object
--> 790 response = self._make_request(
791 conn,
792 method,
793 url,
794 timeout=timeout_obj,
795 body=body,
796 headers=headers,
797 chunked=chunked,
798 retries=retries,
799 response_conn=response_conn,
800 preload_content=preload_content,
801 decode_content=decode_content,
802 **response_kw,
803 )
805 # Everything went great!

File /usr/local/lib/python3.9/dist-packages/urllib3/connectionpool.py:496, in HTTPConnectionPool._make_request(self, conn, method, url, body, headers, retries, timeout, chunked, response_conn, preload_content, decode_content, enforce_content_length)
495 try:
--> 496 conn.request(
497 method,
498 url,
499 body=body,
500 headers=headers,
501 chunked=chunked,
502 preload_content=preload_content,
503 decode_content=decode_content,
504 enforce_content_length=enforce_content_length,
505 )
507 # We are swallowing BrokenPipeError (errno.EPIPE) since the server is
508 # legitimately able to close the connection after sending a valid response.
509 # With this behaviour, the received response is still readable.

File /usr/local/lib/python3.9/dist-packages/urllib3/connection.py:395, in HTTPConnection.request(self, method, url, body, headers, chunked, preload_content, decode_content, enforce_content_length)
394 self.putheader(header, value)
--> 395 self.endheaders()
397 # If we're given a body we start sending that in chunks.

File /usr/lib/python3.9/http/client.py:1250, in HTTPConnection.endheaders(self, message_body, encode_chunked)
1249 raise CannotSendHeader()
-> 1250 self._send_output(message_body, encode_chunked=encode_chunked)

File /usr/lib/python3.9/http/client.py:1010, in HTTPConnection._send_output(self, message_body, encode_chunked)
1009 del self._buffer[:]
-> 1010 self.send(msg)
1012 if message_body is not None:
1013
1014 # create a consistent interface to message_body

File /usr/lib/python3.9/http/client.py:950, in HTTPConnection.send(self, data)
949 if self.auto_open:
--> 950 self.connect()
951 else:

File /usr/local/lib/python3.9/dist-packages/urllib3/connection.py:243, in HTTPConnection.connect(self)
242 def connect(self) -> None:
--> 243 self.sock = self._new_conn()
244 if self._tunnel_host:
245 # If we're tunneling it means we're connected to our proxy.

File /usr/local/lib/python3.9/dist-packages/urllib3/connection.py:218, in HTTPConnection._new_conn(self)
217 except OSError as e:
--> 218 raise NewConnectionError(
219 self, f"Failed to establish a new connection: {e}"
220 ) from e
222 # Audit hooks are only available in Python 3.8+

NewConnectionError: : Failed to establish a new connection: [Errno 111] Connection refused

The above exception was the direct cause of the following exception:

MaxRetryError Traceback (most recent call last)
File /usr/local/lib/python3.9/dist-packages/requests/adapters.py:486, in HTTPAdapter.send(self, request, stream, timeout, verify, cert, proxies)
485 try:
--> 486 resp = conn.urlopen(
487 method=request.method,
488 url=url,
489 body=request.body,
490 headers=request.headers,
491 redirect=False,
492 assert_same_host=False,
493 preload_content=False,
494 decode_content=False,
495 retries=self.max_retries,
496 timeout=timeout,
497 chunked=chunked,
498 )
500 except (ProtocolError, OSError) as err:

File /usr/local/lib/python3.9/dist-packages/urllib3/connectionpool.py:844, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw)
842 new_e = ProtocolError("Connection aborted.", new_e)
--> 844 retries = retries.increment(
845 method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
846 )
847 retries.sleep()

File /usr/local/lib/python3.9/dist-packages/urllib3/util/retry.py:515, in Retry.increment(self, method, url, response, error, _pool, _stacktrace)
514 reason = error or ResponseError(cause)
--> 515 raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
517 log.debug("Incremented Retry for (url='%s'): %r", url, new_retry)

MaxRetryError: HTTPConnectionPool(host='localhost', port=1969): Max retries exceeded with url: /ping (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))

During handling of the above exception, another exception occurred:

ConnectionError Traceback (most recent call last)
File /usr/local/lib/python3.9/dist-packages/quantrocket/houston.py:183, in Houston.request(self, method, url, *args, **kwargs)
182 try:
--> 183 return super(Houston, self).request(
184 method, url, *args, headers=self.headers, **kwargs)
185 except requests.ConnectionError as error:

File /usr/local/lib/python3.9/dist-packages/requests/sessions.py:589, in Session.request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
588 send_kwargs.update(settings)
--> 589 resp = self.send(prep, **send_kwargs)
591 return resp

File /usr/local/lib/python3.9/dist-packages/requests/sessions.py:703, in Session.send(self, request, **kwargs)
702 # Send the request
--> 703 r = adapter.send(request, **kwargs)
705 # Total elapsed time of the request (approximately)

File /usr/local/lib/python3.9/dist-packages/requests/adapters.py:519, in HTTPAdapter.send(self, request, stream, timeout, verify, cert, proxies)
517 raise SSLError(e, request=request)
--> 519 raise ConnectionError(e, request=request)
521 except ClosedPoolError as e:

ConnectionError: HTTPConnectionPool(host='localhost', port=1969): Max retries exceeded with url: /ping (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))

During handling of the above exception, another exception occurred:

CannotConnectToHouston Traceback (most recent call last)
Cell In[1], line 2
1 from quantrocket.houston import ping
----> 2 ping()

File /usr/local/lib/python3.9/dist-packages/quantrocket/houston.py:244, in ping()
235 def ping() -> dict[str, str]:
236 """
237 Pings houston.
238
(...)
242 reply from houston
243 """
--> 244 response = houston.get("/ping")
245 houston.raise_for_status_with_json(response)
246 return response.json()

File /usr/local/lib/python3.9/dist-packages/requests/sessions.py:602, in Session.get(self, url, **kwargs)
594 r"""Sends a GET request. Returns :class:Response object.
595
596 :param url: URL for the new :class:Request object.
597 :param **kwargs: Optional arguments that request takes.
598 :rtype: requests.Response
599 """
601 kwargs.setdefault("allow_redirects", True)
--> 602 return self.request("GET", url, **kwargs)

File /usr/local/lib/python3.9/dist-packages/quantrocket/houston.py:202, in Houston.request(self, method, url, *args, **kwargs)
195 if parsed.port == 443:
196 raise CannotConnectToHouston(CANNOT_CONNECT_TO_HOUSTON_ERROR_CLOUD.format(
197 error=error,
198 scheme=parsed.scheme,
199 netloc=parsed.netloc
200 ))
--> 202 raise CannotConnectToHouston(CANNOT_CONNECT_TO_HOUSTON_ERROR_LOCAL.format(
203 error=error,
204 scheme=parsed.scheme,
205 netloc=parsed.netloc,
206 port=parsed.port
207 ))

CannotConnectToHouston: HTTPConnectionPool(host='localhost', port=1969): Max retries exceeded with url: /ping (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 111] Connection refused'))

Could not connect to houston at http://localhost:1969

Please verify that houston is running and bound to port 1969 by checking the output of:

docker ps

The output should resemble:

quantrocket/houston ... 0.0.0.0:1969->80/tcp ... quantrocket_houston_1
...

If not running you can deploy it with:

docker-compose -p quantrocket up -d

HOUSTON Container Log:
2023-07-28 10:05:45 no BASIC_AUTH_USER found so not creating .htpasswd file
2023-07-28 10:05:45 LETSENCRYPT_DOMAIN not set so not installing SSL
2023-07-28 10:05:50 172.23.0.7 - - [28/Jul/2023:14:05:50 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:05:50 172.23.0.18 - - [28/Jul/2023:14:05:50 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:05:59 172.23.0.12 - - [28/Jul/2023:14:05:59 +0000] "POST /ibgrouter/registration/ibg1 HTTP/1.1" 200 5 "-" "python-requests/2.27.1"
2023-07-28 10:06:08 172.23.0.7 - - [28/Jul/2023:14:06:08 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:06:08 172.23.0.20 - - [28/Jul/2023:14:06:08 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:06:51 172.23.0.7 - - [28/Jul/2023:14:06:51 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:06:51 172.23.0.18 - - [28/Jul/2023:14:06:51 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:07:08 172.23.0.7 - - [28/Jul/2023:14:07:08 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:07:08 172.23.0.20 - - [28/Jul/2023:14:07:08 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:07:53 172.23.0.7 - - [28/Jul/2023:14:07:53 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:07:53 172.23.0.18 - - [28/Jul/2023:14:07:53 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:08:08 172.23.0.7 - - [28/Jul/2023:14:08:08 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:08:08 172.23.0.20 - - [28/Jul/2023:14:08:08 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:08:09 172.23.0.18 - - [28/Jul/2023:14:08:09 +0000] "GET /master/securities.csv?vendors=ibkr&fields=ibkr_ConId HTTP/1.1" 200 276572 "-" "python-urllib3/1.26.8"
2023-07-28 10:08:09 172.23.0.18 - - [28/Jul/2023:14:08:09 +0000] "GET /master/securities.csv?vendors=alpaca&fields=alpaca_AssetId HTTP/1.1" 400 139 "-" "python-urllib3/1.26.8"
2023-07-28 10:08:54 172.23.0.7 - - [28/Jul/2023:14:08:54 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:08:54 172.23.0.18 - - [28/Jul/2023:14:08:54 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:08:59 172.23.0.12 - - [28/Jul/2023:14:08:59 +0000] "POST /ibgrouter/registration/ibg1 HTTP/1.1" 200 5 "-" "python-requests/2.27.1"
2023-07-28 10:09:08 172.23.0.7 - - [28/Jul/2023:14:09:08 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:09:08 172.23.0.20 - - [28/Jul/2023:14:09:08 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:09:56 172.23.0.7 - - [28/Jul/2023:14:09:56 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:09:56 172.23.0.18 - - [28/Jul/2023:14:09:56 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:10:02 172.23.0.9 - - [28/Jul/2023:14:10:02 +0000] "GET /account/balances.csv?latest=True&fields=NetLiquidation&fields=Paper HTTP/1.1" 200 143 "-" "python-urllib3/1.26.8"
2023-07-28 10:10:08 172.23.0.7 - - [28/Jul/2023:14:10:08 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:10:08 172.23.0.20 - - [28/Jul/2023:14:10:08 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:10:09 172.23.0.7 - - [28/Jul/2023:14:10:09 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:10:09 172.23.0.18 - - [28/Jul/2023:14:10:09 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:10:47 172.23.0.18 - - [28/Jul/2023:14:10:47 +0000] "GET /master/securities.csv?vendors=ibkr&fields=ibkr_ConId HTTP/1.1" 200 276572 "-" "python-urllib3/1.26.8"
2023-07-28 10:10:47 172.23.0.18 - - [28/Jul/2023:14:10:47 +0000] "GET /master/securities.csv?vendors=alpaca&fields=alpaca_AssetId HTTP/1.1" 400 139 "-" "python-urllib3/1.26.8"
2023-07-28 10:10:58 172.23.0.7 - - [28/Jul/2023:14:10:58 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:10:58 172.23.0.18 - - [28/Jul/2023:14:10:58 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:11:08 172.23.0.7 - - [28/Jul/2023:14:11:08 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:11:08 172.23.0.20 - - [28/Jul/2023:14:11:08 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:11:59 172.23.0.7 - - [28/Jul/2023:14:11:59 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:11:59 172.23.0.18 - - [28/Jul/2023:14:11:59 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:11:59 172.23.0.12 - - [28/Jul/2023:14:11:59 +0000] "POST /ibgrouter/registration/ibg1 HTTP/1.1" 200 5 "-" "python-requests/2.27.1"
2023-07-28 10:12:08 172.23.0.7 - - [28/Jul/2023:14:12:08 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:12:08 172.23.0.20 - - [28/Jul/2023:14:12:08 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:13:01 172.23.0.7 - - [28/Jul/2023:14:13:01 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:13:01 172.23.0.18 - - [28/Jul/2023:14:13:01 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:13:08 172.23.0.7 - - [28/Jul/2023:14:13:08 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:13:08 172.23.0.20 - - [28/Jul/2023:14:13:08 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:14:02 172.23.0.7 - - [28/Jul/2023:14:14:02 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:14:02 172.23.0.18 - - [28/Jul/2023:14:14:02 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"
2023-07-28 10:14:09 172.23.0.7 - - [28/Jul/2023:14:14:09 +0000] "GET /ibg1/gateway HTTP/1.1" 200 22 "-" "python-requests/2.27.1"
2023-07-28 10:14:09 172.23.0.20 - - [28/Jul/2023:14:14:09 +0000] "GET /ibgrouter/gateways?status=running HTTP/1.1" 200 9 "-" "python-urllib3/1.26.8"

http://localhost:1969 is for accessing Houston from outside the Docker network. For container-to-container communication within the Docker network, use http://houston as the HOUSTON_URL.