Unable to connect to MongoDB from Docker Container - docker

I am running Mongo DB image with following command:
docker run -d -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=test -e MONGO_INITDB_ROOT_PASSWORD=password --name=testdb mongo
This created container and I'm able to connect to this from robo3T.
Now I ran mongo-express image with following command and trying to above DB:
docker run -d -p 8081:8081 -e ME_CONFIG_MONGODB_ADMINUSERNAME=test -e ME_CONFIG_MONGODB_ADMINPASSWORD=password -e ME_CONFIG_MONGODB_SERVER=testdb --name=mongo-ex mongo-express
But I'm getting following error:
UnhandledPromiseRejectionWarning: MongoNetworkError: failed to connect to server [testb:27017] on first connect [Error: getaddrinfo ENOTFOUND testb
If I'm creating a custom bridge network and running these two images in that container it's working.
My question is: As the default network is bridge network, and these containers are creating in default bridge network, why are they not able to communicate? Why is it working with custom bridge network?

There are two kinds of "bridge network"; if you don't have a docker run --net option then you get the "default" bridge network which is pretty limited. You almost always want to docker network create a "user-defined" bridge network, which has the standard Docker networking features.
# Use modern Docker networking
docker network create myapp
docker run -d --net myapp ... --name testdb mongo
docker run -d --net myapp ... -e ME_CONFIG_MONGODB_SERVER=testdb mongo-express
# Because both containers are on the same --net, the first
# container's --name is usable as a host name from the second
The "default" bridge network that you get without --net by default forbids inter-container communication, and you need a special --link option to make the connection. This is considered obsolete, and the Docker documentation page describing links notes that links "may eventually be removed".
# Use obsolete Docker networking; may stop working at some point
docker run -d ... --name testdb mongo
docker run -d ... -e ME_CONFIG_MONGODB_SERVER=testdb --link testdb mongo-express
# Containers can only connect to each other by name if they use --link
On modern Docker setups you really shouldn't use --link or the equivalent Compose links: option. Prefer to use the more modern docker network create form. If you're using Compose, note that Compose creates a network named default but this is a "user-defined bridge"; in most cases you don't need any networks: options at all to get reasonable inter-container networking.

Related

Cannot access dockerized MySQL instance from another container

When I start MySQL :
docker run --rm -d -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -v /Docker/data/matos/mysql:/var/lib/mysql mysql:5.7
And start PHPMyAdmin :
docker run --rm -d -e PMA_HOST=172.17.0.1 phpmyadmin/phpmyadmin:latest
PMA cannot connect to the DB server.
When I try with PMA_HOST=172.17.0.2 (which is the address assigned to the MySQL container), it works.
But :
as MySQL container publishes its 3306 port, I think it should be reachable on 172.17.0.1:3306.
I don't want to use the 172.17.0.2 address because the MySQL container can be assigned another address whenever it restarts
Am I wrong ?
(I know I can handle this with docker-compose, but prefer managing my containers one by one).
(My MySQL container is successfully telnetable from my laptop with telnet 172.17.0.1 3306).
(My docker version : Docker version 20.10.3, build 48d30b5).
Thanks for your help.
Create a new docker network and start both containers with the network
docker network create my-network
docker run --rm -d --network my-network -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -v /Docker/data/matos/mysql:/var/lib/mysql --name mysql mysql:5.7
docker run --rm -d --network my-network -e PMA_HOST=mysql phpmyadmin/phpmyadmin:latest
Notice in the command that I've given the mysql container a name 'mysql' and used it as the address for phpmyadmin
Just found out the problem.
My ufw was active on my laptop, and did not allow explicitly port 3306.
I managed to communicate between PMA container and MySQL, using 172.17.0.1, either by disabling ufw or adding a rule to explicitly accept port 3306.
Thanks #kidustiliksew for your quick reply, and the opportunity you gave me to test user-defined networks.
maybe it's a good idea to use docker-compose.
Create a docker-compose.yml file and inside declare two services, one web and the other db, then you can reference them through their service names (web, db)
ex: PMA_HOST=db

Connect application to database when they are in separate docker containers

Well, the set up is simple, there should be two containers: one of them for the mysql database and the other one for web application.
What I do to run the containers,
the first one for database and the second for the app:
docker run --name mysql-container -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=db -p 3306:3306 -d mysql
docker run -p 8081:8081 myrepo/myapp
The application tries to connect to database using localhost:3306, but as I found out the issue is that each container has its own localhost.
One of the solution I found was to add the same network for containers using --net and the docker commands happend to be like the following:
docker network create my-network
docker run --name mysql-container -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=db -p 3306:3306 -d
--net my-network mysql
docker run --net my-network -p 8081:8081 myrepo/myapp
Though, the web application still is not able to connect to the database. What am I doing wrong and what is the proper flow to connect application to database when they are both inside containers?
You could use the name of the container (i.e. mysql-container) to connect to mysql. Example:
Run the mysql container:
docker run --name mysql-container -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=db -p 3306:3306 -d --net my-network mysql
Connect from another container using the mysql client:
docker run --net my-network -it mysql mysql -u root -p db -h mysql-container
In your application you should replace in the database URL, whatever IP you have with mysql-container.
Well, after additional research, I successfully managed to connect to the database.
The approach I used is the following:
On my host I grabbed the IP address of the docker itself but not the specific container:
sudo ip addr show | grep docker0
The IP address of the docker0 I added to the database connection URL inside my application and thus application managed to connect to the database (note: with this flow I don't add the --net keyword when start container)
What definitely strange is that even adding shared network like --net=my-nework for both the container didn't work. Moreover I did try to use --net=host to share the host network with container's one, still it was unsuccessful. If there's any who can explain why it couldn't work, please - share your knowledge.

How to create websocket connection between two Docker containers

I've got two Docker containers that need to have a websocket connection between the two.
I run one container like this:
docker run --name comm -p 8080:8080 comm_module:latest
to expose port 8080 to the host. Then I try to run the second container like this:
docker run --name test -p 8080:8080 datalogger:latest
However, I get the error below:
docker: Error response from daemon: driver failed programming external
connectivity on endpoint test
(f06588ee059e2c4be981e3676d7e05b374b42a8491f9f45be27da55248189556):
Bind for 0.0.0.0:8080 failed: port is already allocated. ERRO[0000]
error waiting for container: context canceled
I'm not sure what to do. Should I connect these to a network? How do I run these containers?
you can't bind the same host port twice in the same time you may change one of the ports on one container:
docker run --name comm -p 8080:8080 comm_module:latest
docker run --name test -p 8081:8080 datalogger:latest
you may check the configuration in the containers on how they communicate .
you can also create link between them:
docker run --name test -p 8081:8080 --link comm datalogger:latest
I finally worked it out. These are the steps involved for a two-way websocket communication between two Docker containers:
Modify the source code in the containers to use the name of the other container as the destination host address + port number (e.g. comm:port_no inside test, and vice versa).
Expose the same port (8080) in the Dockerfiles of the two containers and build the images. No need to publish them as they are will be visible to other containers on the network.
Create a user-defined bridge network like this:
docker network create my-net
Create my first container and attach it to the network:
docker create --name comm --network my-net comm_module:latest
Create my second container and attach it to the network:
docker create --name test --network my-net datalogger:latest
Start both containers by issuing the docker start command.
And the two-way websocket communication works nicely!
My Solution works fine.
docker network create mynet
docker run -p 443:443 --net=mynet --ip=172.18.0.3 --hostname=frontend.foobar.com foobarfrontend
docker run -p 9999:9999 --net=mynet --ip=172.18.0.2 --hostname=backend.foobar.com foobarbackend
route /P add 172.18.0.0 MASK 255.255.0.0 10.0.75.2
the foobarfrontend calls a wss websocket on foobarbackend on port 9999
PS: i work on docker windows 10 with linuxcontainers
have fun

Container: Accessing DB within same VM fails

I am trying to have my application connect to the Sql Server Express DB, both which are containerized.
When i run my app container in in a separate VM to the db, it connects and all is good.
However if the app container is running on the same VM as the DB container, it cannot connect.
I've tried setting the network mode to host and still nothing.
I got a very simple setup as part of my hands on learning.
Diagram of setup below.
Model A: Vm to VM - Connection Works
Model B: Internal VM - Cannot Connect thus App fails
I been reading up on docker a bit (running simple docker setup) to try and figure out the problem but no luck so far.
I've also used docker-compose to try and help still no luck.
Edit 1:
Commands used.
SQL Server: as per docker hub instructions
docker run --restart always -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=RANDOMPASS01!' -e 'MSSQL_PID=Express' -p 1433:1433 -d mcr.microsoft.com/mssql/server:2017-latest-ubuntu
AppA
This by itself works fine in Model A
docker run -p 5000:80 -d appa:0.1
I've also tried
docker run -p 5000:80 --network host -d appa:01
For what I see that you're doing it (starting your app container with net=host) should be working without issues as long as you are using localhost for connecting to the db.
If this is just for testing in your local machine I would suggest start both containers within their own docker network and access the db by container name, you can do it manually or use docker-compose to do it.
Example with docker-compose:
version: '3'
services:
db:
image: mcr.microsoft.com/mssql/server:2017-latest-ubuntu
ports:
- 1433:1433
environment:
- MSSQL_PID=Express
- SA_PASSWORD=RANDOMPASS01!
- ACCEPT_EULA=Y
restart: always
app:
# You can use this to tell docker-compose to build the image of you app
# or use a prebuilt image like the db service is using
image: appa:0.1
ports:
- 5000:80
Put this in a file called docker-compose.yml and start it with:
docker-compose up
This will create two containers in the same network, this will provide you as well with a DNS record for each container with the name of the provided service in the docker-compose file, so instead of using an IP or localhost you use "db" or "app".
More info for docker-compose: https://docs.docker.com/compose/overview/
The manual way:
docker network create mynetwork
Run the containers within the network:
docker run -p 5000:80 -d --net=mynetwork --name app appa:0.1
docker run --restart always -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=RANDOMPASS01!' -e 'MSSQL_PID=Express' -p 1433:1433 --net=mynetwork --name db -d mcr.microsoft.com/mssql/server:2017-latest-ubuntu
In the same way as using docker-compose you can access the db by using the "db" dns record that docker creates based on the name of the container.
The aforementioned DNS records are only resolvable within the containers.
More info on user-defined networks: https://docs.docker.com/network/bridge/

docker reverse-proxy doesnt work when change network (by --net)

docker version: 17.05.0-ce
I have some containers running by hand using docker run ... but recently for new project I create docker-compose.yml file based on this tutorial. However when i run following commands in my hosting:
docker network create --driver bridge reverse-proxy
docker-compose up
and
docker run -d --name nginx-reverse-proxy --net reverse-proxy -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
The proxy not work for old containers and I am unable to use subdomain to that projects (they "stop work").
So what to do?
I make experiments with --net parameter in docker run ... and using docker network inspect network_name. I get many different results like welcome to nginx or http 404 not found or http 503 temporarily unavailable and get following conclusions:
if no --net command then container is run in bridge network
if --net xxx command then cntainer is run only in 'xxx' network (not in bridge !)
if --net xxx --net yyy then container is run only in 'yyy' (no 'xxx' at all!)
The bridge is default docker network for containers inter-communication.
So when on running proxy we use only --net reverse-proxy then proxy container not see bridge and cannot communicate with other containers. If we try to use --net reverse-proxy --net bridge (two or more times in one line - like -p) then container will be connected only to last network.
So solution is... run proxy in following way:
docker run -d --name nginx-reverse-proxy -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
docker network connect reverse-proxy reverse-proxy
As you see we not use --net command at all. The network connect command allow container to connect to use multiple networks. When you execute docker network inspect reverse-proxy and docker network inspect bridge we will see that nginx-reverse-proxy is in both networks :)

Resources