0
votes

I have developed a small project using flask/tensorflow. It runs under app server - gunicorn. I have to also include nginx into the project for serving static files. Without docker app is running fine. All parts(gunicorn, nginx, flask) cooperate as intended. It's now time to move this project to an online server, and i need to do it via docker.

Nginx and gunicorn->flask app communicate via unix socket. In my localhost environment i used socket inside app root folder - myapp/app.sock, it all worked great.

Problem now is that i can't quite understand how do i tell nginx inside docker to use same socket file and tell gunicorn to listen to it. I get the following error:

upstream: http:// unix:/var/run/app.sock failed (No such file or directory) while connecting to upstream

Tried using different paths to socket file, but no luck - same error.

docker-compose file:

version: '3'
services:
  nginx:
    image: nginx:latest
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/remote-app:/etc/nginx/sites-enabled/remote-app
      - /etc/nginx/proxy_params:/etc/nginx/proxy_params
    ports:
      - 8000:8000
    
    build: .
    command: gunicorn --bind unix:/var/run/app.sock wsgi:app --reload --workers 1 --timeout 60
    
    environment:
      - FLASK_APP=prediction_service.py
      - FLASK_DEBUG=1
      - PYTHONUNBUFFERED=True
    restart: on-failure

main Dockerfile (for main app, it builds app fine, all is working):

FROM python:3.8-slim

RUN pip install flask gunicorn flask_wtf boto3 tqdm
RUN pip install numpy==1.18.5
RUN pip install tensorflow==2.2.0 onnxruntime==1.4.0

COPY *.ipynb /temp/
COPY *.hdf5 /temp/
COPY *.onnx /temp/
COPY *.json /temp/
COPY *.py /temp/

WORKDIR /temp

nginx.conf is 99% same as default with only increased file size for uploading to 8M proxy-params is just a preset of configurtion params for making nginx proxy requests and remote-app is a config for my app(simple one):

server {
    listen 8000;
    server_name localhost;

   location / {
      include proxy_params;
      proxy_pass htpp://unix:/var/run/app.sock; //**tried /temp/app.sock here same issue**
}
}

So if i open localhost(even without port 8000) i can get nginx answer. If i try to open localhost:8000 i get that socket error( that is pasted above with strong text ).

1

1 Answers

1
votes

I would avoid using sockets for this, as there is IP communication between containers/services, and you really should have a separate service for the app server.

Something like:

version: '3'
services:

  nginx:
    image: nginx:latest
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/remote-app:/etc/nginx/sites-enabled/remote-app
      - /etc/nginx/proxy_params:/etc/nginx/proxy_params
    ports:
      - 80:80
      - 143:143

  app_server:
    build: .
    command: gunicorn --bind '0.0.0.0:5000' wsgi:app --reload --workers 1 --timeout 60
    
    environment:
      - FLASK_APP=prediction_service.py
      - FLASK_DEBUG=1
      - PYTHONUNBUFFERED=True
    restart: on-failure

Notice instead of binding gunicorn to the socket, it is bound to all IP interfaces of the app_server container on port 5000.

With the separate service app_server alongside your current nginx service, you can simply treat these values like DNS aliases in each container. So in the nginx config:

proxy_pass http://app_server:5000/

So if i open localhost(even without port 8000) i can get nginx answer.

That sounds like you mean connecting to localhost on port 80 which could be a nginx server running on the host machine. This is also suggested by this line in your compose file: /etc/nginx/proxy_params:/etc/nginx/proxy_params.

That's loading the file from a local installation of nginx on the host. You should probably be aware of this, as having that server running also could confuse you when debugging, and launching this compose file somewhere would mean /etc/nginx/proxy_params has to be present on the host.

You should probably store this in the project directory, like the other files which are mounted, and mount it like:

  - ./nginx/proxy_params:/etc/nginx/proxy_params