I have a go grpc service. I'm developing on a mac, sierra. When running a grpc client against the service locally, all is well, but when running same client against same service in the docker container I get this error:
transport: http2Client.notifyError got notified that the client transport was broken EOF.
FATA[0000] rpc error: code = Internal desc = transport is closing
this is my docker file:
FROM golang:1.7.5
RUN mkdir -p /go/src/github.com/foo/bar
WORKDIR /go/src/github.com/foo/bar
COPY . /go/src/github.com/foo/bar
# ONBUILD RUN go-wrapper download
RUN go install
ENTRYPOINT /go/bin/bar
EXPOSE 51672
my command to build the image:
docker build -t bar .
my command to launch the docker container:
docker run -p 51672:51672 --name bar-container bar
Other info:
client program runs fine from within the docker container
connecting to a regular rest endpoint works fine (http2, grpc related?)
running the lsof command in OS X yields these results
$lsof -i | grep 51672
com.docke 984 oldDave 21u IPv4 0x72779547e3a32c89 0t0 TCP *:51672 (LISTEN)
com.docke 984 oldDave 22u IPv6 0x72779547cc0fd161 0t0 TCP localhost:51672 (LISTEN)
here's a snippet of my server code:
server := &Server{}
endpoint := "localhost:51672"
lis, err := net.Listen("tcp", endpoint)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer(grpc.Creds(creds))
pb.RegisterExpServiceServer(s, server)
// Register reflection service on gRPC server.
reflection.Register(s)
log.Info("Starting Exp server: ", endpoint)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
When you specify a hostname or IP address to listen on (in this case localhost which resolves to 127.0.0.1), then your server will only listen on that IP address.
Listening on localhost isn't a problem when you are outside of a Docker container. If your server only listens on 127.0.0.1:51672, then your client can easily connect to it since the connection is also made from 127.0.0.1.
When you run your server inside a Docker container, it'll only listen on 127.0.0.1:51672 as before. The 127.0.0.1 is a local loopback address and it not accessible outside the container.
When you fire up the docker container with "-p 51672:51672", it'll forward traffic heading to 127.0.0.1:51672 to the container's IP address, which in my case is 172.17.0.2.
The container gets an IP addresses within the docker0 network interface (which you can see with the "ip addr ls" command)
So, when your traffic gets forwarded to the container on 172.17.0.2:51672, there's nothing listening there and the connection attempt fails.
The fix:
The problem is with the listen endpoint:
endpoint := "localhost:51672"
To fix your problem, change it to
endpoint := ":51672"
That'll make your server listen on all it container's IP addresses.
Additional info:
When you expose ports in a Docker container, Docker will create iptables rules to do the actual forwarding. See this. You can view these rules
with:
iptables -n -L
iptables -t nat -n -L
If you use docker container to run grpc service,you should make sure grpc service and grpc client on ths same bridge
if you are using docker container, u can define network by IP and give this IP to your IP address(like: 178.20.0.5).
Related
On my Windows 10 host machine with Docker 4.9.1 I want to ssh into a docker container.
I followed a bunch of tutorials just like this one:
https://phoenixnap.com/kb/how-to-ssh-into-docker-container
From within the container I can ssh into the container using its IP of 172.17.0.2, but from my host machine I cannot.
Confirmation of the IP address:
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' interesting_meitner
'172.17.0.2'
Ping without response:
ping 172.17.0.2
Ping wird ausgeführt für 172.17.0.2 mit 32 Bytes Daten:
Zeitüberschreitung der Anforderung.
Ping-Statistik für 172.17.0.2:
Pakete: Gesendet = 1, Empfangen = 0, Verloren = 1
(100% Verlust),
SSH with connection timeout:
ssh root#172.17.0.2
ssh: connect to host 172.17.0.2 port 22: Connection timed out
Starting the container (obviously done before trying to connect to it):
docker run -ti with_ssh:new /bin/bash
I have also tried this with options for remapping ports i.e. -p 22:666 or -p 666:22 .
Starting ssh server:
/etc/init.d/ssh start
* Starting OpenBSD Secure Shell server sshd
Checking status:
/etc/init.d/ssh status
* sshd is running
Ssh from container into container:
ssh root#172.17.0.2
The authenticity of host '172.17.0.2 (172.17.0.2)' can't be established.
ECDSA key fingerprint is SHA256:471dnz1q83owB/Nu0Qnnyz/Sct4Kwry9Sa9L9pwQeZo.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.17.0.2' (ECDSA) to the list of known hosts.
root#172.17.0.2's password:
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 5.10.16.3-microsoft-standard-WSL2 x86_64)
[...]
Again from the Docker host I get a connection timeout. What do?
Your Docker container runs in a virtual network you cannot reach from the host (because it is isolated), which is why you cannot ping the containers IP from the host (but your docker container can, because it is attending the same network). You can expose the port like you already did with -p 666:22, but then you have to SSH to localhost not to the IP of the container: ssh -p 666 root#127.0.0.1.
You could also configure a correct routing from your hosts network to the virtual network and then you can reach the IP directly.
I did not reproduce your setup but this might work i guess. Hope it helps.
I am running the container and mapping the port like so:
docker run -d --expose 4242 -p 4242:4242 42wim/matterbridge:stable --debug
I've created a firewall rule to allows TCP connections over port 4242 to my VM. When I send an http request to the public IP of my VM the connection is refused:
http://{public-ip}:4242/api/messages
Howevever if I open a shell into the container and do a curl to the path I get the expected response curl localhost:4242/api/messages
What is the correct way to map TCP requests on port 4242 from my Host to my Container? I'm running a Ubuntu VM on GCP that hosts my docker container
Update, if use docker run --network="host" I can curl from the host to the docker container with curl localhost:4242/api/messages with the expected response. Yet when I do the same curl request with the public IP the connection is still refused.
if I ss -na | grep :4242
tcp LISTEN 0 4096 127.0.0.1:4242 0.0.0.0:*
it shows it's listening. Is there additional mapping I need to do? I have validated from google firewall logs that it is allowing and forwarding TCP connections from port 4242 to the VM
I have configured my router to expose http 80 on my local machine ip address:
ie '192.168.0.79', and exposed both inbound and outbound ip address, including allowing through firewall. For the purpose of this example lets say its "200.200.200.200"
I have a node server running locally on this same ip address which works and I can see 'hello world' when I visit my exposed ip address, eg: 200.200.200.200 on my web browser. This works.
import yargs from 'yargs';
import express from 'express';
const app = express();
const argv = yargs.argv;
const host = argv.host ;
const port = argv.port;
app.get('/', (req, res) => res.send('Hello World!'));
app.listen(port, host, function() {
console.log('listening on ', host, ':', port);
});
when I stop the node server and instead run a docker container on the same ip address as follows:
docker run -p 192.168.0.79:80:8080 -p 50000:50000 --name myjenkins -v %cd%/jenkins:/var/jenkins_home jenkins/jenkins
I can see this locally on my machine, but when trying to access it from external webbrowser, eg: "200.200.200.200" it simply returns - HTTP ERROR 504
Is there something else I need to expose via the docker container to make this visible online?
I'm having the same issue with an nginx image. So i'm convinced there is something missing in my docker arguments.
Dockerfile
FROM nginx:alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY dist /usr/share/nginx/html/dist
COPY nginx/default.conf /etc/nginx/conf.d/
docker build -t nginx_image .
docker run -p 192.168.0.79:80:8080 nginx_image
Sounds like a return route issue. Log onto your docker container and see if you can ping 8.8.8.8. Also run netstat -r and see what the default route is. It should be the internal IP address of your firewall.
ok so on much exhaustive research it seems there might be a problem with windows exposing these containers. Or it might be something more advanced regarding proxying this container to the outside.
My solution. Create a node server that proxys to the localhost on my machine.
step 1 - get my ip address for this particular desktop computer on the ethernet
start > cmd
ipconfig
Ethernet adapter Ethernet 4 (Yours will be different. Which ever is connected to the internet):
...
IPv4 Address. . . . . . . . . . . : 192.168.0.79
step 2 - configure router, sky or other, to expose this ip to the internet
visit 192.168.0.2
user: admin
pass: sky
Advanced > Lan IP Setup > LAN TCP/IP Setup
LAN TCP/IP Setuphelp
IP Address:
192. 168. 0. 1
IP Subnet Mask:
255. 255. 255. 0
TICK - Use Router as DHCP Serverhelp
Starting IP Address:
192. 168. 0. 2
Ending IP Address:
192. 168. 0. 254
Address Reservation > Add
cmd
ip address: 192.168.0.79
Mac adress: (This number will look something like 4c:a2:e0 etc.... - can by got by going to a website and typing whats my ip)
Device Name: (Right click my computer > properties) MYCOMPUTERNAME
Security > Firewall Rules > Outbound services > Edit
Service: http: tcp 80
action: allow always
access from: any
0 0 0 0
Security > Firewall Rules > Inbound services > Edit
Service: http: tcp 80
action: allow always
Destination IPv4 LAN address: 192.168.0.79
access from: any
step 3 - create a docker container (ie jenkins), that will default to localhost, and expose the port on something other than 80, ie 81. (We need 80, to be exposed via our router)
Create docker container on localhost:81
docker run -p 81:8080 -p 50000:50000 --name myjenkins -v %cd%/jenkins:/var/jenkins_home jenkins/jenkins
step 4 - Create a node server or equivalent that will proxy the exposed ip address to this localhost
Create a proxy server that redirects 192.168.0.79 to localhost:81
import express from 'express';
import httpProxy from 'http-proxy';
const app = express();
const host = '192.168.0.79' ;
const port = '80';
const apiProxy = httpProxy.createProxyServer();
app.all('/*', (req, res) => {
console.log('redirecting to docker container - http://localhost:81');
apiProxy.web(req, res, {target: 'http://localhost:81'});
});
app.listen(port, host, function() {
console.log('listening on ', host, ':', port);
});
step 5 - type into a webbrowser - whats my ip
ipv4 will by something like 30.132.323.11
Now type this into a webbrowser and you should see your docker container exposed via the node server proxy.
Following the tutorial on https://docs.docker.com/get-started/part2/.
I start my docker container with docker run -p 4000:80 friendlyhello
and see
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://0.0.0.0:8088/ (Press CTRL+C to quit)
But it's inaccessible from the expected path of localhost:4000.
$ curl http://localhost:4000/
curl: (7) Failed to connect to localhost port 4000: Connection refused
$ curl http://127.0.0.1:4000/
curl: (7) Failed to connect to 127.0.0.1 port 4000: Connection refused
Okay, so maybe it's not on my local host. Getting the container ID I retrieve the IP with
docker inspect --format '{{ .NetworkSettings.IPAddress }}' 7e5bace5f69c
and it returns 172.17.0.2 but no luck! curl continues to give the same responses. I can confirm something is running on 4000....
lsof -i :4000
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
com.docke 94812 travis 18u IPv6 0x7516cbae76f408b5 0t0 TCP *:terabase (LISTEN)
I'm pulling my hair out on this. I've read through the troubleshooting guide and can confirm
* not on a proxy
* don't use a custom dns
* I'm having issues connecting to docker, not docker connecting to my pip server.
Running the app.py with python app.py the server starts and I'm able to hit it. What am I missing?
Did you accidentally put port=8088 at the bottom of your app.py file? When you are running this the last line of your output is saying that your python app is exposed on port 8088 not 80.
To confirm you can run either modify the app.py file and rebuild the image, or alternatively you could run: docker run -p 4000:8088 friendlyhello which would map your local port 4000 to 8088 in the container.
Try to run it using:
docker run -p 4000:8088 friendlyhello
As you can see from the logs, your app starts on port 8088, but you connect 4000 to 80 where on 80, nothing is actually listening.
I'm trying to make requests to the Docker API remotely.
I have the docker engine running on virtual machine, and I'm making the requests from docker containers.
Firstly, I've done this to make the Docker daemon listen on a specific IP and port:
edit /lib/systemd/system/docker.service
ExecStart=/usr/bin/docker -H fd:// -H=tcp://0.0.0.0:5555
systemctl daemon-reload
sudo service docker restart
I configured to listen on 0.0.0.0, so it will be reachable at any IPv4 address.
When I test this via curl on host, it works fine. e.g: curl localhost:5555/services
However, my goal is to make requests from containers. Here is how I construct the docker client inside my go program:
cli, err := client.NewClientWithOpts(
client.WithHost("tcp://192.168.56.1:5555"),
)
if err != nil {
panic(err)
}
networkFilters := filters.NewArgs()
networkFilters.Add("driver", "overlay")
networks, err := cli.NetworkList(context.Background(), types.NetworkListOptions{Filters: networkFilters})
if err != nil {
panic(err)
}
The error I'm having:
http: panic serving 10.255.0.2:39632: error during connect: Get http://192.168.56.1:5555/v1.40/networks?filters=%7B%22driver%22%3A%7B%22overlay%22%3Atrue%7D%7D: read tcp 172.18.0.3:36126->192.168.56.1:5555: read: connection reset by peer
Any ideas? Thanks