status-im / nim-graphql

Nim implementation of GraphQL with sugar and steroids
Apache License 2.0
65 stars 6 forks source link

Can't access the server when running from docker #93

Closed EriKWDev closed 3 years ago

EriKWDev commented 3 years ago

Background

I'm trying to run the starwars example from inside a docker container, but I can't seem to get it to work. Everything builds fine and the correct messages are logged saying that the server has started on 127.0.0.1:8547 (GraphQL service started tid=406 at=http://127.0.0.1:8547/graphql), but when I actually go there I just get "This site can't be reached" (ERR_CONNECTION_REFUSED). Building outside the container, i.e. just running "nimble starwars", works fine and results in a website I can go to.

My Dockerfile

I created a Dockerfile inside the repository root as such:

FROM nimlang/nim:1.4.8
WORKDIR /app

COPY graphql.nimble .
RUN nimble install --depsOnly -y --verbose
COPY . .
RUN nim c -d:release playground/swserver

EXPOSE 8547

CMD ["./playground/swserver", "starwars"]

and run it using: docker build -t test . && docker run -p 8547:8547 -t test I have also tried: docker build -t test . && docker run --expose 8547 -t test

When I run it detached (-d), I can do docker exec <container-id> wget localhost:8547/graphql/ui and it seems to be able to connect to it. Am I forwarding the ports incorrectly?

Also tried with docker-compose

I've also tried with docker-compose.yaml

version: "3"

services:
  graphql:
    build: .
    ports:
      - 8547:8547
    expose:
      - 8547

running with docker-compose up --build -d, but doesn't work either. I have a similar project with nim using jester and it works fine from within docker running on the same machine. I have tried both on my macbook and on a debian pc and it doesn't work on either.

Any thoughts?

stefantalpalaru commented 3 years ago

127.0.0.1

The container's IP alias is different. Something like 172.17.0.1: https://forums.docker.com/t/accessing-localhost-inside-the-container-itself/43203/8

EriKWDev commented 3 years ago

Well, I don't need to access the server from within the container, nor do I want to access the host machine from the container. I just want to access the website from the host machine but have the server in the container.

When I run my other project, the jester server, in a container in the same way (with -p PORT:PORT, I can go to localhost:PORT in my web browser and reach the site without problems. I can't get it to work with the starwars example here though :/

EriKWDev commented 3 years ago

Interesting. The error message changed. Now when I run the project with -p 8547:8547 (which is supposed to forward the port from the container to the localhost of my machine), I now get "This page isn’t working. localhost didn’t send any data. ERR_EMPTY_RESPONSE" when i go to localhost:8547/graphql/ui

docker ps output:

CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                       NAMES
60c26e7f36e8   test      "./playground/swserv…"   3 minutes ago   Up 3 minutes   0.0.0.0:8547->8547/tcp, :::8547->8547/tcp   fervent_lehmann
stefantalpalaru commented 3 years ago

See the listening ports inside the container, after starting that server: ss -lntp

While you're at it, also list the network interfaces: ip address show

EriKWDev commented 3 years ago

docker exec 7acbeefab8ac ss -lntp

State    Recv-Q   Send-Q     Local Address:Port     Peer Address:Port  Process  
LISTEN   0        100            127.0.0.1:8547          0.0.0.0:*      users:(("swserver",pid=1,fd=3))

docker exec 7acbeefab8ac ip address show

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
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1000
    link/tunnel6 :: brd ::
39: eth0@if40: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
jangko commented 3 years ago

To make this work, the swserver need to bind to 0.0.0.0:port, not 127.0.0.1:port, But currently it doesn't have cli to configure it's binding address. Feel free to make a PR.

EriKWDev commented 3 years ago

That was it! Thank you so much.

I didn't reflect on it, but my jester server was indeed binding to 0.0.0.0 when in the container. I wonder how jester/httpbeast decides what address to bind to by default. Whatever their solution is should perhaps become the default here instead of hardcoded :) I'll have a look.