Docker container with published port not accessible from outside - ruby-on-rails

My Docker container is running Rails on port 3000, and I'm publishing the port to port 8900. See:
$ docker-compose ps
Name Command State Ports
rails_poc_1 /bin/sh -c puma -C config/ ... Up 0.0.0.0:3000->8900/tcp
However, when visiting http://localhost:8900 my browser displays ERR_CONNECTION_REFUSED.
When curling port 3000 from inside the container with docker exec 8fcceed1d477 curl localhost:3000 I get a valid response which proves Rails is working properly.
Am I overlooking something?

I think you have your port mapping reversed. Your ps line should look more like:
0.0.0.0:8900->3000/tcp
If you want to access 3000 outside the container as 8900

Related

expose docker container's application url to host

I have a docker image with some ruby on rails environment built in (i.e. installing some rails gems and system packages) and I have an EXPOSE 3000 to expose the port at the end.
I ran a container with docker run -p 3000:3000 -ti <image> bash, then start the rails server. The logs are saying the web server is available on localhost:3000. I tried to connect to both the IPAddress as specified in docker inspect <id> and localhost on my host machine, but neither would be able to connect. What could be the problem here?
If your application is listening on localhost, it will only respond to requests from the container's localhost - that is, other processes inside the container.
To fix this you need to set the listen address of your server to listen to any address (usually, you specify this as 0.0.0.0). I've never used rails, but from a quick search, you should use the -b option.
So changing your ENTRYPOINT or CMD in your Dockerfile to contain -b 0.0.0.0 would probably do it.

Issue with running HAProxy locally on docker

I have a container running HAProxy version 2.0 locally on Docker port 3001.
Config file is:
global
debug
defaults
log global
mode http
timeout connect 50000
timeout client 50000
timeout server 50000
frontend main
bind *:3000
default_backend app
backend app
balance leastconn
mode http
server dummy <localhostIP>:80
Docker file is:
FROM haproxy:2.0
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
Docker Run command:
docker run -p3001 --name my-running-haproxy my-haproxy
I am issuing a postman GET to port 3000 and expecting HaProxy to redirect to my server "dummy" on local port 80. But I am not able to get any legible response back. Appreciate any inputs.
If you run the the container like you did, Docker will assign a random port on your localhost and route traffic to port 3001. You can check which port that is by running docker ps after you started the container and looking at the PORTS section:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6b502af649be my-haproxy "/docker-entrypoint.…" 1 minute ago Up 47 minutes 0.0.0.0:32769->3001/tcp upbeat_shtern
So on my example, you can access your application on port 32769, but this number is random.
Keep in mind, that in your example, Docker routes traffic to port 3001, whereas you configured your HAProxy to bind to port 3000. You would at least need to change the docker run command to the following:
docker run -p3000 --name my-running-haproxy my-haproxy
But usually you want to have a fixed port on localhost, e.g. port 80. Start your container like this to achieve that:
docker run -p 80:3000 --name my-running-haproxy my-haproxy
Now you can access your application at localhost:80.

Cant connect to docker container port for dotnetcore api

I can curl localhost:5000 inside container but not from outside even when port binding added as 5000:5000
pramodjangam#Pramods-MacBook-Pro:~/code/helloworld$ curl localhost:5000/WeatherForecast
curl: (52) Empty reply from server
pramodjangam#Pramods-MacBook-Pro:~/code/helloworld$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5f0c986867d9 kitematic/hello-world-nginx:latest "sh /start.sh" 10 minutes ago Up 10 minutes 0.0.0.0:32768->80/tcp hello-world-nginx
1200a6c8c7df helloworlddotnet "/bin/sh -c out/Hell…" 19 minutes ago Up 19 minutes 0.0.0.0:5000-5001->5000-5001/tcp great_haslett
pramodjangam#Pramods-MacBook-Pro:~/code/helloworld$ docker exec -it 1200a6c8c7df bash
root#1200a6c8c7df:/# curl localhost:5000
root#1200a6c8c7df:/# curl localhost:5000/WeatherForecast
[{"date":"2019-12-07T19:00:43.0919669+00:00","temperatureC":5,"temperatureF":40,"summary":"Balmy"},{"date":"2019-12-08T19:00:43.0920037+00:00","temperatureC":13,"temperatureF":55,"summary":"Cool"},{"date":"2019-12-09T19:00:43.0920128+00:00","temperatureC":52,"temperatureF":125,"summary":"Warm"},{"date":"2019-12-10T19:00:43.0920303+00:00","temperatureC":-3,"temperatureF":27,"summary":"Balmy"},{"date":"2019-12-11T19:00:43.0920383+00:00","temperatureC":46,"temperatureF":114,"summary":"Balmy"}]root#1200a6c8c7df:/#
root#1200a6c8c7df:/# exit
exit
I have ran into this sort of issues. Please make sure that your dotnet application running inside your docker container is also listening on all network interfaces.
For instance, whenever I run a Django application (in dev mode), I always make sure to see a message like this:
Starting development server at http://0.0.0.0:8000/
The key here is 0.0.0.0:8000 which indicates that my app, inside the container, is listening on all network interfaces.
Another option is to run your container with host networking mode (https://docs.docker.com/network/network-tutorial-host/)
I am having the same problem. It seems to be a dotnet 3.1 problem. When I start the app in the container it only binds to localhost:5000 and not to the other network interface. The problem is that localhost is always only reachable from the host (or in this case the container) itself, even if you port forward in docker it will not work.
I tried adding
.UseUrls("http://0.0.0.0:5000")
to the hostbuilder to make the app listen to all available network devices but it does not work, neither does adding:
ENV ASPNETCORE_URLS http://*:5000
This to the Dockerfile or
environment:
- ASPNETCORE_URLS=http://*:5000
to the docker-compose.
These options used to work fine in dotnet 2 but in 3.1 they do not have any effect. I also tried 0.0.0.0 instead of * nothing seems to work.
So basically dotnet always starts the Server on localhost (even on my developmachine) which makes your app only reachable from the host it is running on.
Inside the container, localhost refers to the container. Outside the container, localhost is your machine, not the container. When you want to access something running in the container outside the container, you need to use the container's IP address, not localhost.
You can get the container's IP address using:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' [container_name_here]

Can't access service running in docker

I'm unable to access a nodejs based service via http://localhost:8000 running in a docker image. I'm using Docker for Mac (https://docs.docker.com/docker-for-mac/)
I'm following the tutorial here https://nodejs.org/en/docs/guides/nodejs-docker-webapp/.
The server runs on port 8000. I start the docker image with the following:
$ docker run -p 8000:8000 -d geuis/node-server:latest
If I run docker ps I see:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9fa2e446918b geuis/node-server:latest "npm start" 6 seconds ago Up 5 seconds 0.0.0.0:8000->8000/tcp unruffled_lewin
If I docker exec -it 9fa2e446918b /bin/bash I can access the docker vm and I can curl http://localhost:8000 and access the server from inside the container.
However, I try the same curl http://localhost:8000 from my system terminal and its not accessible.
Not sure what I need to do next.
Try the following listen statement:
app.listen(PORT, '0.0.0.0');
From reading the tutorial you mention it looks like express is listening on localhost. This is fine if you're running locally but inside of a container, localhost is not the same localhost that's outside of the container.
0.0.0.0 is the unspecified IPv4 address and so Express will bind on any IP it can find, which will be the IP that your requests are coming in from outside the container.

Docker not mapping port using gunicorn

I'm running gunicorn inside a docker container. I know this works because sshing into it and curling localhost:8000/things in docker container gives me the response I want, however, I am not able to reach this on my host, despite docker telling me the port has been mapped. What gives?
I ran
docker run -d -p 80:8000 myapp:version1.1 /bin/bash -c 'gunicorn things:app'
docker ps gives me
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
614df1f2708e myapp:version1.1 "/bin/bash -c 'gunico" 6 minutes ago Up 6 minutes 5000/tcp, 0.0.0.0:80->8000/tcp evil_stallman
On my host, curling locahost/things gives me
curl: (52) Empty reply from server
However, when I docker exec -t -i 614df1f2708e /bin/bash and then curl localhost:8000/things, I succesfully get my correct response.
Why isn't docker mapping my port 8000 correctly?
When you publish a port, Docker will forward requests into the container, but the container needs to be listening for them. The container has an IP address from the Docker network, and your app needs to be listening on that address.
Check your gunicorn bind setting - if it's only listening on 127.0.0.1:8000 then it's not binding to the container's IP address, and won't get requests from outside. 0.0.0.0:8000 is safe as it will bind to all addresses.

Resources