-
-
Notifications
You must be signed in to change notification settings - Fork 54
Expand file tree
/
Copy pathdockerfile
More file actions
167 lines (143 loc) · 6.74 KB
/
dockerfile
File metadata and controls
167 lines (143 loc) · 6.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# Builder stage for compiling the Yew application
FROM rust:alpine AS builder
# Install build dependencies
RUN apk update && apk upgrade && \
apk add --no-cache musl-dev libffi-dev zlib-dev jpeg-dev curl
# Install trunk from GitHub releases (musl binary, arch-aware) and wasm target
RUN ARCH=$(uname -m) && \
curl -sSL "https://github.com/trunk-rs/trunk/releases/download/v0.21.14/trunk-${ARCH}-unknown-linux-musl.tar.gz" \
| tar -xz -C /usr/local/bin && \
rustup target add wasm32-unknown-unknown
# Copy Cargo.lock early so we can read the wasm-bindgen version before the full build
COPY ./web/Cargo.lock /app/Cargo.lock
# Pre-populate trunk's wasm-bindgen cache with the musl binary matching Cargo.lock.
# Trunk downloads glibc binaries by default which don't run on Alpine, so we grab
# the musl variant ourselves. Version is read dynamically so it tracks Cargo.lock.
RUN WASM_BINDGEN_VERSION=$(grep -A2 'name = "wasm-bindgen"' /app/Cargo.lock | grep '^version' | head -1 | sed 's/version = "\(.*\)"/\1/') && \
ARCH=$(uname -m) && \
mkdir -p /tmp/wb-dl /root/.cache/trunk/wasm-bindgen-${WASM_BINDGEN_VERSION} && \
curl -sSL "https://github.com/rustwasm/wasm-bindgen/releases/download/${WASM_BINDGEN_VERSION}/wasm-bindgen-${WASM_BINDGEN_VERSION}-${ARCH}-unknown-linux-musl.tar.gz" \
| tar -xz -C /tmp/wb-dl && \
find /tmp/wb-dl -name "wasm-bindgen" ! -name "*test*" -type f \
| xargs -I{} cp {} /root/.cache/trunk/wasm-bindgen-${WASM_BINDGEN_VERSION}/wasm-bindgen && \
chmod +x /root/.cache/trunk/wasm-bindgen-${WASM_BINDGEN_VERSION}/wasm-bindgen && \
rm -rf /tmp/wb-dl
# Add application files to the builder stage
COPY ./web/Cargo.toml ./web/dev-info.md ./web/index.html ./web/tailwind.config.js ./web/Trunk.toml /app/
COPY ./web/src /app/src
COPY ./web/static /app/static
WORKDIR /app
# Build the Yew application in release mode
RUN RUSTFLAGS="--cfg=web_sys_unstable_apis --cfg getrandom_backend=\"wasm_js\"" trunk build --features server_build --release
# Go builder stage for the gpodder API
FROM golang:alpine AS go-builder
WORKDIR /gpodder-api
# Install build dependencies
RUN apk add --no-cache git
# Copy go module files first for better layer caching
COPY ./gpodder-api/go.mod ./gpodder-api/go.sum ./
RUN go mod download
# Copy the rest of the source code
COPY ./gpodder-api/cmd ./cmd
COPY ./gpodder-api/config ./config
COPY ./gpodder-api/internal ./internal
# Build the application
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o gpodder-api ./cmd/server/
# Python builder stage for database setup
FROM python:3.11-alpine AS python-builder
WORKDIR /build
# Install build dependencies for PyInstaller and MariaDB connector
RUN apk add --no-cache gcc musl-dev libffi-dev openssl-dev mariadb-connector-c-dev
# Copy Python source files
COPY ./database_functions ./database_functions
COPY ./startup/setup_database_new.py ./startup/setup_database_new.py
COPY ./requirements.txt ./requirements.txt
# Install Python dependencies including PyInstaller
RUN pip install --no-cache-dir -r requirements.txt pyinstaller
# Build standalone database setup binary
RUN pyinstaller --onefile \
--name pinepods-db-setup \
--hidden-import psycopg \
--hidden-import mysql.connector \
--hidden-import cryptography \
--hidden-import cryptography.fernet \
--hidden-import passlib \
--hidden-import passlib.hash \
--hidden-import passlib.hash.argon2 \
--hidden-import argon2 \
--hidden-import argon2.exceptions \
--hidden-import argon2.profiles \
--hidden-import argon2._password_hasher \
--add-data "database_functions:database_functions" \
--console \
startup/setup_database_new.py
# Rust API builder stage
FROM rust:alpine AS rust-api-builder
WORKDIR /rust-api
# Install build dependencies
RUN apk add --no-cache musl-dev pkgconfig openssl-dev openssl-libs-static
# Copy Rust API files
COPY ./rust-api/Cargo.toml ./rust-api/Cargo.lock ./
COPY ./rust-api/src ./src
# Set environment for static linking
ENV OPENSSL_STATIC=1
ENV OPENSSL_LIB_DIR=/usr/lib
ENV OPENSSL_INCLUDE_DIR=/usr/include
# Build the Rust API
RUN cargo build --release && strip target/release/pinepods-api
# Final stage for setting up runtime environment
FROM alpine
# Metadata
LABEL maintainer="Collin Pendleton <collinp@collinpendleton.com>"
# Install runtime dependencies
RUN apk add --no-cache tzdata nginx openssl bash mariadb-client postgresql-client curl ffmpeg wget jq mariadb-connector-c-dev
# Download and install latest yt-dlp binary (musllinux for Alpine)
RUN LATEST_VERSION=$(curl -s https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest | jq -r .tag_name) && \
wget -O /usr/local/bin/yt-dlp "https://github.com/yt-dlp/yt-dlp/releases/download/${LATEST_VERSION}/yt-dlp_musllinux" && \
chmod +x /usr/local/bin/yt-dlp
# Download and install Horust (x86_64)
RUN wget -O /tmp/horust.tar.gz "https://github.com/FedericoPonzi/Horust/releases/download/v0.1.11/horust-x86_64-unknown-linux-musl.tar.gz" && \
cd /tmp && tar -xzf horust.tar.gz && \
mv horust /usr/local/bin/ && \
chmod +x /usr/local/bin/horust && \
rm -f /tmp/horust.tar.gz
ENV TZ=UTC
# Copy compiled database setup binary (replaces Python dependency)
COPY --from=python-builder /build/dist/pinepods-db-setup /usr/local/bin/
# Copy built files from the builder stage to the Nginx serving directory
COPY --from=builder /app/dist /var/www/html/
# Copy translation files for the Rust API to access
COPY ./web/src/translations /var/www/html/static/translations
# Copy Go API binary from the go-builder stage
COPY --from=go-builder /gpodder-api/gpodder-api /usr/local/bin/
# Copy Rust API binary from the rust-api-builder stage
COPY --from=rust-api-builder /rust-api/target/release/pinepods-api /usr/local/bin/
# Move to the root directory to execute the startup script
WORKDIR /
# Copy startup scripts
COPY startup/startup.sh /startup.sh
RUN chmod +x /startup.sh
# Copy Pinepods runtime files
RUN mkdir -p /pinepods
RUN mkdir -p /var/log/pinepods/ && mkdir -p /etc/horust/services/
COPY startup/ /pinepods/startup/
# Legacy cron scripts removed - background tasks now handled by internal Rust scheduler
COPY clients/ /pinepods/clients/
COPY database_functions/ /pinepods/database_functions/
RUN chmod +x /pinepods/startup/startup.sh
ENV APP_ROOT=/pinepods
# Define the build argument
ARG PINEPODS_VERSION
# Write the Pinepods version to the current_version file
RUN echo "${PINEPODS_VERSION}" > /pinepods/current_version
# Configure Nginx
COPY startup/nginx.conf /etc/nginx/nginx.conf
# Copy script to start gpodder API
COPY ./gpodder-api/start-gpodder.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/start-gpodder.sh
RUN cp /usr/share/zoneinfo/UTC /etc/localtime && \
echo "UTC" > /etc/timezone
# Expose ports
EXPOSE 8080 8000
# Start everything using the startup script
ENTRYPOINT ["bash", "/startup.sh"]