Docker container in-app port forwarding - python

I actually trying to make port forwarding for Docker which make request to mysql database on a remote server.
My goal is to create a copy of an app production in a container which can has access to an existent MySQL server based on a remote one.
I create a Dockerfile with all the requirements embedded, as follow :
FROM python:2.7-alpine
mkdir /working_env
RUN apk add --update mysql\
mysql-client\
python-dev\
build-base \
&& rm -rf /var/cache/apk/*
# Requirements here
RUN pip install -r requirements.txt
WORKSPACE working_env
COPY init.sh .
# BIND TO 8053
RUN init.sh start
and run this container with a volume mapped to the local project
docker run --name --rm project -v $(pwd):/working_env -d -p 8053:8053 project_docker
the call is made in my code as follows :
conn = MySQLdb.connect(host=10.11.12.13, port=3000, passwd=foo, user=admin, db=default)
But I want to be able when the call is made from inside my container, that it's been replaced from 10.11.12.13:3000 to 10.11.12.13:3001.
I've found topics about iptables and tries to create rules, but all my tries have failed in order to forward this port.
sudo iptables -t nat -A PREROUTING -s 127.0.0.1 -p tcp --dport 3000 -j REDIRECT --to 3001
Does it even possible to made this kind of modification or is it a another way to alter the port from inside the docker?

Related

Docker run does not produce any endpoint

I am trying to dockerize this repo. After building it like so:
docker build -t layoutlm-v2 .
I try to run it like so:
docker run -d -p 5001:5000 layoutlm-v2
It downloads the necessary libraries and packages:
And then nothing... No errors, no endpoints generated, just radio silence.
What's wrong? And how do I fix it?
You appear to be expecting your application to offer a service on port 5000, but it doesn't appear as if that's how your code behaves.
Looking at your code, you seem to be launching a service using gradio. According the quickstart, calling gr.Interface(...).launch() will launch a service on localhost:7860, and indeed, if you inspect a container booted from your image, we see:
root#74cf8b2463ab:/app# ss -tln
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 2048 127.0.0.1:7860 0.0.0.0:*
There's no way to access a service listening on localhost from outside the container, so we need to figure out how to fix that.
Looking at these docs, it looks like you can control the listen address using the server_name parameter:
server_name
to make app accessible on local network, set this to "0.0.0.0". Can be set by environment variable GRADIO_SERVER_NAME. If None, will use "127.0.0.1".
So if we run your image like this:
docker run -p 7860:7860 -e GRADIO_SERVER_NAME=0.0.0.0 layoutlm-v2
Then we should be able to access the interface on the host at http://localhost:7860/...and indeed, that seems to work:
Unrelated to your question:
You're setting up a virtual environment in your Dockerfile, but you're not using it, primarily because of a typo here:
ENV PATH="VIRTUAL_ENV/bin:$PATH"
You're missing a $ on $VIRTUAL_ENV.
You could optimize the order of operations in your Dockerfile. Right now, making a simple change to your Dockerfile (e.g, editing the CMD setting) will cause much of your image to be rebuilt. You could avoid that by restructuring the Dockerfile like this:
FROM python:3.9
# Install dependencies
RUN apt-get update && apt-get install -y tesseract-ocr
RUN pip install virtualenv && virtualenv venv -p python3
ENV VIRTUAL_ENV=/venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
WORKDIR /app
COPY requirements.txt ./
RUN pip install -r requirements.txt
RUN git clone https://github.com/facebookresearch/detectron2.git
RUN python -m pip install -e detectron2
COPY . /app
# Run the application:
CMD ["python", "-u", "app.py"]

container: volume dockerfile does not work

I m not able to launch new jupyter-notebook from my project.
Below my dockerfile.
FROM python:3.9.0
ARG WORK_DIR=/opt/dir1
RUN apt-get update && apt-get install cron -y && apt-get install -y default-jre
# Install python libraries
COPY requirements.txt /tmp/requirements.txt
RUN pip install --upgrade pip && pip install -r /tmp/requirements.txt
WORKDIR $WORK_DIR
EXPOSE 8888
# Copy etl code
# copy code on container under your workdir "/opt/dir1"
COPY . .
ENTRYPOINT ["sh", "-c"]
CMD ["jupyter-notebook --ip 0.0.0.0 --no-browser --allow-root]
VOLUME /home/data/dir1/
then in my terminal i did
#build
docker build -t my-python-app .
#run
docker run -it -p 8888:8888 my-python-app
#in container i did
jupyter notebook --ip 0.0.0.0 --no-browser --allow-root
I think that my VOLUME doesn't work because when i did modifications in file of container nothing happens in the host /home/data/dir1/.
Does anyone knows why and how to solve it?
You can use, docker run -it /bin/bash (image name)
and try to navigate to the folder you have set the volume to, and see if an error occurs and check permissions.
When using volumes, check on the host system you can access the folder. Afterwards check which user you are, Docker allows to parse your USER_ID and GROUP_ID to the container.
From there you can use the same user and group as you are on the host system. If you wanted to access the same folder on the host system, you can enter into permissions problems.
More information on this on the following webpage.
https://jtreminio.com/blog/running-docker-containers-as-current-host-user/
Maybe it's could be help you : try another way to start the volume inside container, for example add it within "run" command container creation. i've working with docker and i've never added volumes in this way (this doesn't mean you way is wrong)
Here two examples to working with volumens,I recommend you second link.
docker official docs , working with volumes example

docker port exposing issue

I have a flask application that I'm trying to dockerize but the ports are not getting exposed properly.
DockerFile
FROM tiangolo/uwsgi-nginx-flask:python3.7
LABEL Name=testAPP Version=0.0.1
EXPOSE 5000
ADD . /app
WORKDIR /app
# Using pip:
RUN python3 -m pip install -r requirements.txt
ENTRYPOINT [ "python3" ]
CMD ["application.py" ,"runserver","-h 0.0.0.0"]
Docker Build is successful:
docker build --rm -f "Dockerfile" -t testAPP .
Docker Run is building the image successfully
docker run -device -expose 5000:5000 testAPP
Also tried,
docker run --rm -d -p 443:443/tcp -p 5000:5000/tcp -p 80:80/tcp testAPP
But when I try to access the site it throws an error
site can't be reached error
Flask App(Inside the APP)
if __name__ == '__main__':
app.run(host='127.0.0.1', port=5000)
On Execution of the command
Docker container ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8724cdb38e14 testAPP "/entrypoint.sh pyth…" 15 seconds ago Up 13 seconds 80/tcp, 443/tcp, 0.0.0.0:5000->5000/tcp funny_galois
Defining a port as exposed doesn’t publish the port by itself. Try with the flag -p , like:
-p container_port:local_port
example:
docker run -p 8080:8080 -v ~/Code/PYTHON/ttftt-recipes-manager:/app python_dev
But before running try to check if there is something else that already running on the specified port like:
lsof -i :PORTNUM
and after with something like:
docker logs my_container
Make sure you're mapping your localhost port to the container's port
docker run -p 127.0.0.1:8000:8000 your_image
And once you're application is in the container, you want to run your app with the host set to 0.0.0.0

I can't access docker from outside the container [duplicate]

This question already has answers here:
Configure Flask dev server to be visible across the network
(17 answers)
Are a WSGI server and HTTP server required to serve a Flask app?
(3 answers)
Closed 5 years ago.
I have to "dockerize" a service I'm writing (a small Flask app). This is what I wrote:
FROM python:3
RUN apt-get update && apt-get install -y build-essential
WORKDIR /app
COPY requirements.txt /app
RUN pip install --no-cache-dir -r requirements.txt
COPY . /app
EXPOSE 5000
ENV FLASK_APP=app.py
ENV FLASK_DEBUG=1
CMD flask run
I can build the image and run the container with
docker run -p 5000:5000 <container-name>
and flask tells me it's listening on 127.0.0.1:5000. But I can't access the application from my host machine. I've also tried using the localhost and 0.0.0.0 as the address. However, if I exec into the container I can curl the address to receive the response I expect.
Does anyone know what's going on here?
The EXPOSE instruction does not actually publish the port. You also have to also tell docker to forward connections to that port. When running you would do docker run -p 80:5000 my_docker_image and then traffic inbound on port 80 will be forwarded to port 5000 within the docker container. Alternatively you could forward port 5000 to 5000 in the docker image if you don't want to listen on port 80.

Cannot hit docker container running locally

Here's my Dockerfile:
FROM alpine:3.5
RUN apk add --no-cache python3 && \
python3 -m ensurepip && \
rm -r /usr/lib/python*/ensurepip && \
pip3 install --upgrade pip setuptools && \
rm -r /root/.cache
# Copy files
COPY ./requirements.txt /app/requirements.txt
COPY ./main.py /app/main.py
# Install deps
RUN pip install --upgrade pip
RUN pip install --requirement /app/requirements.txt
# Set the default directory where CMD will execute
WORKDIR /app
EXPOSE 5000
CMD [ "python3", "-u", "./main.py" ]
and my main.py file:
from flask im
port Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
After building the tag and running it via docker run <tag>, get logs saying the flask server was successfully started:
$ docker run test:latest
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
But I cannot hit the server in my browser.
I thought the problem may be in the port mapping, so I ran the container like this:
$ docker run -p 5000:5000 test:latest
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
Still no dice. I am able to run the server outside of the container, simply by running python3 main.py. what am I doing wrong?
The script is listening to 127.0.0.1 in the container, making it inaccessible from the host. It must listen to 0.0.0.0.
The 127.0.0.1 address that you see is the localhost of the container networking, that is not the same as the main host. When exposing ports, docker maps a port binding in container internal IP (172.17....) to a port in the hosts interfaces.
So you must tell your flask to listen to all of its interfaces:
app.run(host='0.0.0.0')
127.0.0.1 is the loopback address (also known as localhost).
0.0.0.0 is a non-routable meta-address used to designate an invalid, unknown, or non-applicable target (a ‘no particular address’ place holder). For things like address binding of network connections, the result can be to assign an appropriate interface address to the connection.
In Docker, the loopback address (127.0.0.1) of a container is not the same as the host. Use 0.0.0.0 as the host instead.
app.run(host='0.0.0.0')

Categories