call external api from within docker container - docker-compose

I'm building a project which uses an api which will be running as a service or iisexpress (depends when running on windows, or linux)
while my dashboard application is running in a docker container.
If my dashboard is running in the container and my api is running from the exe(kestrel) than i'm not able to call my api.
I assume that it is because the internal docker network cannot find the host addresses?
what I have tried:
var result = new Host();
using (HttpClient client = new HttpClient())
{
var response = await client.GetAsync("http://192.168.0.196:5000/api/host");
var content = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<Host>(content);
}
the ip address given is the host ip address of my computer, because i want to test it locally.
version: '3.4'
services:
dashboard:
image: ${DOCKER_REGISTRY-}dashboard
container_name: Dashboard
build:
context: .
dockerfile: Dashboard/Dockerfile
ports:
- "1433:1433"
docker -compose that currently maps 1433 for the database
How can I call an external api from within the container?

Related

Connect to PostgreSQL from Flask app in another docker container

On a virtual machine I have 2 docker containers running with the names <postgres> and <system> that run on the network with name <network>. I can't change options in these containers. I have created a flask application that connects to a database and outputs the required information. To connect from local computer I use
conn = psycopg2.connect(
database="db", user='user1', password='user1_passwd'
host='<VM_ip>', port='<db_port>',
sslmode='require',
sslcert='./user1.crt',
sslkey='./user1.key')
and it worked great.
But, when I run my application on the same VM and specify
conn = psycopg2.connect(
database="db", user='user1', password='user1_passwd'
host='<postgres>.<network>', port='<db_port>',
sslmode='require',
sslcert='./user1.crt',
sslkey='./user1.key')
I get an error:
psycopg2.OperationalError: could not parse network address \"<postgres>.<network>\": Name or service not known.
Local connections are allowed in pg_hba, the problem is in connecting from the new container in VM.
Here are the settings of my new container:
version: '3'
services:
app:
container_name: app
restart: always
build: ./app
ports:
- "5000:5000"
command: gunicorn -w 1 -b 0.0.0.0:8000 wsgi:server
I tried to make the same connection as from the local computer, specifying the VM_ip, but that didn't help either.
I also tried to specify the <postgres> container ip instead of its name in the host=, but this also caused an error.
Do you know what could be the problem?
You need to create a network first which you will use to communicate between containers. You can do that by:
docker network create <example> #---> you can name it whatever you want
Then you need to connect both containers with the network that you made.
docker run -d --net example --name <postgres_container> <postgres_image>
docker run -d --net example --name <flask_container> <flask_image>
You can read more about the docker network in its documentation here:
https://docs.docker.com/network/
from what I can see you might be using the docker-compose file for the deployment of the services, you can add one more layer above the service layer for the network where you can define the network that is supposed to be used by the services that are deployed. The network that is defined needs also be mentioned in the service definition this lets the Internal DNS engine that docker-compose creates in the background discover all the services in the network with the help of the service name.
A Bridge network may be a good driver to be used here.
You can use the following links for a better understanding of networks in docker-compose.
https://docs.docker.com/compose/compose-file/compose-file-v3/#network
https://docs.docker.com/compose/compose-file/compose-file-v3/#networks

MongoDB connection problem with Docker container

Recently I'm using Docker and host it to our Dedicated Server everything is working fine,But Issue is we have made and absolute URL for mongodb here is our link below. I put mongodb URL in .env file
mongodb://<username>:<password>#<serverip>:27017/<dbname>?authSource=admin
This URL is accessible without docker, we have existing project in our server with this given URL and it is working. I did not use mongodb in our docker, it is installed globally in our server. Is there any suggestion ??
If you are trying to access the MongoDB from inside a container, replace the with the name of the service in you docker-compose file.
So if your docker-compose.yml looks like this
version: "2"
services:
mymongodb:
image: mongo
volumes:
- ./mongodb:/data/db:z
ports:
- 127.0.0.1:27017:27017
restart: always
your connection string looks like this: mongodb://<username>:<password>#mymongodb:27017/<dbname>?authSource=admin

unable to run docker flask image -pymongo.errors.ServerSelectionTimeoutError: localhost:27017: [Errno 111] Connection refused

I have built a docker image for a flask app I have with some html templates and after running my image I go to localhost:5000which takes me to the start page in my flask app . I press a register button to register a user using a flask endpoint but I get
pymongo.errors.ServerSelectionTimeoutError: localhost:27017: [Errno 111] Connection refused
Before going to localhost I run my mongodb image with sudo docker start mongodband the connection seems to hit this error whenever I have to search something in my monogdb database for the endpoint . Do I need a docker-compose.yml to connect and I cannot connect without one ?
This is how I connect to mongodb using pymongo
client = MongoClient('mongodb://localhost:27017/')
db = client['MovieFlixDB']
users = db['Users']
movies = db['Movies']
How I run my flask app :
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)
I would appreciate your help . Thank you in advance
To connect containers to each other you should use networks.
First you create a network
docker network create my-network
Run mongodb specyfing the network.
docker container run -d --name mongodb -p 27017:27017 --network my-network mongodb:latest
Modify your app to connect to mongodb as host instead of localhost. Containers that are connected to a common network can talk to each other by using their names (DNS names) that can be automatically resolved to container IPs.
client = MongoClient('mongodb://mongodb:27017/')
You could also think about providing such deatils (db host, user, password) through environment variables and read them in your app.
Rebuild image with your app and run it
docker container run --name flask-app -d --network my-network my-flaskapp-image
You can read more about container networking in docker docs.
Do I need a docker-compose.yml to connect and I cannot connect without
one ?
If you use docker-compose, it will be easier and don't have to use too many commands to deploy. Look at this example (there are too many however you can refer random service).
Steps -
Build your docker-componse file [I have modified the one in the example of random service, removing rest] e.g.
version: '3.3'
services:
web-random:
build:
context: .
args:
requirements: ./flask-mongodb-example/requirements.txt
image: web-random-image
ports:
- "800:5000"
entrypoint: python ./flask-mongodb-example/random_demo.py
depends_on:
- mongo
mongo:
image: mongo:4.2-bionic
ports:
- "27017:27017"
Refer this example to update your mongo URL in your python code
Now, use the following command to compose and bring up the containers
docker-compose build
docker-compose up
Now, either browse your URL with browser or use the curl command

Is a service running in a docker network secure from outside connection, even from localhost?

Question:
Can anybody with access to the host machine connect to a Docker network, or are services running within a docker network only visible to other services running in a Docker network assuming the ports are not exposed?
Background:
I currently have a web application with a postgresql database backend where both components are being run through docker on the same machine, and only the web app is exposing ports on the host machine. The web-app has no trouble connecting to the db as they are in the same docker network. I was considering removing the password from my database user so that I don't have to store the password on the host and pass it into the web-app container as a secret. Before I do that I want to ascertain how secure the docker network is.
Here is a sample of my docker-compose:
version: '3.3'
services:
database:
image: postgres:9.5
restart: always
volumes:
#preserves the database between containers
- /var/lib/my-web-app/database:/var/lib/postgresql/data
web-app:
image: my-web-app
depends_on:
- database
ports:
- "8080:8080"
- "8443:8443"
restart: always
secrets:
- source: DB_USER_PASSWORD
secrets:
DB_USER_PASSWORD:
file: /secrets/DB_USER_PASSWORD
Any help is appreciated.
On a native Linux host, anyone who has or can find the container-private IP address can directly contact the container. (Unprivileged prodding around with ifconfig can give you some hints that it's there.) On non-Linux there's typically a hidden Linux VM, and if you can get a shell in that, the same trick works. And of course if you can run any docker command then you can docker exec a shell in the container.
Docker's network-level protection isn't strong enough to be the only thing securing your database. Using standard username-and-password credentials is still required.
(Note that the docker exec path is especially powerful: since the unencrypted secrets are ultimately written into a path in the container, being able to run docker exec means you can easily extract them. Restricting docker access to root only is also good security practice.)

Connect to a mongoDB session from within container

I'm new to learning how to use goLang to build microservices. I had a whole project up and running locally, but when I tried deploying it I ran into a problem. The session I was working with (mgo.Dial("localhost")) was no longer working. When I put this into a docker image, it failed to connect to the local host, which makes sense, since the docker image builds it over a new OS (alpine in my case). I was wondering what I should do to get it to connect.
To be clear, when I was researching this, most people wanted to connect to a mongoDB session that is a docker container, I want to connect to a mongoDB session from within a docker container. Also once I'm ready for deployment I'll be using StatefulSet with kubernetes if that changes anything.
For example, this is what I want my program to be like:
sess, err := mgo.Dial("localhost") //or whatever
if err != nil {
fmt.Println("failed to connect")
else {
fmt.Println("connected")
What I tried doing:
Dockerfile:
FROM alpine:3.6
COPY /build/app /bin/
EXPOSE 8080
ENTRYPOINT ["/bin/app"]
In terminal:
docker build -t hell:4 .
docker run -d -p 8080:8080 hell:4
And as you can expect, it says not connected. Also the port mapping is for the rest of the project, not this part.
Thanks for your help!
I think you should not try to connect to the MongoDB server running on your machine. Think about deploying the whole application lateron you want a MongoDB server running together with your service on some cloud or server.
That problem could be solved by setting up an additional container and link it to your Go Web App. Docker compose can handle this. Just place a docker-compose.yml file in the directory you are executing your docker build in.
version: '3'
services:
myapp:
build: .
image: hell:4
ports:
- 8080:8080
links:
- mongodb
depends_on:
- mongodb
mongodb:
image: mongo:latest
ports:
- "27017:27017"
environment:
- MONGODB_USER="user"
- MONGODB_PASS="pass"
Something like this should do it (not tested). You have two services: One for your app that gets build according to your Dockerfile in the directory in which you currently are. Additionally it links to a service called mongodb defined below. The mongodb service is accessible via the service name mongodb.
If your mongoDB server is running in your host machine, replace localhost by you host IP.