0
votes

The problem: (summarized) I have a Redmine running on a docker container that lives in a VM ( Centos 8, but I also tried on Ubuntu 18 server and I get the same result). When I make a request through the API Rest, I receive a "timed out" error or similar.

More Info:

  • I made a program that makes a lot of requests to a Redmine through its API Rest service. The same program was tested on Redmine that is installed locally in a VM, and everything worked perfectly. Which led me to think my program is not the problem.

  • When I write, for example, http://ip_of_my_dockerized_redmine:port/users.json ( which returns a list of users according to the Redmine api rest documentation), directly on the browser, it work just fine, and prints the json on the browser.

  • Of course, I already activated the REST web service through the web ui.

My program is written in python, so that's why I'm using the python request library to make the petitions to the server. However, I also used Postman and the result was the same. Here are some of the errors I'm receiving.

My docker compose file:

version: '3.8'

services:

  postgres:
    image: 'postgres:13'
    container_name: 'contenedor_postgres'
    restart: always
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      - 'POSTGRES_PASSWORD=<some password>'
      - 'POSTGRES_DB=redmine'

  redmine:
    image: 'redmine:4.2.1'
    container_name: 'contenedor_redmine'
    restart: always
    volumes:
      - redmine-data:/usr/src/redmine/files
      - redmine-plugins:/usr/src/redmine/plugins
    ports:
      - 3000:3000
    environment:
      - 'REDMINE_DB_POSTGRES=postgres'
      - 'REDMINE_DB_DATABASE=redmine'
      - 'REDMINE_DB_PASSWORD=<a password>'

volumes:
  postgres-data:
  redmine-data:
  redmine-plugins:

This is a Python request made from a jupyter Notebook, ( Already tested on the Redmine that runs local and worked)

# The credentials and other auth. data are stored here
from app import connection
# The request library
import requests
url = "http://ip:3000"
# The request in question.
response = requests.get( url + "/user.json", verify=False, auth=( connection.REDMINE_USER, connection.REDMINE_PASSWORD), timeout=20)
response

You can see that I already introduced the timeout=20 parameter, as it was mention in other similar posts it could work, it didn't.

The response was:

---------------------------------------------------------------------------
timeout                                   Traceback (most recent call last)
~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connection.py in _new_conn(self)
    168         try:
--> 169             conn = connection.create_connection(
    170                 (self._dns_host, self.port), self.timeout, **extra_kw

~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\util\connection.py in create_connection(address, timeout, source_address, socket_options)
     95     if err is not None:
---> 96         raise err
     97 

~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\util\connection.py in create_connection(address, timeout, source_address, socket_options)
     85                 sock.bind(source_address)
---> 86             sock.connect(sa)
     87             return sock

timeout: timed out

During handling of the above exception, another exception occurred:

ConnectTimeoutError                       Traceback (most recent call last)
~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py in urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)
    698             # Make the request on the httplib connection object.
--> 699             httplib_response = self._make_request(
    700                 conn,

~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py in _make_request(self, conn, method, url, timeout, chunked, **httplib_request_kw)
    393             else:
--> 394                 conn.request(method, url, **httplib_request_kw)
    395 

~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connection.py in request(self, method, url, body, headers)
    233             headers["User-Agent"] = _get_default_user_agent()
--> 234         super(HTTPConnection, self).request(method, url, body=body, headers=headers)
    235 

~\AppData\Local\Programs\Python\Python39\lib\http\client.py in request(self, method, url, body, headers, encode_chunked)
   1254         """Send a complete request to the server."""
-> 1255         self._send_request(method, url, body, headers, encode_chunked)
   1256 

~\AppData\Local\Programs\Python\Python39\lib\http\client.py in _send_request(self, method, url, body, headers, encode_chunked)
   1300             body = _encode(body, 'body')
-> 1301         self.endheaders(body, encode_chunked=encode_chunked)
   1302 

~\AppData\Local\Programs\Python\Python39\lib\http\client.py in endheaders(self, message_body, encode_chunked)
   1249             raise CannotSendHeader()
-> 1250         self._send_output(message_body, encode_chunked=encode_chunked)
   1251 

~\AppData\Local\Programs\Python\Python39\lib\http\client.py in _send_output(self, message_body, encode_chunked)
   1009         del self._buffer[:]
-> 1010         self.send(msg)
   1011 

~\AppData\Local\Programs\Python\Python39\lib\http\client.py in send(self, data)
    949             if self.auto_open:
--> 950                 self.connect()
    951             else:

~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connection.py in connect(self)
    199     def connect(self):
--> 200         conn = self._new_conn()
    201         self._prepare_conn(conn)

~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connection.py in _new_conn(self)
    173         except SocketTimeout:
--> 174             raise ConnectTimeoutError(
    175                 self,

ConnectTimeoutError: (<urllib3.connection.HTTPConnection object at 0x000000B37871A940>, 'Connection to <my_vm_ip> timed out. (connect timeout=20)')

During handling of the above exception, another exception occurred:

MaxRetryError                             Traceback (most recent call last)
~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\adapters.py in send(self, request, stream, timeout, verify, cert, proxies)
    438             if not chunked:
--> 439                 resp = conn.urlopen(
    440                     method=request.method,

~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py in urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)
    754 
--> 755             retries = retries.increment(
    756                 method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2]

~\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\util\retry.py in increment(self, method, url, response, error, _pool, _stacktrace)
    572         if new_retry.is_exhausted():
--> 573             raise MaxRetryError(_pool, url, error or ResponseError(cause))
    574 

MaxRetryError: HTTPConnectionPool(host='<my_vm_ip>', port=3000): Max retries exceeded with url: /user.json (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000000B37871A940>, 'Connection to <my_vm_ip> timed out. (connect timeout=20)'))

During handling of the above exception, another exception occurred:

ConnectTimeout                            Traceback (most recent call last)
<ipython-input-3-dc378d70e4d9> in <module>
----> 1 response = requests.get( url + "/user.json", verify=False, auth=( connection.REDMINE_USER, connection.REDMINE_PASSWORD), timeout=20)
      2 
      3 response

~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\api.py in get(url, params, **kwargs)
     74 
     75     kwargs.setdefault('allow_redirects', True)
---> 76     return request('get', url, params=params, **kwargs)
     77 
     78 

~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\api.py in request(method, url, **kwargs)
     59     # cases, and look like a memory leak in others.
     60     with sessions.Session() as session:
---> 61         return session.request(method=method, url=url, **kwargs)
     62 
     63 

~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\sessions.py in request(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)
    540         }
    541         send_kwargs.update(settings)
--> 542         resp = self.send(prep, **send_kwargs)
    543 
    544         return resp

~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\sessions.py in send(self, request, **kwargs)
    653 
    654         # Send the request
--> 655         r = adapter.send(request, **kwargs)
    656 
    657         # Total elapsed time of the request (approximately)

~\AppData\Local\Programs\Python\Python39\lib\site-packages\requests\adapters.py in send(self, request, stream, timeout, verify, cert, proxies)
    502                 # TODO: Remove this in 3.0.0: see #2811
    503                 if not isinstance(e.reason, NewConnectionError):
--> 504                     raise ConnectTimeout(e, request=request)
    505 
    506             if isinstance(e.reason, ResponseError):

ConnectTimeout: HTTPConnectionPool(host='<my_vm_ip>', port=3000): Max retries exceeded with url: /user.json (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000000B37871A940>, 'Connection to <my_vm_ip> timed out. (connect timeout=20)'))

Trying to make the same request with Postman gives the same result:

GET http://<my_vm_ip>:3000/users.json
Error: connect ETIMEDOUT <my_vm_ip>:3000
Request Headers
Authorization: Basic YW***************mQ=
User-Agent: PostmanRuntime/7.28.1
Accept: */*
Postman-Token: b52f****************3de0fbe
Host: <my_vm_ip>:3000
Accept-Encoding: gzip, deflate, br
Connection: keep-alive

I have the feeling, that it might be a problem related to Docker, but i don't know. I'm not an expert on Docker tbh.

Edit#1: Just for the purposes of an update, I tried to make the ports accesible to the firewall ( In this case firewalld since is Redhat), so:

firewall-cmd --permanent --add-port=3000/tcp

and

firewall-cmd --permanent --add-port=5432/tcp

returns succeed but the result is the same. Not working.

Edit#2: I also tried using the library python-redmine, but the result is similar.

TimeoutError: [WinError 10060]
1
Have you checked redmine logs (docker logs contenedor_redmine)? Can you see requests that end up with a timeout in logs? - anemyte
I did and the funny thing is that I don't receive any registry of my petition. The only way I do is when I make the request explicitly on the web browser, then the last log is ip_vm:3000/my/page -> / ip_requesting - - [10/Jun/2021:05:35:34 UTC] "GET /users.json HTTP/1.1" 200 329 - -> /users.json Which is what should look the other way too. - Fède Olut

1 Answers

0
votes

Excuse my question but it is not mentioned: Can you access your Redmine instance through http and have you enabled the Rest API from there?

Eliminating that I would look in the VM firewall settings to see if 3000 can be accessed.

For a quick test you can set docker to expose your redmine's 3000 port through port 80:

redmine:
    image: 'redmine:4.2.1'
    container_name: 'contenedor_redmine'
    ...
    ports:
      - 80:3000
    ...