Skip to content

Instantly share code, notes, and snippets.

@lucbettaieb
Created November 16, 2023 13:24
Show Gist options
  • Save lucbettaieb/8d05311495ab296e3059c16807899b0e to your computer and use it in GitHub Desktop.
Save lucbettaieb/8d05311495ab296e3059c16807899b0e to your computer and use it in GitHub Desktop.

Running a Docker on Google Cloud Run with Celery + Flask + Redis

Tricks

  1. Set everything up normally and get things working in testing.
  2. Have the docker run something like
CMD ["./server.sh"]

at the end

  1. In server.sh have something like
redis-server  &
P1=$!

celery -A app.celery worker --loglevel=info &
P2=$!

gunicorn --bind :5000 --workers 4 --threads 8 --timeout 0 app:app
P3=$!

wait $P1 $P2 $P3
  1. And run that locally... Does it work? Cool.
  2. When you deploy to Cloud Run, your tasks might fuck up if they're long lasting or making external API calls. In my case, I'm making a call to a Google API that takes a long time. Before I made a specific change I got an SSL errors galore.
  3. Make sure you switch the "CPU Allocation and Pricing" option to CPU is always allocated
  4. Should work

Yes I know I should use a VM or Sidecars or something. I don't care right now. I just need something that works. Remember, tech debt can be a privelage.

@lucbettaieb
Copy link
Author

lucbettaieb commented Jun 10, 2024

That didn't work for me with Celery making API calls to LLm APIs.

@lazaroborges
Are you deploying to cloud run? Steps 5/6 are important for it to work.

Happy to provide my 2 cents if you provide more details.

@lazaroborges
Copy link

Hey, thanks for the quick comment. I run it locally, and it will work fine. But when deployed, it breaks after the 2nd API call.

I guess the only substantial difference is that I use supervisord instead of a shell script to load the servers.

[supervisord]
nodaemon=true

[program:gunicorn]
command=gunicorn --config gunicorn-cfg.py core.wsgi
directory=/app
autostart=true
autorestart=true
stdout_logfile=/var/log/gunicorn.log
stderr_logfile=/var/log/gunicorn.log

[program:redis]
command=redis-server --dir /data --dbfilename "" 
autostart=true
autorestart=true
stdout_logfile=/var/log/redis.log
stderr_logfile=/var/log/redis.log

[program:celery]
command=celery -A apps.tasks worker -l info -B
directory=/app
autostart=true
autorestart=true
stdout_logfile=/var/log/celery.log
stderr_logfile=/var/log/celery.log
FROM python:3.12.3-slim

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV DJANGO_ENV production
ENV DJANGO_SETTINGS_MODULE core.settings
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
ENV DJANGO_DB_NAME /app/core/db/your_database.sqlite3
ENV DEBUG False

# Install system dependencies and node 18, npm, redis-server, supervisor, and locale in a single RUN to avoid multiple layers
RUN apt-get update && \
    apt-get install -y ca-certificates curl gnupg locales && \
    mkdir -p /etc/apt/keyrings && \
    curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | \
    gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
    echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" > /etc/apt/sources.list.d/nodesource.list && \
    apt-get update && \
    apt-get install -y nodejs redis-server supervisor python3-venv build-essential zsh && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

RUN chsh -s /bin/zsh

# Set up the locale
RUN echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && \
    locale-gen en_US.UTF-8 && \
    update-locale LANG=en_US.UTF-8

# Create the /data directory for Redis
RUN mkdir -p /data

# Copy the requirements.txt file into the container
COPY requirements.txt /tmp/

# Create a virtual environment
RUN python -m venv /opt/venv

# Activate the virtual environment and install python dependencies
ENV PATH="/opt/venv/bin:$PATH"
RUN pip install --upgrade pip && \
    pip install --no-cache-dir -r /tmp/requirements.txt

# Copy project files
COPY . /app

WORKDIR /app

# Copy Supervisor configuration file
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# Install npm dependencies and build assets
RUN npm install && \
    npm run build && \
    rm -rf node_modules

# Manage Assets & DB
RUN python manage.py collectstatic --no-input && \
    python manage.py makemigrations && \
    python manage.py migrate

RUN rm -f /app/celerybeat-schedule.db

RUN chmod 664 /app/core/db/db.sqlite3

# Expose ports for Gunicorn and Redis
EXPOSE 5005 6379 8080

ENV PORT 8080

# Command to run Supervisor to start all services
CMD ["/usr/bin/supervisord"]

@VladMusaelyan
Copy link

didn't work for me as well, i am also using supervisor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment