Skip to content

Commit 63051bf

Browse files
authored
Merge pull request #657 from philomena-dev/prod-images-1-2
backport production image stuff to 1.2
2 parents c259a09 + 2f2799f commit 63051bf

31 files changed

Lines changed: 943 additions & 3 deletions

.dockerignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
assets
21
_build
32
.cargo
43
deps
54
.elixir_ls
6-
priv
5+
priv/static
6+
native/philomena/target
7+
node_modules

.github/workflows/production.yml

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
name: Production Images
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
tags:
8+
- '*'
9+
10+
jobs:
11+
build-and-push-philomena:
12+
name: 'Build and Publish Philomena'
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: read
16+
packages: write
17+
attestations: write
18+
id-token: write
19+
steps:
20+
- name: Set up Docker Buildx
21+
uses: docker/setup-buildx-action@v3
22+
23+
- name: Checkout repository
24+
uses: actions/checkout@v5
25+
26+
- name: Log in to GitHub Container Registry
27+
uses: docker/login-action@v3
28+
with:
29+
registry: ghcr.io
30+
username: ${{ github.actor }}
31+
password: ${{ secrets.GITHUB_TOKEN }}
32+
33+
- name: Extract metadata for Docker
34+
id: meta
35+
uses: docker/metadata-action@v5
36+
with:
37+
images: ghcr.io/philomena-dev/philomena
38+
39+
- name: Build and push Philomena image
40+
uses: docker/build-push-action@v5
41+
with:
42+
context: .
43+
file: ./docker/production/Dockerfile
44+
platforms: 'linux/amd64'
45+
push: true
46+
tags: ${{ steps.meta.outputs.tags }}
47+
labels: ${{ steps.meta.outputs.labels }}
48+
49+
build-and-push-web:
50+
name: 'Build and Publish Web'
51+
runs-on: ubuntu-latest
52+
permissions:
53+
contents: read
54+
packages: write
55+
attestations: write
56+
id-token: write
57+
steps:
58+
- name: Set up Docker Buildx
59+
uses: docker/setup-buildx-action@v3
60+
61+
- name: Checkout repository
62+
uses: actions/checkout@v5
63+
64+
- name: Log in to GitHub Container Registry
65+
uses: docker/login-action@v3
66+
with:
67+
registry: ghcr.io
68+
username: ${{ github.actor }}
69+
password: ${{ secrets.GITHUB_TOKEN }}
70+
71+
- name: Extract metadata for Docker
72+
id: meta
73+
uses: docker/metadata-action@v5
74+
with:
75+
images: ghcr.io/philomena-dev/philomena-web
76+
77+
- name: Build and push Philomena Web Server image
78+
uses: docker/build-push-action@v5
79+
with:
80+
context: .
81+
file: ./docker/production/web/Dockerfile
82+
platforms: 'linux/amd64'
83+
push: true
84+
tags: ${{ steps.meta.outputs.tags }}
85+
labels: ${{ steps.meta.outputs.labels }}
86+
87+
build-and-push-fiberglass:
88+
name: 'Build and Publish Fiberglass Server'
89+
runs-on: ubuntu-latest
90+
permissions:
91+
contents: read
92+
packages: write
93+
attestations: write
94+
id-token: write
95+
steps:
96+
- name: Set up Docker Buildx
97+
uses: docker/setup-buildx-action@v3
98+
99+
- name: Checkout repository
100+
uses: actions/checkout@v5
101+
102+
- name: Log in to GitHub Container Registry
103+
uses: docker/login-action@v3
104+
with:
105+
registry: ghcr.io
106+
username: ${{ github.actor }}
107+
password: ${{ secrets.GITHUB_TOKEN }}
108+
109+
- name: Extract metadata for Docker
110+
id: meta
111+
uses: docker/metadata-action@v5
112+
with:
113+
images: ghcr.io/philomena-dev/fiberglass-server
114+
115+
- name: Build and push Fiberglass Media Processing image
116+
uses: docker/build-push-action@v5
117+
with:
118+
context: .
119+
file: ./docker/production/fiberglass/Dockerfile
120+
platforms: 'linux/amd64'
121+
push: true
122+
tags: ${{ steps.meta.outputs.tags }}
123+
labels: ${{ steps.meta.outputs.labels }}

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ services:
6868
- '5173:5173'
6969

7070
postgres:
71-
image: postgres:17.6-alpine
71+
image: postgres:17.7-alpine
7272
environment:
7373
- POSTGRES_PASSWORD=postgres
7474
volumes:

docker/production/Dockerfile

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# We need to grab "psql" from the Postgres image for database setup
2+
FROM postgres:17.7-alpine AS pg
3+
4+
#
5+
# Step 1: Build Philomena release
6+
#
7+
8+
FROM elixir:1.18.4-alpine AS builder
9+
10+
WORKDIR /tmp/philomena
11+
12+
ENV MIX_ENV=prod
13+
ENV NODE_ENV=production
14+
ENV PATH=$PATH:/root/.cargo/bin
15+
16+
ADD https://api.github.com/repos/philomena-dev/fiberglass-wrapper/git/refs/heads/master /tmp/fiberglass_wrapper_version.json
17+
18+
# Install dependencies and build tools
19+
RUN apk update --allow-untrusted \
20+
&& apk add build-base git npm nodejs wget rust cargo --allow-untrusted \
21+
&& mix local.hex --force \
22+
&& mix local.rebar --force
23+
24+
# Build fiberglass-wrapper from source
25+
RUN git clone --depth 1 https://github.com/philomena-dev/fiberglass-wrapper /tmp/fiberglass_wrapper \
26+
&& cd /tmp/fiberglass_wrapper \
27+
&& cargo build --release
28+
29+
# Copy repo files into the image
30+
COPY . /tmp/philomena
31+
32+
# Install and compile assets
33+
RUN cd /tmp/philomena/assets \
34+
&& NODE_ENV=development npm install \
35+
&& npm run deploy
36+
37+
# Build the application and create symlinks for easier access
38+
RUN cd /tmp/philomena \
39+
&& mix deps.get \
40+
&& mix release --overwrite
41+
42+
# Digest and copy static assets
43+
RUN mix phx.digest -o /tmp/philomena/_build/prod/rel/philomena/lib/philomena-*/priv/static
44+
45+
#
46+
# Step 2: Copy only the final release into a minimal image
47+
# Also copy psql from the Postgres image
48+
#
49+
50+
FROM alpine:3.23
51+
52+
LABEL org.opencontainers.image.authors="liamwhite <liamwhite@users.noreply.github.com>, Nighty <luna@nighty.cloud>, and contributors"
53+
LABEL org.opencontainers.image.description="The official Philomena Docker image intended for production use."
54+
LABEL org.opencontainers.image.source="https://github.com/philomena-dev/philomena"
55+
LABEL org.opencontainers.image.licenses="AGPL-3.0-only"
56+
57+
# Install runtime dependencies
58+
# Required by Erlang/Elixir: libncursesw libstdc++ libgcc
59+
# Required by psql: libedit krb5-libs libldap
60+
RUN apk update \
61+
&& apk add --no-cache libncursesw libstdc++ libgcc libedit krb5-libs libldap
62+
63+
# Set up a non-root user to run the application
64+
RUN addgroup -g 1000 -S philomena \
65+
&& adduser -u 1000 -S philomena -G philomena
66+
67+
# Copy the finished release and the config (because of .json files) from the builder stage...
68+
COPY --from=builder --chown=1000:1000 /tmp/philomena/_build/prod/rel/philomena /srv/philomena
69+
COPY --from=builder --chown=1000:1000 /tmp/philomena/config /srv/philomena/config
70+
71+
# Copy fiberglass-wrapper executable too
72+
COPY --from=builder /tmp/fiberglass_wrapper/target/release/fiberglass-wrapper /usr/local/bin/fiberglass-wrapper
73+
74+
# ...and the production scripts from the repository
75+
COPY --chown=1000:1000 docker/production/purge-cache /usr/local/bin/purge-cache
76+
COPY --chown=1000:1000 docker/production/run-cron /usr/local/bin/run-cron
77+
COPY --chown=1000:1000 docker/production/run-cron-daily /usr/local/bin/run-cron-daily
78+
COPY --chown=1000:1000 docker/production/run-production /usr/local/bin/run-production
79+
COPY --chown=1000:1000 docker/production/setup-production /usr/local/bin/setup-production
80+
COPY --chown=1000:1000 docker/production/programs/* /usr/local/bin/
81+
82+
# Copy postgres client.
83+
COPY --from=pg /usr/local/bin/psql /usr/local/bin/psql
84+
COPY --from=pg /usr/local/bin/pg_isready /usr/local/bin/pg_isready
85+
COPY --from=pg /usr/local/lib/libpq.so /usr/local/lib/libpq.so
86+
COPY --from=pg /usr/local/lib/libpq.so.5 /usr/local/lib/libpq.so.5
87+
COPY --from=pg /usr/local/lib/libpq.so.5.17 /usr/local/lib/libpq.so.5.17
88+
89+
# A "philomena" symlink for easier access
90+
RUN ln -sf /srv/philomena/bin/philomena /usr/local/bin/philomena
91+
92+
USER philomena
93+
94+
# Create the static assets symlink as the philomena user
95+
RUN ln -sf /srv/philomena/lib/philomena-*/priv /srv/philomena/priv
96+
97+
WORKDIR /srv/philomena
98+
99+
EXPOSE 4000-4002
100+
101+
CMD ["/usr/local/bin/run-production"]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
FROM ghcr.io/philomena-dev/fiberglass:2025-12-10
2+
3+
LABEL org.opencontainers.image.authors="liamwhite <liamwhite@users.noreply.github.com>, Nighty <luna@nighty.cloud>, and contributors"
4+
LABEL org.opencontainers.image.description="Legacy Philomena image processing tools, used by Philomena 1.2.x and older. Deprecated in favor of Mediaproc."
5+
LABEL org.opencontainers.image.source="https://github.com/philomena-dev/philomena"
6+
LABEL org.opencontainers.image.licenses="AGPL-3.0-only"
7+
8+
WORKDIR /tmp/fiberglass-server
9+
10+
COPY docker/production/fiberglass/fiberglass-server.ru /tmp/fiberglass-server/fiberglass-server.ru
11+
12+
USER root
13+
14+
RUN apk add ruby ruby-dev build-base rsvg-convert \
15+
&& gem install rack puma rackup base64 \
16+
&& apk del build-base \
17+
&& rm -f /sbin/apk \
18+
&& rm -rf /etc/apk /lib/apk /usr/share/apk /var/lib/apk
19+
20+
USER fiberglass
21+
22+
CMD puma -b tcp://0.0.0.0:8080 -w 8 -t 1:1 /tmp/fiberglass-server/fiberglass-server.ru
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
require 'open3'
2+
require 'base64'
3+
require 'fileutils'
4+
require 'securerandom'
5+
6+
$PERMITTED_COMMANDS = %w[convert ffmpeg ffprobe file gifsicle identify image-intensities jpegtran magick mediastat mediathumb optipng safe-rsvg-convert svgstat]
7+
8+
class Application
9+
def call(env)
10+
req = Rack::Request.new(env)
11+
12+
if req.post?
13+
run(req.body.read)
14+
else
15+
[405, {}, []]
16+
end
17+
end
18+
19+
private
20+
21+
def run(input)
22+
# Container-side script. Can be more lax here.
23+
24+
cwd = "/tmp/#{SecureRandom.uuid}"
25+
FileUtils.mkdir_p(cwd)
26+
FileUtils.cd(cwd)
27+
28+
progname = nil
29+
args = []
30+
files = []
31+
32+
# Parse input
33+
input.each_line.with_index do |line, index|
34+
line.chomp!
35+
36+
if index == 0
37+
progname = Base64.strict_decode64(line)
38+
39+
unless $PERMITTED_COMMANDS.include?(progname.chomp)
40+
return [400, {}, []]
41+
end
42+
43+
next
44+
end
45+
46+
if index == 1
47+
args = line.split(",").map { |a| Base64.strict_decode64(a) }
48+
next
49+
end
50+
51+
name, contents = line.split(":")
52+
files << name
53+
File.write(name, Base64.strict_decode64(contents.to_s))
54+
end
55+
56+
# Run command
57+
stdout, stderr, status = Open3.capture3(progname, *args)
58+
59+
# Generate output
60+
output = []
61+
62+
output.push status.exitstatus.to_s
63+
output.push "\n"
64+
65+
output.push Base64.strict_encode64(stdout)
66+
output.push "\n"
67+
68+
output.push Base64.strict_encode64(stderr)
69+
output.push "\n"
70+
71+
files.each do |file|
72+
output.push Base64.strict_encode64(File.read(file))
73+
output.push "\n"
74+
end
75+
76+
FileUtils.cd("/")
77+
FileUtils.rm_rf(cwd)
78+
79+
[200, {}, output]
80+
end
81+
end
82+
83+
run Application.new

docker/production/programs/convert

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh
2+
safe-wrapper convert "$@"

docker/production/programs/ffmpeg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh
2+
safe-wrapper ffmpeg "$@"

docker/production/programs/ffprobe

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh
2+
safe-wrapper ffprobe "$@"

docker/production/programs/file

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/sh
2+
safe-wrapper file "$@"

0 commit comments

Comments
 (0)