cant connect make request from fastapi container to kafka container - python

I have two containers one is kafka container open port 9092:9092 and another is Fastapi container. If I don't dockerize Fastapi, I can make rest api request to fastapi to kafka. It sends message to kafka via fastapi. But when I dockerize fastapi can't connect fastapi container to kafka container.
I cant run fastapi docker file with -p 8000:8000 -p 9092:9092 it says 9092 is already used.
How can I make request to fastapi container then fastapi connects to kafka container.
fastapi dockerfile
FROM python:3.8.10
ADD . .
COPY requirements.txt .
RUN pip3 install -r requirements.txt
CMD ["python3", "main.py"]
My error is
kafka.errors.NoBrokersAvailable: NoBrokersAvailable.
I get kafka container IP address and I am making to kafka container IP address example
producer = KafkaProducer(bootstrap_servers=containerip, value_serializer=lambda x: json.dumps(x).encode('utf-8'),api_version=(2)), lines=True, orient='records')

cant run fastapi docker file with -p 8000:8000 -p 9092:9092 it says 9092 is already used.
Remove it then. Unclear why you need port 9092 on your API, anyway ; it's not the Kafka service.
Without seeing your complete Kafka client code, it's hard to say what your other problems are, so please consult Connect to Kafka running in Docker
For example, what is containerip? This should be kafka:9092 (if you follow the instructions in the linked post)
Run docker network create
Make sure you use docker run with --network on both containers
Ensure KAFKA_ADVERTISTED_LISTENERS variable contains at least INTERNAL://kafka:9092
Remove the -p flags for the Kafka container since you are only interacting with Kafka from another container.
Connect Python to kafka:9092

If you set network mode of your container to host, it's done.
run your fast-api (pay attention to network switch):
docker run --network host -p 8000:8000 fast-api
run kafka:
docker run -p 9092:9092 kafka
run postgres:
docker run -p 5432:5432 postgres
but it's better to use bridge-networks.

Related

Container didn't respond to HTTP pings on port: 80, failing site start

I have deployed python:3.8-slim-buster image to the App Service. Generally it is being run correctly as I can see the processing in the logs, however the health-check mechanism tries to ping the hosted server but it does not respond as it is only code that runs in a loop and process the messages from the queue.
It would be fine, but the application is being killed with the error:
Container didn't respond to HTTP pings on port: 80, failing site start.
Stopping site because it failed during startup.
Is there either a way to remove this Waiting for response to warmup request for container or specify in the dockerfile to respond with OK to those requests?
Currently my dockerfile is a 2 liner, that only copies the scripts and then runs python script.
The code that is inside this script is copied from https://learn.microsoft.com/en-us/azure/event-hubs/event-hubs-python-get-started-send#create-a-python-script-to-receive-events
The Dockerfile:
FROM python:3.8-slim-buster
COPY ./Scripts .
CMD [ "python3","-u","./calculate.py"]
The fix for that is to either host the script in a server e.g. nodejs or equivalent for given language, or create separate process that will return something for the 80 port.
There also might be a problem with the port configured on default, here is an answer how to fix that case:
https://serverfault.com/questions/1003418/azure-docker-app-error-site-did-not-start-within-expected-time-limit-and-co
step-1
add EXPOSE 8080 inside Dockerfile
step-2
build image from Dockerfile:
docker build . -t python-calculator
step-3
docker images #search the image with the tag you mentioned earlier i.e python-calculator
step-4
docker run -p 8080:8080 -d
step-5
localhost:8080

Connection Refused on MongoDB Docker Container from Flask Docker Container

I have two docker containers.
Flask app
MongoDB
Flask app has a DockerFile that looks like this.
from alpine:latest
RUN apk add --no-cache python3-dev \
&& pip3 install --upgrade pip
WORKDIR /app
COPY . /app
RUN pip3 --no-cache-dir install -r requirements.txt
EXPOSE 5000
ENTRYPOINT ["python3"]
CMD ["app.py"]
This is how I am connecting my local Mongo (Not Container) from Flask
mongo_uri = "mongodb://host.docker.internal:27017/myDB"
appInstance.config["MONGO_URI"] = mongo_uri
mongo = PyMongo(appInstance)
MongoDB is running on the container in mongodb://0.0.0.0:2717/myDB.
This is obvious when I run Flask container with local mongo uri which is mongodb://host.docker.internal:27017/myDB, everything works. But It shouldn't work when I try to connect the Mongo Container in the same way. Coz Flask container doesn't know anything about that Mongo Container.
My question is - how do I connect this Mongo Container with Flask Container so that I can query Mongo container from Flask Container.
Thanks in advance.
If I was you, I would use docker-compose.
Solution just using docker
You'd have to find out the IP address of your mongo container and put this IP in the flask configuration file. Keep in mind that the IP address of the container can change - for example if you use a newer image.
Find IP address:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name_or_id
Solution using docker-compose
In your docker-compose file you'd define two services - one for flask and one for mongo. In the flask configuration file you can then access the mongo container with its service name as both services run in the same network.
docker-compose.yml:
services:
mongo:
...
flask:
...
flask configuration:
mongo_uri = "mongodb://mongo/myDB"
In this example mongo is the name for your mongo service.

Azure App Service: specifying docker run port on container side

I want to use scrapinghub/splash container on Azure App Service (Web App for Containers) on Linux.
But docker run command on deploy randomly changes the binding port of container side (see the log below, port 8961 is automatically assigned. this number varies every deploy)
2020-01-21 08:56:47.494 INFO - docker run -d -p 8961:8050 --name b2scraper-splash_3_d89ce1f2 -e WEBSITES_ENABLE_APP_SERVICE_STORAGE=false -e WEBSITES_PORT=8050 -e WEBSITE_SITE_NAME=b2scraper-splash -e WEBSITE_AUTH_ENABLED=False -e PORT=8050 -e WEBSITE_ROLE_INSTANCE_ID=0 -e WEBSITE_HOSTNAME=b2scraper-splash.azurewebsites.net -e WEBSITE_INSTANCE_ID=5446f93a2cbcb25300f091395c54ce738773ce47489c2818322ffabbc23e3413 scrapinghub/splash:latest python3 /app/bin/splash --proxy-profiles-path /etc/splash/proxy-profiles --js-profiles-path /etc/splash/js-profiles --filters-path /etc/splash/filters --lua-package-path "/etc/splash/lua_modules/?.lua" --disable-private-mode --port 8050
Changing host port binding is possible using WEBSITES_PORT, but seems no way to change container side.
Is there way to fix container-side port binding like -p 8050:80 or -p 8050:443 of docker run command?
e.g. Using the container on Azure Container Instances is possible, without changing service port 8050.
--publish in the docker run command creates a firewall rule which maps a container port to a port on the Docker host.
https://docs.docker.com/config/containers/container-networking/
For the command: docker run -d -p 8961:8050 imagename, TCP port 8050 in the container is mapped to 8961 on the Docker Host. On App Services, this docker run command cannot be changed. The container port (8050 in this case) can be set to a specific value using WEBSITES_PORT application setting.
That doesn´t work. you get 443 as port with HTTPS.
Neither EXPOSE XXXX, nor WEBSITES_PORT or PORT as configuration parameters...
You do see "docker run -d -p 8961:8050" in the logs, but it doesn´t matter to Azure when it comes to exposing the app...

get a python docker container to interact with a redis docker container

I'm new to docker, redis and any kind of networking, (I know python at least!). Firstly I have figured out how to get a redis docker image and run it in a docker container:
docker run --name some-redis -d redis
As I understand this redis instance has port 6379 available to connect to other containers.
docker network inspect bridge
"Containers": {
"2ecceba2756abf20d5396078fd9b2ecf0d60ab04ca6b8df5e1b631b6fb5e9a85": {
"Name": "some-redis",
"EndpointID": "09f0069dae3632a2456cb4d82ad5e7c9782a2b58cb7a4ee655f57b5c410c3e87",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
If I run the following command I can interact with the redis instance and generate key:value pairs:
docker run -it --link some-redis:redis --rm redis redis-cli -h redis -p 6379
set 'a' 'abc'
>OK
get 'a'
>"abc"
quit
I have figured out how to make and run a docker container with the redis library installed that will run a python script as follows:
Here is my Dockerfile:
FROM python:3
ADD redis_test_script.py /
RUN pip install redis
CMD [ "python", "./redis_test_script.py" ]
Here is redis_test_script.py:
import redis
print("hello redis-py")
Build the docker image:
docker build -t python-redis-py .
If I run the following command the script runs in its container:
docker run -it --rm --name pyRed python-redis-py
and returns the expected:
>hello redis-py
It seems like both containers are working ok, the problem is connecting them both together, I would like to ultimately use python to perform operation on the redis container. If I modify the script as follows and rebuild the image for the python container it fails:
import redis
print("hello redis-py")
r = redis.Redis(host="localhost", port=6379, db=0)
r.set('z', 'xyz')
r.get('z')
I get several errors:
...
OSError: [Errno 99] Cannot assign requested address
...
redis.exceptions.ConnectionError: Error 99 connecting to localhost:6379. Cannot assign requested address.
.....
It looks like they're not connecting, I tried again using the bridge IP in the python script:
r = redis.Redis(host="172.17.0.0/16", port=6379, db=0)
and get this error:
redis.exceptions.ConnectionError: Error -2 connecting to 172.17.0.0/16:6379. Name or service not known.
and I tried the redis sub IP:
r = redis.Redis(host="172.17.0.2/16", port=6379, db=0)
and I get this error:
redis.exceptions.ConnectionError: Error -2 connecting to 172.17.0.2/16:6379. Name or service not known.
It feels like I'm fundamentally misunderstanding something about how to get the containers to talk to each other. I've read quite a lot of documentation and tutorials but as I say have no networking experience and have not previously used docker so any helpful explanations and/or solutions would be really great.
Many thanks
That's all about Docker networking. Fast solution - use host network mode for both containers. Drawback is low isolation, but you will get it working fast:
docker run -d --network=host redis ...
docker run --network=host python-redis-py ...
Then to connect from python to redis just use localhost as a hostname.
Better solution is to use docker user-defined bridge network
# create network
docker network create foo
docker run -d --network=foo --name my-db redis ...
docker run --network=foo python-redis-py ...
Note that in this case you cannot use localhost but instead use my-db as a hostname. That's why I've used --name my-db parameter when starting first container. In user-defined bridge networks containers reach each other by theirs names.
Do:
Explicitly create a Docker network for your application, and run your containers connected to that network. (If you use Docker Compose, this happens for you automatically and you don’t need to do anything.)
docker network create foo
docker run -d --net foo --name some-redis redis
docker run -it --rm --net foo --name pyRed python-redis-py
Use containers’ --name as DNS hostnames: you connect to some-redis:6379 to reach the container. (In Docker Compose the name of the service block works too.)
Make the locations of external services configurable, most likely using an environment variable. In your Python code you can connect to
redis.Redis(host=os.environ.get("REDIS_HOST", "localhost"),
port=int(os.environ.get("REDIS_PORT", "6379"))
docker run --rm -it \
--name py-red \
--net foo \
-e REDIS_HOST=some-redis \
python-redis-py
Don’t:
docker inspect anything to find the container-private IP addresses. Between containers you can always use hostnames as described above. The container-private IP addresses are unreachable from other hosts, and may even be unreachable from the same hosts on some platforms.
Use localhost in Docker for anything, expect the specific case of connecting from a browser or other process running directly on the host (not in a container) to a port you’ve published with docker run -p on the same host. (It generally means “this container”.)
Hard-code host names in your code like this; it makes it hard to run the service in a different environment. (For databases in particular it’s not uncommon to run them outside of Docker or even in a hosted cloud service.)
Use --link, it’s outdated and unnecessary.

Connection Refused Docker Run

I'm getting a connection refused after building my Docker image and running docker run -t imageName
Inside the container my python script is making web requests (external API call) and then communicating over localhost:5000 to a logstash socket.
My dockerfile is really simple:
FROM ubuntu:14.04
RUN apt-get update -y
RUN apt-get install -y nginx git python-setuptools python-dev
RUN easy_install pip
#Install app dependencies
RUN pip install requests configparser
EXPOSE 80
EXPOSE 5000
#Add project directory
ADD . /usr/local/scripts/
#Set default working directory
WORKDIR /usr/local/scripts
CMD ["python", "logs.py"]
However, I get a [ERROR] Connection refused message when I try to run this. It's not immediately obvious to me what I'm doing wrong here - I believe I'm opening 80 and 5000 to the outside world? Is this incorrect? Thanks.
Regarding EXPOSE:
Each container you run has its own network interface. Doing EXPOSE 5000 tell docker to link a port 5000 from container-network-interface to a random port in your host machine (see it with docker ps), as long as you tell docker to do it when you docker run with -P.
Regarding logstash.
If your logstash is installed in your host, or in another container, it means that logstash is not in the "localhost" of the container (remember that each container has its own network interface, each one has its own localhost). So you need to point to logstash properly.
How?
Method 1:
Don't give container its own iterface, so it has the same localhost as your machine:
docker run --net=host ...
Method 2:
If you are using docker-compose, use the docker network linking. i.e:
services:
py_app:
...
links:
- logstash
logstash:
image: .../logstash..
So point as this: logstash:5000 (docker will resolve that name to the internal IP corresponding to logstash)
Method 3:
If logstash listen in your localhost:5000 (from your host), you can point to it as this: 172.17.0.1:5000 from inside your container (the 172.17.0.1 is the host fixed IP, but this option is less elegant, arguably)

Categories