diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..481ec1a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +# Ignore everything in build context since we clone from git +* + +# But don't ignore .dockerignore itself (for documentation) +!.dockerignore diff --git a/Dockerfile b/Dockerfile index c397769..6424e10 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,25 +1,28 @@ +# --- Stage 1: Build Zola site --- FROM alpine:3.20 AS builder -RUN echo "@community https://dl-cdn.alpinelinux.org/alpine/v3.20/community" \ - >> /etc/apk/repositories && \ - apk add --no-cache zola git +RUN echo "@community https://dl-cdn.alpinelinux.org/alpine/v3.20/community" >> /etc/apk/repositories && \ + apk add --no-cache git zola bash WORKDIR /site -COPY src/ . +RUN git clone --depth=1 --recurse-submodules https://git.rbitton.com/rbitton/Website.git . -RUN git clone https://git.rbitton.com/rbitton/Resume.git /tmp/resume && \ - mkdir -p static/files && \ - mkdir -p content/resume && \ - # cp /tmp/resume/RAPHAEL_BITTON.pdf static/files/ && \ - sh -c "(printf '+++\n\ -title = \"Resume\"\n\ -date = 2025-10-09\n\ -+++\n\n' && cat /tmp/resume/RAPHAEL_BITTON.md) > content/resume/_index.md" - +WORKDIR /site/src RUN zola build --force -FROM nginx:alpine -COPY --from=builder /site/public /usr/share/nginx/html -EXPOSE 80 -CMD ["nginx", "-g", "daemon off;"] + +# --- Stage 2: Runtime --- +FROM python:3.12-alpine + +RUN apk add --no-cache nginx git zola bash + +COPY --from=builder /site /site +COPY --from=builder /site/src/public /usr/share/nginx/html +COPY --from=builder /site/webhook.py /usr/local/bin/webhook.py + +ENV DEPLOY_SECRET="supersecret" +WORKDIR /site/src +EXPOSE 80 5001 + +CMD sh -c "python3 /usr/local/bin/webhook.py & nginx -g 'daemon off;'" diff --git a/webhook.py b/webhook.py new file mode 100755 index 0000000..b6ba027 --- /dev/null +++ b/webhook.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +import os +import subprocess +from http.server import BaseHTTPRequestHandler, HTTPServer + +DEPLOY_SECRET = os.getenv("DEPLOY_SECRET", "supersecret") + +class Handler(BaseHTTPRequestHandler): + def do_POST(self): + auth = self.headers.get("Authorization") + if auth != f"Bearer {DEPLOY_SECRET}": + self.send_response(403) + self.end_headers() + self.wfile.write(b"unauthorized\n") + print("[!] Unauthorized webhook attempt") + return + + print("[+] Authorized redeploy request received") + + # Pull latest Website + subprocess.run(["git", "-C", "/site", "pull", "--recurse-submodules"], check=False) + + # Rebuild site + subprocess.run(["zola", "build", "--force"], cwd="/site/src", check=False) + subprocess.run(["sh", "-c", "cp -r /site/src/public/* /usr/share/nginx/html/"], shell=True, check=False) + + self.send_response(200) + self.end_headers() + self.wfile.write(b"OK\n") + print("Site rebuilt successfully") + +def run(): + server = HTTPServer(("0.0.0.0", 5001), Handler) + print("Listening on port 5001 for /hooks/redeploy ...") + server.serve_forever() + +if __name__ == "__main__": + run()