Skip to content

Instantly share code, notes, and snippets.

@operatorequals
Last active May 19, 2022 01:06
Show Gist options
  • Save operatorequals/a1264ad67b3b9a08651c9736bbfe26b0 to your computer and use it in GitHub Desktop.
Save operatorequals/a1264ad67b3b9a08651c9736bbfe26b0 to your computer and use it in GitHub Desktop.
Cython to ELF multistage build Dockerfile
# Inspired by:
# https://pythonspeed.com/articles/faster-multi-stage-builds/
# Builder image
FROM python:3.7-slim as compile-image
# Install all cython and C toolchain
# Save some space from the compile-image by apt-cleaning and deleting
RUN apt-get update
RUN apt-get install -y --no-install-recommends gcc cython3 python3-dev \
apt-get clean \
rm -rf /var/lib/apt/lists/*
WORKDIR /root
# ----
COPY main.py .
# ----
# Transpile 'main.py' to 'main.c'
RUN cython3 -3 --embed -o main.c main.py
# Compile 'main.c' to an 'main' ELF
RUN gcc -Os -I /usr/include/python3.7m -o main main.c -lpython3.7m -lpthread -lm -lutil
# Use different image for runtime
FROM python:3.7-slim as runtime-image
# Create non-root user (Security First!)
RUN useradd --create-home appuser
WORKDIR /home/appuser
USER appuser
# Copy 'main' executable to a brand new Python3.7m image (it has to be linked against 'python3.7m')
COPY --from=compile-image /root/main .
# Use it as entrypoint
CMD [ "./main" ]
#!/usr/bin/env python3
# cython: language_level=3
print(1)
@operatorequals
Copy link
Author

Building will produce a container of about 450MB which is the builder and one of ~ 180MB which is the runtime

$ docker build -t cython3-twostage:latest .
$ docker run -ti cython3-twostage:latest

@russau
Copy link

russau commented May 19, 2022

This is cool... I see that python3-dev now installs 3.9 headers. I managed to get everything to work by updating everything to 3.9.

There's also some missing &&.

# Builder image
FROM python:3.9-slim as compile-image

# Install all cython and C toolchain
#   Save some space from the compile-image by apt-cleaning and deleting
RUN apt-get update
RUN apt-get install -y --no-install-recommends gcc cython3 python3-dev && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*

WORKDIR /root
# ----
COPY main.py .
# ----

# Transpile 'main.py' to 'main.c'
RUN cython3 -3 --embed -o main.c main.py
# Compile 'main.c' to an 'main' ELF 
RUN gcc -Os -I /usr/include/python3.9 -o main main.c -lpython3.9 -lpthread -lm -lutil

# Use different image for runtime
FROM python:3.9-slim as runtime-image

# Create non-root user (Security First!)
RUN useradd --create-home appuser
WORKDIR /home/appuser
USER appuser

# Copy 'main' executable to a brand new Python3.7m image (it has to be linked against 'python3.7m')
COPY --from=compile-image /root/main .

# Use it as entrypoint
CMD [ "./main" ]

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