Skip to content

Instantly share code, notes, and snippets.

@tushev
Created January 31, 2024 17:25
Show Gist options
  • Save tushev/dd6682ca3ea1ccdc4b8facd39cb0cc1b to your computer and use it in GitHub Desktop.
Save tushev/dd6682ca3ea1ccdc4b8facd39cb0cc1b to your computer and use it in GitHub Desktop.
Minimal dockerizable FastCGI example using Python
COMPOSE_PROJECT_NAME = example
PYTHON_VER = 3
CONTAINER_UID = 1000
CONTAINER_GID = 1000
SOCKET_UID = 1000
SOCKET_GID = 33
SOCKET_MODE = 660
PUBLIC_SOCKETDIR = ./sockets
INTERNAL_SOCKETDIR = /fcgi-sockets.d/
version: '3.9'
services:
example:
build:
context: ./app
dockerfile: Dockerfile
args:
PYTHON_VER: '${PYTHON_VER}'
INTERNAL_SOCKETDIR: '${INTERNAL_SOCKETDIR}'
SOCKET_UID: '${SOCKET_UID}'
SOCKET_GID: '${SOCKET_GID}'
user: '${CONTAINER_UID}:${CONTAINER_GID}'
container_name: '${COMPOSE_PROJECT_NAME}'
restart: unless-stopped
environment:
SOCKET_MODE: '${SOCKET_MODE}'
SOCKET_DIR: '${INTERNAL_SOCKETDIR}'
volumes:
- ${PUBLIC_SOCKETDIR}:${INTERNAL_SOCKETDIR}
ARG PYTHON_VER
FROM python:${PYTHON_VER}
WORKDIR /example
COPY example.py /example/example.py
COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
ARG SOCKET_UID
ARG SOCKET_GID
ARG INTERNAL_SOCKETDIR
RUN (mkdir --mode=u+rwx,g+rs,g-w,o-rwx -p $INTERNAL_SOCKETDIR ) && \
(chown $SOCKET_UID:$SOCKET_GID $INTERNAL_SOCKETDIR )
# make sure that host directory matches these permissions
CMD [ "python3", "/example/example.py" ]
#!/bin/bash
# Load variables from Docker's `.env` file
if [ -f .env ]
then
export -n $(cat .env | sed -e '/^#/d;/^\s*$/d' -e "s/'/'\\\''/g" -e "s/\t//g" | tr -d ' ' | xargs -d '\n')
fi
# Set permissions for volume mounts
if [ -n "$PUBLIC_SOCKETDIR" ]
then
mkdir ${PUBLIC_SOCKETDIR}
chown ${SOCKET_UID}:${SOCKET_GID} ${PUBLIC_SOCKETDIR}
chmod 6710 ${PUBLIC_SOCKETDIR}
fi
#!/usr/bin/python3
# ############################################
from fastcgi import *
from pathlib import Path
from socketserver import UnixStreamServer,TCPServer
from warnings import warn
import sys, os, csv
sock_dir = os.environ.get('SOCKET_DIR', '/fcgi-sockets.d/')
sock_path = f'{sock_dir}/fcgi.sock'
sock_mode = int(os.environ.get('SOCKET_MODE', '660'), 8) # convert to octal
p = Path(sock_path)
if p.exists(): p.unlink()
class FCGIRequestHandler(FcgiHandler):
def handle(self):
self.print(f'Content-type: text/html\n\n<h1>Hello {os.getuid()}!</h1>\n')
self.print(f'<h4>OS</h4><pre>\n')
self.print( '\n'.join([f'{k} = {v}' for k, v in os.environ.items()]) )
self.print(f'</pre><hr><h4>FastCGI::params</h4><pre>\n')
self.print( '\n'.join([f'{k} = {v}' for k, v in self.environ.items()]) )
self.print(f'</pre>\n')
with UnixStreamServer(str(p), FCGIRequestHandler) as srv:
os.chmod(sock_path, sock_mode)
srv.serve_forever()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment