Search code examples
pythondockerflaskdeploymentvercel

Getting Flask app to deploy on Vercel with Docker: App.py is downloaded instead of being served as an image


I'm deploying a Flask application on Vercel using Docker, but when I access my endpoint to generate an image, the app.py file is downloaded instead of returning the expected image.

  • I have created a Dockerfile and a vercel.json configuration.
  • The app works locally using flask run, and the image is generated as expected.
  • On Vercel, after the deployment, visiting the endpoint (e.g., /generate_image?name=John) results in the browser downloading the app.py file instead of displaying the image.

Dockerfile:

# Use an official Python image
FROM python:3.9-slim

# Set working directory
WORKDIR /app

# Install system dependencies for Pillow (libjpeg, zlib)
RUN apt-get update && apt-get install -y libjpeg-dev zlib1g-dev

# Copy project files into the container
COPY . /app

# Copy the fonts directory into the Docker container
COPY fonts /app/fonts

# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt

# Expose the Flask port
EXPOSE 8000

# Install gunicorn (if not already in requirements.txt)
RUN pip install gunicorn

# Run the Flask app with gunicorn for production
CMD ["gunicorn", "-b", "0.0.0.0:8000", "app:app"]

vercel.json:

{
  "version": 2,
  "builds": [
    {
      "src": "Dockerfile",
      "use": "@vercel/docker"
    }
  ],
  "routes": [
    {
      "src": "/(.*)",
      "dest": "/app.py"
    }
  ],
  "functions": {
    "app.py": {
      "runtime": "python3.9",
      "includeFiles": "fonts/*"
    }
  },
  "build": {
    "env": {
      "LD_LIBRARY_PATH": "/usr/lib"
    }
  }
}

When visiting /generate_image?name=John, it should generate and display an image with the first letter of the name as an image in PNG format. Instead, the browser starts downloading the app.py file instead of returning the image as expected.

Do I need to modify my Vercel configuration or Dockerfile to handle the request correctly? Is there something wrong with how the routes are configured in the vercel.json file?

You can view the full project on GitHub here: Letter Image Generator Repo


Solution

  • I got it working by using Vercel's Python runtime. All I had to do was change the file name from 'app.py' to 'api/index.py', and the 'vercel.json' file to the following:

    {
      "rewrites": [
        { "source": "/(.*)", "destination": "/api/index" }
      ]
    } 
    

    I've also updated the requirements to use Flask and Pillow's latest versions:

    Flask==3.1.0
    pillow==11.1.0
    

    And you should also remove the 'venv' folder from github, by adding the line venv/ to you '.gitignore' file.

    You can test Vercel's Python runtime locally by running:

    npm i -g vercel
    vercel dev