docker containers choosing different networks despite never setting any - docker

I'm having a horrible time with setting up my Docker configuration for my go service. Below is an overview of my setup
go_binary(
name = "main_arm64",
embed = [":server_lib"],
goarch = "arm64",
goos = "linux",
visibility = ["//visibility:public"],
)
container_image(
name = "ww_server_image",
base = "#go_image_static_arm64//image",
entrypoint = ["/main_arm64"],
files = [":main_arm64"],
ports = [
"8080",
"3306",
],
)
I have a GraphQL Playgroud (HTTP) running on http://localhost:8080, and despite the port supposedly being exposed, i cant access the playground UI.
All I'm trying to do is:
Be able to access the GraphQL playground and any other APIs running on other ports within the container
Be able to make requests from my Dockerized Go app to a separate MySQL container (I can't figure out how to put them on the same network with rules_docker).
docker exec -it ... /bin/bash into my docker container (this hasnt been working because bash isnt installed, yet i have no idea how to install bash via this container_image command)
Here is the error:
OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found in $PATH: unknown
If i take the generated docker image ID and run docker run -p 8080:8080 IMAGE_ID, I'm able to access the GraphQL playground, but can't communicate with the MySQL container
If I change the network as such: docker run --network=host -p 8080:8080 IMAGE_ID the Dockerized Go app can successfully communicate with the MySQL container, but then the GraphQL playground becomes inaccessible. The GraphQL playground only becomes accessible if I maintain --network=bridge. I'm not sure why MySQL isn't using bridge as well, since i never specified the network when starting it. This is how I got the MySQL container
docker run -p 3306:3306 --name my-db -e MYSQL_ROOT_PASSWORD=testing -d mysql:8.0.31

So, you have several problems here:
First of all, you can most likely access containers that don't have bash installed through docker exec -it container_name /bin/sh, as most containers at least come with sh.
Second, your host machine can only have one service per port, so when you assign network host to a container, you overwrite the port mapping of other containers, which is why your GraphQL became unreachable after starting the go app with network host as a result of that they both use port 8080.
Third, when you use the default bridge network, your containers can only communicate by IP, not by container name.
Also, you don't need a port mapping to let the containers communicate with each other. Port mapping is only required, when something outside the Docker network needs the access.
Your best chance is to create a network with docker network create network_name and then to assign the network to all containers with --network network_name through the Docker run command.
You don't necessarily need a port mapping to get your application running, but when you want to access a service from outside - e.g. your hosts browser - make sure to take a unique port for each container. The port outside doesn't have to be the same as the container's internal port, you can map for instance -p 8081:8080.
Since all containers belong to one app, you also might want to check whether docker compose is the better alternative as it allows you to easily manage all your container by one config file.

the answer was here:
Unable to connect to mysql server with go and docker - dial tcp 127.0.0.1:3306: connect: connection refused
turns out i need to actually access MySQL using the following address, since Docker on Mac uses Linux VM:
docker.for.mac.localhost:3306

Related

Allow my docker container to make network requests

I have my application running locally in a Docker container, I have published the port which I want to use to invoke its API. However, my Docker container application also needs to make other network requests to externally hosted APIs. Currently I am getting network errors when it tries to make these requests. How do I give my Docker container access to the same network that my local machine is on? Is there a Docker config I need to pass to my docker -it -p 8080:8080 command?
You need to add these options to your docker run command:
--network host
It will bind container networking directly to the Docker host’s network.
Documentation: https://docs.docker.com/network/host/

docker networking: How to know which ip will be assigned?

Trying to get acquainted with docker, so bear with me...
If I create a database container (psql) with port 5432 exposed, and then create another webapp which wants to connect on 5432, they get assigned some ip addresses on the bridge network from docker...
probably 172.0.0.1 and 172.0.0.2 respectively. if I fire up the containers, inspect their ips with docker network inspect <bridge id>
if I then take those ips and plug in the port on my webapp settings, everything works great...
BUT I shouldn't have to run my webapp, shell into it, change settings, and then run a server, I should be able to just run the container...
So what am I missing here, is there a way to have these two containers networked without having to do all of that?
Use a Docker network
docker create network myapp
docker run --network myapp --name db [first-container...]
docker run --network myapp --name webapp [second-container...]
# ... and so on
Now you can refer to containers by their names, from within other containers. Just like they were hostnames in DNS.
In the application running in the webapp container, you can configure the database server using db as if it is a hostname.

How to get the mapped port on host from a docker container?

I want to run a task in some docker containers on different hosts. And I have written a manager app to manage the containers(start task, stop task, get status, etc...) . Once a container is started, it will send an http request to the manager with its address and port, so the manager will know how to manage the container.
Since there may be more than one containers running on a same host, they would be mapped to different ports. To register a container on my manager, I have to know which port each container is mapped to.
How can I get the mapped port inside a docker container?
There's an solution here How do I know mapped port of host from docker container? . But it's not applicable if I run container with -P. Since this question is asked more than 1 year ago, I'm wondering maybe there's a new feature added to docker to solve this problem.
You can also you docker port container_id
The doc
https://docs.docker.com/engine/reference/commandline/port/
examples from the doc
$ docker port test
7890/tcp -> 0.0.0.0:4321
9876/tcp -> 0.0.0.0:1234
$ docker port test 7890/tcp
0.0.0.0:4321
$ docker port test 7890/udp
2014/06/24 11:53:36 Error: No public port '7890/udp' published for test
$ docker port test 7890
0.0.0.0:4321
i share /var/run/docker.sock to container and get self info
docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock alpine:latest sh
in container shell
env //get HOSTNAME
curl --unix-socket /var/run/docker.sock http://localhost/containers/3c6b9e44a622/json
the 3c6b9e44a622 is your HOSTNAME
Once a container is started, it will send an http request to the manager with its address and port
This isn't going to be working. From inside a container you cannot figure out to which docker host port a container port is mapped to.
What I can think about which would work and be the closest to what you describe is making the container open a websocket connection to the manager. Such a connection would allow two ways communication between your manager and container while still being over HTTP.
What you are trying to achieve is called service discovery. There are already tools for service discovery that work with Docker. You should pick one of them instead of trying to make your own.
See for instance:
etcd
consul
zookeeper
If you really want to implement your service discovery system, one way to go is to have your manager use the docker event command (or one of the docker client librairies). This would enable your manager to get notified of containers creations/deletions with nothing to do on the container side.
Then query the docker host to figure out the ports that are mapped to your containers with docker port.

Docker - Access mapr UI from host

I have installed docker on a CentOS machine. Now I am trying to run a MapR sandbox on it. After starting I get this:
Starting MapR Services.................
To manage this node go to: https://172.17.0.13:8443
But I am not able to access this URL from the windows machine in the same network as the CentOS machine.
This is an internal docker network inaccessible outside of the box. In order to access this container you need:
EXPOSE command in container (most likely it is already there)
run container with -p option
If you just specify -p port will be random - you could find it with inspect command, or you could use permanent port -p hostIp:externalPort:8443 where hostIp is address of your docker host.
After that you could access container from network as https://hostIp:externalPort

How to connect two docker containers through localhost?

I have two services running in separate containers, one is grunt(application) and runs off port 9000 and the other is sails.js (server) which runs off port 1337. What I want to try to do is have the client app connect with the server through localhost:1337. Is this feasible? Thanks.
HOST
You won't be able to connect to the other container with localhost (as localhost is the current container) but you can connect via the container host (the host that is running your container). In your case you need boot2docker VM IP (echo $(boot2docker ip)). For this to work, you need to expose your port at the host level (which you are doing with -p 1337:1337).
LINK
Another solution that is most common and that I prefer when possible, is to link the containers.
You need to add the --name flag to the server docker run command:
--name sails_server
You need to add the --link flag to the application docker run command:
--link sails_server:sails_server
And inside your application, you will be able to access the server at sail_server:1337
You could also use environment variables to get the server IP. See documentation: https://docs.docker.com/userguide/dockerlinks/
BONUS: DOCKER-COMPOSE
Your run commands may start to be a bit long... in this case I like to use docker-compose that allows me to define my containers and their relationships (volumes, names, link, commands...) in one file.
Yes if you use docker parameter -p 1337:1337 in your docker run command, it will expose the port 1337 from inside the container to your localhost:1337

Resources