I've got two Docker containers running. One is MongoDB and one is a container running a simple rest API that should be able to query the MongoDB container.
Port mappings
0.0.0.0:28001->27017/tcp (mongodb)
0.0.0.0:3000->3000/tcp (restapi)
Commands used for the MongoDB image
docker run -p 28001:27017 -v /home/ubuntu/docker/mongodb/mongod.conf:/etc/mongod.conf --name mongodb_container -d mongodb_image
I override mongo.conf to add 0.0.0.0 to bind IP
net:
port: 27017
bindIp: [127.0.0.1,0.0.0.0]
Run command used for the API:
docker container run -it -v /home/ubuntu/docker/node_modules:/usr/lib/node_modules -p 3000:3000 --name rest_container rest_image /bin/bash
I'm able to query the rest api, but it hangs and times out (never returns result). The rest config file looks something like this:
{ "db": {
'port': 28001,
'host': "192.168.123.191"
},
'server': {
'port': 3000,
'timeout': 120,
'address': "0.0.0.0"
},
'flavor': "regular",
'debug': true
};
Internal IP of the rest api container:
172.17.0.4
Internal IP of the mongodb container:
172.17.0.2
I know the API works because I'm able to do queries without running the programs on docker. Ports 27017 and 3000 are both exposed in the Dockerfile. In the mongodb container I can also see that the number of connections increases every time I do a query.
Prior to docker 1.9 you had to use "a link" but it has been deprecated. Now you should create a "custom network" https://docs.docker.com/engine/userguide/networking) and run your containers within this network.
For example :
docker network create --driver bridge my_network
docker run --network=my_network -p 28001:27017 -v /home/ubuntu/docker/mongodb/mongod.conf:/etc/mongod.conf --name mongodb_container -d mongodb_image
docker container run --network=my_network -it -v /home/ubuntu/docker/node_modules:/usr/lib/node_modules -p 3000:3000 --name rest_container rest_image /bin/bash
And you need to configure Node to talk with Mongo using a hostname (which is the same as the name of containe'rs) and using the port of the Mongo container and not the external one, I mean port 27017 not 28001. That's why port binding -p 28001: 27017 is unnecessary unless you want to access it from the outside.
{ "db": {
'port': 27017,
'host': "mongodb_container"
},
'server': {
'port': 3000,
'timeout': 120,
'address': "0.0.0.0"
},
'flavor': "regular",
'debug': true
};
Related
using UBUNTO OS
have downloaded the postgres and pgadmin images and ran the containers
postgres command
sudo docker run --name some-postgres -e POSTGRES_PASSWORD=XYZ_PW -p 5432:5432 -d postgres
pgadmin command
sudo docker run --name pgadmin --link some-postgres:postgres -p 80:80 -d fenglc/pgadmin4
then ensured that both the containers are running like below
sudo docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3bf1e2bcf5e7 fenglc/pgadmin4 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp, :::80->80/tcp, 5050/tcp pgadmin
b21c2bda2cff postgres "docker-entrypoint.s…" 13 minutes ago Up 13 minutes 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp some-postgres
now issue is when trying to access pgadmin # localhost/ or localhost:80
it is showing connection reset error
also below is the result of docker inspect pgadmin
"NetworkSettings": {
"Bridge": "",
"SandboxID": "fb4f3dcf1eed267055060b945ba8fb4bff372873d1cc179a24c934c883c1d100",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"5050/tcp": null,
"80/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "80"
},
{
"HostIp": "::",
"HostPort": "80"
}
]
},
"SandboxKey": "/var/run/docker/netns/fb4f3dcf1eed",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "879f386a86712d2699373ef8667b07984db337e7267a2381da69cdbc5405251e",
"Gateway": "XXXX.XX.0.1",
"GlobalIPv6Address": "",
Regards,
Ashish
fengic/pgadmin4 listens on port 5050. Not on port 80. So your docker run command needs to be
sudo docker run --name pgadmin --link some-postgres:postgres -p 80:5050 -d fenglc/pgadmin4
Then you should be able to access pgadmin on localhost port 80.
Be aware that links are an outdated way of connecting containers and the feature may be removed at some point. The recommended way to connect containers is using docker networks.
I have setup a mongoDB Replicaset (3-repicas) inside Docker Container. I am able to access the replicateset from host machine but unable to access the mongoDB Replicaset from a remote client.
Reference: https://www.sohamkamani.com/blog/2016/06/30/docker-mongo-replica-set/
Scripts to create mongoDB replicaset:
$ docker run -it -v <host mount path>:/data/db -p 30000:30000 --name mongo0 --net my-mongo-cluster -d mongo --replSet my-mongo-set --port 30000
$ docker run -it -v <host mount path>:/data/db -p 30001:30001 --name mongo1 --net my-mongo-cluster -d mongo --replSet my-mongo-set --port 30001
$ docker run -it -v <host mount path>:/data/db -p 30002:30002 --name mongo2 --net my-mongo-cluster -d mongo --replSet my-mongo-set --port 30002
$docker exec -it mongo1 mongo
> rs.initiate({_id: "my-mongo-set", version: 1, members: [
{ _id: 0, host : "mongo0:30000" },
{ _id: 1, host : "mongo1:30001" },
{ _id: 2, host : "mongo2:30002" }
]});
The above command was successful.
I tried accessing the mongo Replicaset from same host outside docker container:
$ mongo mongodb://<PUBLIC_IP>:30000,<PUBLIC_IP>:30001,<PUBLIC_IP>:30002/?replicaSet=my-mongo-set
my-mongo-set:PRIMARY>
even this worked:
$ mongo mongodb://localhost:30000,localhost:30001,localhost:30002/?replicaSet=my-mongo-set
my-mongo-set:PRIMARY>
my /etc/hosts file:
$ cat /etc/hosts
127.0.0.1 localhost mongo0 mongo1 mongo2
<PUBLIC_IP> <domain> mongo0 mongo1 mongo2
What is not working:
From remote client (shell and MongoDB Compass):
$ mongo mongodb://<PUBLIC_IP>:30000,<PUBLIC_IP>:30001,<PUBLIC_IP>:30002/?replicaSet=my-mongo-set
connecting to: mongodb://<PUBLIC_IP>:30000,<PUBLIC_IP>:30001,<PUBLIC_IP>:30002/?replicaSet=my-mongo-set
2020-06-02T22:56:53.776+0530 I NETWORK [js] Starting new replica set monitor for my-mongo-set/<PUBLIC_IP>:30000,<PUBLIC_IP>:30001,<PUBLIC_IP>:30002
2020-06-02T22:56:53.796+0530 I NETWORK [ReplicaSetMonitor-TaskExecutor] Successfully connected to <PUBLIC_IP>:30000 (1 connections now open to <PUBLIC_IP>:30000 with a 5 second timeout)
2020-06-02T22:56:53.796+0530 I NETWORK [js] Successfully connected to <PUBLIC_IP>:30002 (1 connections now open to <PUBLIC_IP>:30002 with a 5 second timeout)
2020-06-02T22:56:53.805+0530 I NETWORK [ReplicaSetMonitor-TaskExecutor] changing hosts to my-mongo-set/mongo0:30000,mongo1:30001,mongo2:30002 from my-mongo-set/<PUBLIC_IP>:30000,<PUBLIC_IP>:30001,<PUBLIC_IP>:30002
2020-06-02T22:56:54.315+0530 W NETWORK [js] Unable to reach primary for set my-mongo-set
2020-06-02T22:56:54.315+0530 I NETWORK [js] Cannot reach any nodes for set my-mongo-set. Please check network connectivity and the status of the set. This has happened for 1 checks in a row.
2020-06-02T22:56:54.821+0530 W NETWORK [js] Unable to reach primary for set my-mongo-set
2020-06-02T22:56:54.821+0530 I NETWORK [js] Cannot reach any nodes for set my-mongo-set. Please check network connectivity and the status of the set. This has happened for 2 checks in a row.
How to resolve this issue?
This is because from version 3.6 forward, mongod listens only localhost -address, until you tell it otherwise. Check here! or google "mongod bindIp".
I've build a docker container running a mongodb-instance, that should be exposed to the host.
However, when i want to connect from the host into the mongodb-container, the connection will be denied.
This is my Dockerfile:
FROM mongo:latest
RUN mkdir -p /var/lib/mongodb && \
touch /var/lib/mongodb/.keep && \
chown -R mongodb:mongodb /var/lib/mongodb
ADD mongodb.conf /etc/mongodb.conf
VOLUME [ "/var/lib/mongodb" ]
EXPOSE 27017
USER mongodb
WORKDIR /var/lib/mongodb
ENTRYPOINT ["/usr/bin/mongod", "--config", "/etc/mongodb.conf"]
CMD ["--quiet"]
/etc/mongodb.conf:
And this is the config-file for MongoDB, where i bind the IP 0.0.0.0 explicitly as found here on SO, that 127.0.0.1 could be the root cause of my issue (but it isn't)
systemLog:
destination: file
path: /var/log/mongodb/mongo.log
logAppend: true
storage:
dbPath: /var/lib/mongodb
net:
bindIp: 0.0.0.0
The docker container is running, but a connection from the host is not possible:
host$ docker run -p 27017:27017 -d --name mongodb-test mongodb-image
host$ docker ps
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6ec958034a6f mongodb-image "/usr/bin/mongod --co" 4 seconds ago Up 3 seconds 0.0.0.0:27017->27017/tcp mongodb-test
Find the IP-Address:
host$ docker inspect 6ec958034a6f |grep IPA
"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
"IPAMConfig": null,
"IPAddress": "172.17.0.2",
Try to connect:
host$ mongo 172.17.0.2:27017
MongoDB shell version v3.4.0
connecting to: mongodb://172.17.0.2:27017
2016-12-16T15:53:40.318+0100 W NETWORK [main] Failed to connect to 172.17.0.2:27017 after 5000 milliseconds, giving up.
2016-12-16T15:53:40.318+0100 E QUERY [main] Error: couldn't connect to server 172.17.0.2:27017, connection attempt failed :
connect#src/mongo/shell/mongo.js:234:13
#(connect):1:6
exception: connect failed
When i ssh into the container, i can connect to mongo and list the test database successfully.
Use host.docker.internal with exposed port : host.docker.internal:27017
Using localhost instead of the ip, allows the connection.
Combine it with the exposed port: localhost:27017
I tested the solution as it was stated in the comments, and it works.
I received the following error when trying to write session data using Tomcat's PersistentManager to a Postgres DB running on my local machine:
SEVERE: A SQL exception occurred org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
The application itself runs in a docker container. For completeness sake, my current context.xml file is:
<?xml version='1.0' encoding='utf-8'?>
<Context>
<Manager className="org.apache.catalina.session.PersistentManager"
distributable="true" processExpiresFrequency="6" maxIdleBackup="0" debug="99" >
<Store className="org.apache.catalina.session.JDBCStore"
driverName="org.postgresql.Driver"
connectionURL="jdbc:postgresql://localhost/admin?stringtype=unspecified"
connectionName="admin" connectionPassword="admin"
sessionAppCol="app_name" sessionDataCol="session_data" sessionIdCol="session_id"
sessionLastAccessedCol="last_access" sessionMaxInactiveCol="max_inactive"
sessionTable="tomcat_sessions_tb" sessionValidCol="valid_session" />
</Manager>
</Context>
Pursuant to the suggestions here: Postgresql : Connection refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections
I confirmed via a netstat -aln | grep LISTEN that Postgresql is running and listening on the correct ports:
tcp4 0 0 127.0.0.1.5432 *.* LISTEN
tcp6 0 0 ::1.5432 *.* LISTEN
and that my postgresql.conf (located in usr/local/var/postgres) has listen_addresses = localhost and port = 5432, which mirrors the host and port of my running server in Pgadmin3.
I suspect that the problem is that Docker runs in a VM, and thus the local information I have obtained may not be the whole story. Reading up on the available information online, it seems that I may require some sort of bridged networking.
However, I admit I am a novice in this area, and I'm unsure of how to set it up.
Why I can NOT connect to localhost:5432?
Cat your container's /etc/hosts
$ sudo docker exec -it [container] cat /etc/hosts
For docker networks is bridge by default, the localhost inside points to container itself(Docker default bridge network).
Then you don't have 5432 listening in your container:
$ sudo docker exec [container] nc -v -z localhost 5432
Solution 1. If you wanna hardcode the "localhost:5432" inside your config xml, the easiest way is creating your container with the option "--net=host":
$ sudo docker run --net=host -it ...
Solution 2. Change the localhost of your docker host ip inside the container
Get your docker host ip:
$ sudo docker inspect -f '{{ .NetworkSettings.Gateway }}'
192.168.5.1
Enter your container:
$ sudo docker exec -it [container] /bin/bash
Edit the file /etc/hosts to point the localhost to docker host ip:
$ sudo vim /etc/hosts
192.168.5.1 localhost
Solution 3. Modify your db config file to use an alias instead of localhost:
connectionURL="jdbc:postgresql://DB_ALIAS/admin?stringtype=unspecified"
Then add the DB_ALIAS to the container's hosts :
$ sudo docker run --add-host DB_ALIAS:192.168.5.1 -it [image] ...
If you are using docker-compose together with postgres image, than you can reuse service name as IP inside jdbc connection (here: app-db)
web:
build: ./web
ports:
- "8080:8080"
links:
- app-db
environment:
- MYAPP_JDBC_URL=jdbc:postgresql://app-db:5432/somedb
- MYAPP_JDBC_USER=someuser
- MYAPP_JDBC_PASS=pass
app-db:
image: postgres:9.6
environment:
- POSTGRES_USER=someuser
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=somedb
expose:
- 5432
volumes_from:
- app-db-data
app-db-data:
image: cogniteev/echo
command: echo 'Data Container for PostgreSQL'
volumes:
- /opt/postgresdata/:/var/lib/postgresql/data
The best decision!
jdbc:postgresql://host.docker.internal:5432/somedb
Don't thank.
I had to expose port with -p 5432:5432:
docker run --name postgres -e POSTGRES_PASSWORD=secret -d -p 5432:5432 postgres
I was getting the same error but this simple solution works perfect for me.
sudo docker run -d --net="host" -it <IMAGE>
Now I can run my app https://x.x.x.x:pppp/../.. and everything works fine. I hope this helps
I'm trying to deploy a mongodb replicaset using docker.
I managed to do it on a same server by executing this :
docker run -d --expose 27017 --name mongodbmycompany1 dockerfile/mongodb mongod --replSet rsmycompa
docker run -d --expose 27017 --name mongodbmycompany2 dockerfile/mongodb mongod --replSet rsacommeassure
docker run -d --expose 27017 --name mongodbmycompany3 dockerfile/mongodb mongod --replSet rsacommeassure
MONGODB1=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' mongodbmycompany1)
MONGODB2=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' mongodbmycompany2)
MONGODB3=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' mongodbmycompany3)
echo $MONGODB1
echo $MONGODB2
echo $MONGODB3
echo "Mongodb Replicaset init"
docker exec mongodbmycompany1 mongo 127.0.0.1:27017/mycompany --eval 'if(!rs.conf()) { rs.initiate(); cfg = rs.conf(); cfg.members[0].host = "'$MONGODB1':27017"; rs.reconfig(cfg); rs.add("'$MONGODB2':27017"); rs.add("'$MONGODB3':27017"); } rs.status();'
It's working as expected. My replicaset is initialized and my mongodb resultset config contains my 3 servers identified by their internal IP address.
It's not perfect as I'd prefer to use servers names but I didn't manage to do it.
Docker only populate each /etc/hosts file with servers names passed at image launch with --link parameter. If i add a new server while others are running. Those servers won't ping the new server.
Now I have another question. In production, having a lot of Mongodb docker image running on a same physical server is possible but it's not safe :
- if my physical server falls down, i lose all my Mongodb replicas and my service is down
- if my physical server uses internal storage, all my docker images use the same disk... and I'm going to have IO problems.
So my question is : How can I deploy many mongodb replicas on multiple physical servers ? How those mongodb replicas can communicate with each others (primary and secondaries servers can change) while they are on different servers or even on different datacenters ?
Let's assume:
you have 3 different docker hosts (servers), with IPs 10.1.1.101, 10.1.1.102, 10.1.1.103
want to deploy a single replica set called rsacommeassure
Dockerfiles for mongodb expose port 27017
all servers are in a trusted zone and can talk to each other
First let's start mongodb containers on each server (10.1.1.101 ~$ is used for command prompt):
10.1.1.101 ~$ docker run -d -p 27017:27017 --name mongodbmycompany1 dockerfile/mongodb mongod --replSet rsacommeassure
10.1.1.102 ~$ docker run -d -p 27017:27017 --name mongodbmycompany2 dockerfile/mongodb mongod --replSet rsacommeassure
10.1.1.103 ~$ docker run -d -p 27017:27017 --name mongodbmycompany3 dockerfile/mongodb mongod --replSet rsacommeassure
-p 27017:27017 exposes port 27017 on the host IP so mongo is accessible on servers' host IP address.
Then you need to initiate the replica set, so just run this against a mongodb container (I'll pick server1 here):
your_laptop ~$ > mongo --host 10.1.1.101
MongoDB shell version: 2.6.9
connecting to: test
> rs.initiate()
> cfg = rs.conf()
> cfg.members[0].host = "10.1.1.101:27017"
> rs.reconfig(cfg)
> rs.add("10.1.1.102:27017")
> rs.add("10.1.1.103:27017")
> rs.status();
The IPs are local but it works with global as well as long as the servers can talk to each other (VPN, firewall, DMZ, whatever). Btw you should consider security carefully.
I've created a Replica Set on different physical servers using docker-machine and virtual box as a driver:
$ docker-machine create --driver virtualbox server1
$ docker-machine create --driver virtualbox server2
$ docker-machine create --driver virtualbox server3
Open 3 different terminals, in each
$(Terminal1) eval "$(docker-machine env server1)"
$(Terminal2) eval "$(docker-machine env server2)"
$(Terminal3) eval "$(docker-machine env server3)"
In each terminal:
$(Terminal1) docker run -d -p 27017:27017 --name mongoClient1 mongo mongod --replSet r1
$(Terminal2) docker run -d -p 27017:27017 --name mongoClient2 mongo mongod --replSet r1
$(Terminal3) docker run -d -p 27017:27017 --name mongoClient3 mongo mongod --replSet r1
Go in VirtualBox -> on each environment(server1,server2,server3) -> Setting -> Network -> Adapter 1 -> Port Forwarding. Create a new rule Protocol TCP, Host Port - 27017, Guest Port - 27017, leave Host Ip and Guest Ip empty
Now restart all the environments, you can do this from the VirtualBox or from the terminal, from terminal just run:
$(Terminal1) docker-machine restart server1
$(Terminal2) docker-machine restart server2
$(Terminal3) docker-machine restart server3
Restart the containers:
$(Terminal1) docker start mongoClient1
$(Terminal2) docker start mongoClient2
$(Terminal3) docker start mongoClient3
Now the containers should be running, you can check them by running
$ docker ps in each terminal
Get into the first container's(or another) Mongo Shell
$(Terminal1) docker exec -it mongoClient1 mongo
// now we are in the Mongo Shell
$(Mongo Shell) rs.initiate()
$(Mongo Shell) cfg = rs.conf()
$(Mongo Shell) cfg.members[0].host = <server1's Ip Address>
// you should get server1's Ip Address by running $ docker-machine ls, mine was 192.168.99.100
$(Mongo Shell) rs.reconfig(cfg)
$(Mongo Shell Primary) rs.add("<server2's Ip Address>:27017")
// now we added a Secondary
$(Mongo Shell Primary) rs.add("<server3's Ip Address>:27017", true)
// now we added an Arbiter
$(Mongo Shell Primary) use planes
// now we create a new database
$(Mongo Shell Primary) db.tranporters.insert({name:'Boeing'})
// create a new collection
$(Mongo Shell Primary) db.tranporters.find()
// we obtain the inserted plane
To connect to a Secondary, you can either:
$(Terminal2) docker exec -it mongoClient2 mongo planes
// or
$(Mongo Shell Primary) db = connect ("<server2's Ip Address>:27017/planes")
Now we are in the Mongo Shell of a Secondary
$(Mongo Shell Secondary) rs.slaveOk()
// to allow readings from the Shell
$(Mongo Shell Secondary)db.tranporters.find()
// should return inserted plane
You could use "Weave - the Docker network" to resolve your problem easily.
Weave creates an overlay network that joins containers on different hosts, even at different cloud providers. Weave also supplies a DNS service that lets you find containers by name within the Weave network.
#Here stop already running instances
docker stop m1 m2 m3
#Cleanup of the volumes
docker rm -f m1 m2 m3
# Start MongoDB services optimised for faster startup
docker run -dP --name m1 mongo mongod --replSet "r1" --noprealloc --smallfiles --nojournal --syncdelay 0
docker run -dP --name m2 mongo mongod --replSet "r1" --noprealloc --smallfiles --nojournal --syncdelay 0
docker run -dP --name m3 mongo mongod --replSet "r1" --noprealloc --smallfiles --nojournal --syncdelay 0
export M1_ADDRESS=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' m1`
export M2_ADDRESS=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' m2`
export M3_ADDRESS=`docker inspect --format '{{ .NetworkSettings.IPAddress }}' m3`
docker exec m1 mongo --eval "rs.initiate();"
docker exec m1 mongo --eval "cfg = rs.conf(); cfg.members[0].host = '$M1_ADDRESS:27017'; rs.reconfig(cfg);"
docker exec m1 mongo --eval "rs.add('$M2_ADDRESS:27017');rs.add('$M3_ADDRESS:27017')"
# Check if everything is fine.
docker exec m1 mongo --eval "rs.status();"
I scripted a docker-image that sets up a mongodb replicaSet for any number of containers and automates scaling as you add more containers. check out the github github repo or docker registry
Use Docker Compose
setup your docker-compose.yml
version: "2"
services:
<your_service_name>:
image: rollymaduk/mongo-replica:local
environment:
REPLICA_NAME: "<your_replica_name>"
volumes:
- /var/config:/var/config
run in command line
docker-compose up
scale up to more containers
docker-compose scale <your_service_name>=3
Docker Cloud
To deploy mongo-db replicaSet using docker-cloud, set up a stack
file
stack.yml: stack file not requiring shared volumes
<service_name>:
image: rollymaduk/mongo-replica:cloud
deployment_strategy: high_availability
target_num_containers: 3
environment:
REPLICA_NAME: <your_replica_name>
DOCKERCLOUD_AUTH: <your_docker_auth_key>
stack.yml: stack file requiring shared volume
<service_name>:
image: rollymaduk/mongo-replica:local
deployment_strategy: high_availability
target_num_containers: 3
volumes:
- /var/config:/var/config
environment:
REPLICA_NAME: <your_replica_name>
using docker-cloud cli run in command line (If stack file does not exist in cloud)
docker-cloud stack create --name <your_stack_name> -f <your_stack_file>
docker-cloud stack start <your_stack_name>
using docker-cloud cli run in command line (If stack file already exists in cloud)
docker-cloud stack update -f <your_stack_file> <your_stack_name>
docker-cloud stack redeploy <your_stack_name>
Important: you must specify a shared volume and mount it to the container's
config directory [default: /var/config ] the example below mounts a host
directory /var/config to the container's config volume.
You can use any of the docker recommended ways of sharing volumes between
containers i.e mounting a host directory or data volume container),just
you specify the correct path for the config volume (/var/config).
_to change default config directory use the environment variable
--CONFIG_DIR to setup your container. Make sure to update host volume
path to reflect your new --CONFIG_DIR name_