skip to Main Content

Ihave configured gitlab in my ubunutu machine, I have also registered runner(docker) in my local machine, So when the pipeline run. I’m getting this error

fatal: unable to access 'http://127.0.0.1/gitlab-instance-0daf0d62/car-assembly-line.git/': Failed to connect to 127.0.0.1 port 80 after 0 ms: Connection refused
ERROR: Job failed: exit code 1

I have setup gitlab in my machine and registered the runner(docker) in the same machine, so when I triggeer the pipeline build is failing

2

Answers


  1. Firstly, I would discourage you from running the runner on the same machine as you’re running your Gitlab instance (many reasons, mainly security)


    On the topic of your problem – when running gitlab runner with the docker executor you’re running the runner itself (not just the CI jobs, but the "manager" too) in a docker container.
    For that docker container "localhost" means itown local (virtual) interface.

    If we look at my development machine I have 3 interfaces;

    • lo which is loopback, also known as localhost
    • ens18 which is my "public" interface, exposed to the network to which the machine is connected
    • docker0 which is the default virtual docker interface
    [root@dev3 ~]# ip a
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host
           valid_lft forever preferred_lft forever
    2: ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
        link/ether a2:b3:48:fa:40:22 brd ff:ff:ff:ff:ff:ff
        altname enp0s18
        inet 10.10.10.117/24 brd 10.10.10.255 scope global ens18
           valid_lft forever preferred_lft forever
        inet6 fe80::a0b3:48ff:fefa:4022/64 scope link
           valid_lft forever preferred_lft forever
    3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
        link/ether 02:42:23:ae:df:4d brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
           valid_lft forever preferred_lft forever
        inet6 fe80::42:23ff:feae:df4d/64 scope link
           valid_lft forever preferred_lft forever
    [root@dev3 ~]#
    

    If I start up an nginx container, bind it to port 80 and curl localhost from the host machine I will get the default nginx response.

    docker run -ti --rm -p 80:80 nginx
    
    [root@dev3 ~]# docker ps
    CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                               NAMES
    7c37177b8e16   nginx     "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp   eager_swartz
    [root@dev3 ~]#
    [root@dev3 ~]#
    [root@dev3 ~]# curl localhost
    <!DOCTYPE html>
    ...html...
    <title>Welcome to nginx!</title>
    ...styling...
    <body>
    <h1>Welcome to nginx!</h1>
    ...html...
    </html>
    [root@dev3 ~]#
    [root@dev3 ~]#
    [root@dev3 ~]# docker exec -ti eager_swartz curl localhost
    <!DOCTYPE html>
    ...html...
    <title>Welcome to nginx!</title>
    ...styling...
    <body>
    <h1>Welcome to nginx!</h1>
    ...html...
    </html>
    [root@dev3 ~]#
    

    I truncated the content as it’s irrelevant, just know that we reached the nginx container.

    If we now look at the nginx logs we’ll see two reqests coming from two different addresses, the first one from our host machine and the second one coming from the container itself.

    172.17.0.1 - - [19/Mar/2023:11:41:47 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.88.1-DEV" "-"
    127.0.0.1 - - [19/Mar/2023:11:44:59 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.74.0" "-"
    

    If I start up another container, this time httpd (aka. Apache2) for example, and run curl localhost inside it, just like I did with nginx, you see that we get the Apache’s default page, not the one from nginx.

    [root@dev3 ~]# docker run -d --rm httpd
    5d21f4ed3595e348d258a538aed769f501ec286ccffdea430a334f1121ece9c2
    [root@dev3 ~]# docker ps
    CONTAINER ID   IMAGE          COMMAND                  CREATED              STATUS              PORTS                               NAMES
    5d21f4ed3595   httpd:alpine   "httpd-foreground"       About a minute ago   Up About a minute   80/tcp                              vigorous_panini
    7c37177b8e16   nginx          "/docker-entrypoint.…"   14 minutes ago       Up 14 minutes       0.0.0.0:80->80/tcp, :::80->80/tcp   eager_swartz
    [root@dev3 ~]# docker exec -ti vigorous_panini curl localhost
    <html><body><h1>It works!</h1></body></html>
    [root@dev3 ~]#
    

    And as you can see running curl localhost returns the webpage contents of the default httpd page.

    If we wanted to get the nginx page from the httpd container we would have to first find the internal address of the host machine in the docker network. Remember the docker0 interface of the host machine? We’ll need it now.

    [root@dev3 ~]# ip r
    default via 10.10.10.3 dev ens18 proto static
    10.10.10.0/24 dev ens18 proto kernel scope link src 10.10.10.117
    172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
    

    At the very end of the third line, where docker0 is listed you can see the address of this interface – 172.17.0.1.

    if we curl 172.17.0.1 from the httpd container, instead of getting the default apache page, we get the nginx page.

    [root@dev3 ~]# docker exec -ti vigorous_panini curl 172.17.0.1
    <!DOCTYPE html>
    ...html...
    <title>Welcome to nginx!</title>
    ...styling...
    <body>
    <h1>Welcome to nginx!</h1>
    ...html...
    </html>
    [root@dev3 ~]#
    

    If we curled 10.10.10.117 – which is the "public" address of the host machine – we’d get the same result.


    What have we learned?

    "localhost" is very relative term. It (in vast majority of situations) means the environment you’re currently in. For containers it means the container itself, not the host.


    What you have to do is instead of connecting with your runner to http://localhost, you should connect to your machine’s internal docker address (if you read the post you know how to get it).

    You could also tell it to connect to your public address.

    All of this, of course, only matters if you’re running the gitlab-runner on the same machine as your gitlab instance. If you were running the runner on another machine you’d have to use the public address anyway, so you wouldn’t have this problem in the first place.

    Login or Signup to reply.
  2. Try changing "localhost" to "host.docker.internal"

    When the runner is using the docker executor it starts a docker container that runs your jobs.
    Inside the container the localhost refers to the container’s IP address which is not the same one as the host’s IP address. In order to reach the host you’ll need to use "host.docker.internal" (make sure that the host is accessible through localhost in the desired port).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search