Skip to content

Commit 61523ce

Browse files
authored
Merge pull request #90 from alkem-io/dockerfile
Dockerfile (distroless)
2 parents 989c3aa + 15594d2 commit 61523ce

File tree

5 files changed

+520
-399
lines changed

5 files changed

+520
-399
lines changed

.dockerignore

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
.git
2+
.gitignore
3+
.vscode
4+
.venv
5+
__pycache__
6+
*.pyc
7+
*.pyo
8+
*.pyd
9+
.DS_Store
10+
manifests
11+
.github
12+
.flake8
13+
.azure-template.env
14+
docker-compose.yaml
15+
Dockerfile
16+
README.md
17+
LICENSE

.github/workflows/build-deploy-k8s-sandbox-hetzner.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Build, Migrate & Deploy to Test on Hetzner
1+
name: Build, Migrate & Deploy to Sandbox on Hetzner
22

33
on:
44
workflow_dispatch:
@@ -24,6 +24,7 @@ jobs:
2424
2525
deploy:
2626
runs-on: ubuntu-latest
27+
needs: build
2728
steps:
2829
- name: "Checkout GitHub Action"
2930
uses: actions/checkout@v4.1.7

Dockerfile

Lines changed: 111 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,126 @@
1-
# Use an official Python runtime as a parent image
2-
ARG PYTHON_VERSION=3.11
3-
FROM python:${PYTHON_VERSION}-slim-bullseye AS builder
1+
# =============================================================================
2+
# Stage 1: Build stage - install dependencies using Debian Python for distroless compatibility
3+
# =============================================================================
4+
FROM debian:bookworm-slim AS builder
5+
6+
# Install Python, pip, git and build essentials in a single layer
7+
RUN apt-get update && \
8+
apt-get install -y --no-install-recommends \
9+
python3 \
10+
python3-pip \
11+
python3-venv \
12+
git \
13+
ca-certificates && \
14+
rm -rf /var/lib/apt/lists/*
415

5-
# Set the working directory in the container to /app
616
WORKDIR /app
717

8-
ARG GO_VERSION=1.21.6
18+
# Install Poetry in a separate venv to avoid PEP 668 issues
19+
RUN python3 -m venv /opt/poetry && \
20+
/opt/poetry/bin/pip install --no-cache-dir poetry && \
21+
ln -s /opt/poetry/bin/poetry /usr/local/bin/poetry
22+
23+
# Configure Poetry to create venv in project
24+
ENV POETRY_NO_INTERACTION=1 \
25+
POETRY_VIRTUALENVS_IN_PROJECT=true \
26+
POETRY_VIRTUALENVS_CREATE=true \
27+
POETRY_CACHE_DIR=/tmp/poetry_cache
28+
29+
# Copy only dependency files first (better layer caching)
30+
COPY pyproject.toml poetry.lock* ./
31+
32+
# Install dependencies (without dev dependencies)
33+
RUN poetry install --only main --no-root --no-ansi && \
34+
rm -rf $POETRY_CACHE_DIR && \
35+
# Remove pip + wheel (keep setuptools for runtime compatibility)
36+
/app/.venv/bin/pip uninstall -y pip wheel && \
37+
find /app/.venv -type d -name "__pycache__" -exec rm -rf {} + && \
38+
# Trim non-runtime content from installed packages
39+
SITE_PACKAGES="$(/app/.venv/bin/python -c 'import site; print(site.getsitepackages()[0])')" && \
40+
find "$SITE_PACKAGES" -type d \( \
41+
-name "tests" -o -name "test" -o \
42+
-name "docs" -o -name "doc" -o \
43+
-name "examples" -o -name "example" -o \
44+
-name "__pycache__" \
45+
\) -prune -exec rm -rf '{}' + && \
46+
find "$SITE_PACKAGES" -type f -name "*.pyc" -delete
47+
48+
# Copy application code (kept after dependency install for better caching)
49+
COPY . /app
50+
51+
# Create files/dirs that the distroless runtime cannot create (no shell)
52+
RUN touch /app/app.log
53+
54+
# =============================================================================
55+
# Stage 2: Runtime stage - Google distroless Python image
56+
# =============================================================================
57+
# NOTE: This image does NOT include Git or Hugo. The 'ingest' operation
58+
# will NOT work. Use the 'runtime-full' target if you need ingest capability.
59+
# =============================================================================
60+
FROM gcr.io/distroless/python3-debian12:nonroot AS runtime
61+
62+
# Copy the prebuilt app (code + venv + log file) from the builder.
63+
# Use UID/GID 1000 to stay compatible with typical host-mounted volumes.
64+
COPY --from=builder --chown=1000:1000 /app /app
65+
66+
WORKDIR /app
67+
68+
# Set PATH to use the venv's python executable
69+
ENV PATH="/app/.venv/bin:$PATH" \
70+
PYTHONDONTWRITEBYTECODE=1 \
71+
PYTHONUNBUFFERED=1 \
72+
PYTHONPATH="/app/.venv/lib/python3.11/site-packages:/app"
73+
74+
# Explicitly define the user
75+
USER 1000:1000
76+
77+
# Run main.py using the venv python
78+
ENTRYPOINT ["/app/.venv/bin/python", "main.py"]
79+
80+
# =============================================================================
81+
# Stage 3: Full runtime with Git and Hugo (for ingest capability)
82+
# =============================================================================
83+
FROM debian:bookworm-slim AS runtime-full
84+
985
ARG HUGO_VERSION=0.121.2
1086
ARG TARGETARCH
1187

12-
# install wget and git
13-
RUN apt-get update -y \
14-
&& apt-get upgrade -y \
15-
&& apt-get install -y git wget \
16-
&& apt-get clean \
17-
&& rm -rf /var/lib/apt/lists/*
88+
WORKDIR /app
89+
90+
# Install runtime dependencies
91+
RUN apt-get update && \
92+
apt-get install -y --no-install-recommends \
93+
python3 \
94+
git \
95+
ca-certificates && \
96+
rm -rf /var/lib/apt/lists/*
1897

19-
RUN wget https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz && tar -C /usr/local -xzf go${GO_VERSION}.linux-${TARGETARCH}.tar.gz
98+
# Install Hugo
99+
ADD https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-${TARGETARCH}.tar.gz /tmp/hugo.tar.gz
100+
RUN tar -C /usr/local/bin -xzf /tmp/hugo.tar.gz hugo \
101+
&& rm /tmp/hugo.tar.gz \
102+
&& hugo version
20103

21-
ENV PATH="/usr/local/go/bin:/usr/local:${PATH}"
22-
RUN go version
104+
# Create non-root user
105+
RUN useradd --create-home --uid 1000 --shell /bin/bash appuser
23106

24-
RUN wget https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-${TARGETARCH}.tar.gz \
25-
&& tar -C /bin -xzf hugo_extended_${HUGO_VERSION}_linux-${TARGETARCH}.tar.gz \
26-
&& rm hugo_extended_${HUGO_VERSION}_linux-${TARGETARCH}.tar.gz
107+
# Copy virtual environment from builder
108+
COPY --from=builder --chown=appuser:appuser /app/.venv /app/.venv
27109

28-
RUN hugo version
110+
# Copy application code
111+
COPY --chown=appuser:appuser . .
29112

30-
# Install Poetry
31-
RUN pip install poetry
113+
# Create a writable log file for the appuser
114+
RUN touch /app/app.log && chown appuser:appuser /app/app.log
32115

33-
# Copy the current directory contents into the container at /app
34-
COPY . /app
116+
# Set environment variables
117+
ENV VIRTUAL_ENV=/app/.venv \
118+
PATH="/app/.venv/bin:$PATH" \
119+
PYTHONDONTWRITEBYTECODE=1 \
120+
PYTHONUNBUFFERED=1
35121

36-
# # Use Poetry to install dependencies
37-
RUN poetry config virtualenvs.create true && poetry install --no-interaction --no-ansi
122+
# Switch to non-root user
123+
USER appuser
38124

39125
# Run main.py when the container launches
40-
CMD ["poetry", "run", "python", "main.py"]
126+
ENTRYPOINT ["/app/.venv/bin/python", "main.py"]

0 commit comments

Comments
 (0)