I have 2 dockers in a net: web and backend
When I access "web" from the host machine (http://web:3000) it works.
"web" have a "test connection" button to the backend machine, which just tries to access a static page on the backend machine (http://backend:80/isAlive)
But since the call is made from the browser, and the browser is on the host machine, then the "backend" hostname can not be resolved.
I can fix this by editing my host file to so that "backend" will be resolved to localhost, but is there a more intelligent way to do this?
You should strongly consider setting up a separate container acting as a reverse proxy forwarding requests to different containers using virtual hosts.
backend.foo.bar -> talks to backend container
web.foo.bar -> talks to web container
If you don't want do configure dns you can just map those names to localhost in your hosts file for now.
The quickest way to get this working is using jwilder/nginx. When you get it working you can go into the container and look at the generated config file for nginx and learn a fair bit in case you want to set this up manually in the future.
Again: This means that the jwilder/nginx container is the only one that maps a port to localhost. The other containers are proxied through it.
Related
I'm using docker for building both UI and some backend microservices, and using Spring Zuul as the Proxy to pass Restful API calls from UI to the downstream microservices. My UI project needs to specify an IP address in the JS file before the build, and the Zuul project also needs to specify the IP addresses for the downstream microservices. So that after starting the containers, I can access my application using my docker machine IP http://192.168.10.1/myapp and the restful API calls in the browser network tab will be http://192.168.10.1/mymicroservices/getProduct, etc.
I can set all the IPs to my docker machine IP and build them without issues. However for my colleagues located in other countries, their docker machine IP will be different. How can I make docker use a specific IP, for example, 192.168.10.50, which I can set in the UI project and Zuul Proxy project, so that the docker IP will be the same for everyone, regardless of what their actual docker machine IP is?
What I've tried:
I've tried port forwarding in VirtualBox. It works for the UI, however the restful API calls failed.
I also tried the solution mentioned in this post:
Assign static IP to Docker container
However I can't access the services from the browser using the container IP address.
Do you have any better ideas? Thank you!
first of to clarify couple things,
If you are doin docker run ..... then you just starting container in your docker which is installed on the host machine. And there now way docker can change ip of your host machine. Thus if your other services are running somewhere else they will have to know something about docker host machine, ip or dns name.
so basically docker does runs on 127.0.0.1 if you are trying it on docker host machine, or on host machine IP if from outside of it. So docker don't need IP of host to start.
The other thing is if you are doing docker-composer up/start. Which means all services are in that docker compose file. In this case docker composer creates docker network for all containers in it. in this case you definitely can use fixed IPs for containers, though most often you don't need to because docker takes care of name resolution in that network.
if you are doing k8s way - then it is third way (production way), and it os another story.
if that is neither of above then please provide more info on how are you doing stuff.
EDIT - to:
if you are using docker composer and need to expose any of your containers to host machine you can do it through port mapping:
web:
image: some image here
ports:
- 8181:8080
left is the host machine port, right is container port
and then in browser on the host you can do request to localhost:8181
here is doc
https://docs.docker.com/compose/compose-file/#ports
I've got a site running on my dev machine running in a docker container, and it needs to make a request to a site hosted locally on my machine, hosted via IIS. I've managed to get this working by specifying providing the extra_hosts in the docker-compose.override.yml file,
e.g.
extra_hosts:
- "dev-gb.company-qa.com:192.168.65.2"
- "dev-de.company-qa.com:192.168.65.2"
However the bridge IP I've specified is unique to my machine - the next dev that pulls it down will have to discover this IP and change it for themselves. Is there a cleaner, simpler way of accessing the site hosted on my machine without having to manually bind the host name to the bridged IP? I've read about host.docker.internal but I've no idea where that is supposed to go?
I've setup an app where a nodejs backend has to communicate with a rasa chatbot backend through a react frontend. All services are running through the same docker-compose. Being a docker beginner there are some things I'm not sure about:
communication between host and container is done using the container's ip
browser opening the local react server running on localhost:3000 or 172.22.0.1:3000
browser sending a request to the express backend on localhost:4000 172.22.0.2:4000
however communication between two docker containers is done is the container's name:
rasa server conmmunicating with the rasa custom action server through http://action_server:5055/webhooks
rasa custom action server communicating with the express backend through http://backend_name:4000/users/
my problem is that when I need to contact the rasa backend from my react front end I need to put the rasa docker container's ip which (sometimes) changes upon docker-compose reinitialization. To workaround this I do a docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' app_rasa_1 to get the ip and manually change it into the react frontend.
is there a way to avoid changing the ip alltogether and using the container name (or an alias/link) or what would be a way to automate the change of the container's ip in the react frontend (are environment variables updated via a script an option?)
Completely ignore the container-private IP addresses. They're implementation details that have several practical problems, including (as you note) them changing when a container is recreated. (They're also unreachable on non-Linux hosts, or if the browser isn't on the same host as the containers.)
You show the correct patterns in your question. For calls between containers, use the container names as host names (this setup is described more in Networking in Compose. For calls from outside containers, including from browser-based applications, use the host's DNS name or IP address and the first number from the ports: you publish.
If the browser application needs to contact a back-end server, it needs a path to do this. This could be via published ports:, or one of your other components could proxy the request to the service (maybe using the express-http-proxy middleware).
A dedicated container that only proxies to other backend services is also a useful pattern (Docker Nginx Proxy: how to route traffic to different container using path and not hostname includes some examples), particularly since this will let you use path-only URLs like /api or /rasa in your browser application. If the React application is served from http://localhost:8080/, and the main backend is http://localhost:8080/api, then you can just make HTTP requests to /api and they will be interpreted relative to the page's URL. This avoids the hostname problem completely, so long as your reverse proxy has path-based routes to every container you need to directly contact.
I have some docker containers talking together through docker bridge networks. They cannot be accessed from outside (I was said) as they are launched from a script with a default command which does not include 'expose' nor '-p' option. I cannot change that script.
I would like to connect to one of this containers which runs a server and listens for requests on port 8080. I tried connecting that bridge to a newly created docker bridge network, but i did not succede.
Now I am thinking of creating a new container and letting it talk to the server one (through bridge networks). As it is a new contaienr I can use the 'expose' or '-p' options, so it would be able to talk to the host machine.
Is it a good idea? How can I forward every request made to that container to the server one and get responses back to the host machine then?
Thanks
Within the default docker network, all ports are exposed. So you only need a container that exposes a port to the host machine and is in the same network as the other containers you have already created.
This is a relatively normal pattern. You can use a reverse proxy like nginx to achieve something like this.
There are some containers that automate this process:
https://github.com/jwilder/nginx-proxy
If you have no control over the other containers though, you will need to write the proxy config by hand.
If the container to which you are trying to connect is an http server, you may be able to use a ready-made container image that can work as an http forwarder (e.g., nginx - it is relatively easy to configure it as an http forwarder).
If you need plain tcp forwarding, you could make a container running 'socat' (socat can work as a tcp forwarder).
NOTE: in either case, you will be exposing a listener that wasn't meant to be on a public address. Do take measures not to allow unauthorized connections.
I'm running applications using docker containers. I run it with docker-compose. For example there is arangodb dependency:
arangodb:
image: localartifactiory/arangodb:3.2.5
volumes_from:
- arangodb_data
ports:
- 8530:8529
environment:
- ARANGO_ROOT_PASSWORD=admin
I can reach the service with http://localhost:8530, but I can't reach it using service name http://arangodb:8530 or http://arangodb:8529 in browser, still it looks like my application connects to this db by http://arangodb:8529 address.
Can you please tell me if it is possible to reach my service using service-based-url from browser or is it internal docker address that can be reached only inside containers?
The service name url is available due to the embedded DNS server in user-defined networks. This DNS server is only used to resolve DNS requests for containers that are part of the network.
Check Query docker embedded dns from host to see how to resolve DNS names using the embedded DNS server
To access service externally (from the browser) you need to use IP_ADDRESS of the host machine. Host machine means Windows/Ubuntu/ Mac, actual machine address.
To access service internally from one container to another then you can use container name (e.g. http://arangodb:8529).
let me know if you need any further details.