-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathDockerfile
More file actions
204 lines (166 loc) · 6.39 KB
/
Dockerfile
File metadata and controls
204 lines (166 loc) · 6.39 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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# syntax=docker/dockerfile:1.4
# ============================================
# Flutter Build Stage
# ============================================
FROM ghcr.io/cirruslabs/flutter:3.38.6 AS flutter-builder
WORKDIR /app/player
# Copy player source
COPY player/pubspec.yaml player/pubspec.lock ./
COPY player/build.yaml ./
COPY player/lib ./lib
COPY player/web ./web
COPY player/rust_builder ./rust_builder
# Copy the GraphQL schema (resolves symlink from priv/graphql/)
COPY priv/graphql/schema.graphql ./lib/graphql/schema.graphql
# Install dependencies, generate code, and build
# Cache pub packages to avoid re-downloading 1656 dependencies each build
RUN --mount=type=cache,target=/root/.pub-cache,sharing=locked \
flutter config --no-analytics && \
flutter pub get && \
dart run build_runner build --delete-conflicting-outputs && \
flutter build web --release --base-href /player/ --tree-shake-icons
# ============================================
# Elixir Build Stage
# ============================================
FROM elixir:1.19-alpine AS builder
# Install build dependencies
RUN apk add --no-cache \
build-base \
git \
nodejs \
npm \
sqlite-dev \
postgresql16-dev \
rust \
cargo \
curl \
ca-certificates
# Increase hex timeout for slow networks/CI
ENV HEX_HTTP_TIMEOUT=300000
# Install Hex and Rebar
RUN mix local.hex --force && mix local.rebar --force
# Database type: sqlite (default) or postgres
# This is a BUILD-TIME argument that determines which database adapter is compiled into the release
# It CANNOT be changed at runtime - each Docker image is built for a specific database
ARG DATABASE_TYPE=sqlite
# Build commit hash for development/master builds
# When set, the version will display as "X.Y.Z*<short-commit>" instead of just "X.Y.Z"
ARG BUILD_COMMIT=""
# Set build environment
ENV MIX_ENV=prod
ENV DATABASE_TYPE=${DATABASE_TYPE}
ENV BUILD_COMMIT=${BUILD_COMMIT}
# Create app directory
WORKDIR /app
# Copy dependency manifests
COPY mix.exs mix.lock ./
# Install dependencies
# Cache hex packages to avoid re-downloading each build
RUN --mount=type=cache,target=/root/.hex,sharing=locked \
mix deps.get --only prod
# Apply patches to dependencies
# Fix ueberauth_oidcc to respect user-provided response_mode option
# This prevents auto-selection of JARM modes (query.jwt) which some OIDC providers
# advertise but don't properly support
COPY patches/ueberauth_oidcc_request.ex ./deps/ueberauth_oidcc/lib/ueberauth_oidcc/request.ex
# Compile dependencies
# Cache cargo registry for Rust NIF compilation (mydia_p2p_core)
RUN --mount=type=cache,target=/root/.cargo/registry,sharing=locked \
--mount=type=cache,target=/root/.cargo/git,sharing=locked \
--mount=type=cache,target=/app/native/mydia_p2p_core/target,sharing=locked \
mix deps.compile
# Copy application source
COPY config ./config
COPY priv ./priv
COPY lib ./lib
COPY assets ./assets
COPY native ./native
# Copy Flutter build output from flutter-builder stage
COPY --from=flutter-builder /app/player/build/web ./priv/static/player
# Application version: set by CI from the git tag, defaults to "dev" for local builds
ARG BUILD_VERSION=""
ENV BUILD_VERSION=${BUILD_VERSION}
# Compile application (includes building Rust NIFs via Rustler)
# Cache cargo for Rust NIF compilation
RUN --mount=type=cache,target=/root/.cargo/registry,sharing=locked \
--mount=type=cache,target=/root/.cargo/git,sharing=locked \
--mount=type=cache,target=/app/native/mydia_p2p_core/target,sharing=locked \
mix compile
# Build Phoenix assets
# Cache npm packages to avoid re-downloading each build
RUN --mount=type=cache,target=/root/.npm,sharing=locked \
cd assets && \
npm ci --prefix . --progress=false --no-audit --loglevel=error && \
cd .. && \
mix assets.deploy
# Build release
RUN mix release
# ============================================
# Runtime Stage
# ============================================
FROM erlang:28-alpine
# Database type: sqlite (default) or postgres
# This argument is only used for image labels - the actual adapter is already compiled
ARG DATABASE_TYPE=sqlite
# Add OCI labels following LinuxServer.io standards
LABEL org.opencontainers.image.title="Mydia" \
org.opencontainers.image.description="Modern, self-hosted media management platform" \
org.opencontainers.image.url="https://github.com/getmydia/mydia" \
org.opencontainers.image.source="https://github.com/getmydia/mydia" \
org.opencontainers.image.vendor="Mydia" \
org.opencontainers.image.licenses="AGPL-3.0-or-later" \
org.opencontainers.image.database="${DATABASE_TYPE}" \
maintainer="Mydia"
# Install runtime dependencies including LSIO-compatible tools
# libpq is needed for PostgreSQL connections at runtime
# sqlite provides the sqlite3 CLI for database inspection
# openssl is needed for self-signed certificate generation
RUN apk add --no-cache \
sqlite \
libpq \
curl \
ca-certificates \
ffmpeg \
fdk-aac \
su-exec \
tzdata \
shadow \
openssl
# Create app user with default UID/GID (will be updated by entrypoint if needed)
RUN addgroup -g 1000 mydia && \
adduser -D -u 1000 -G mydia mydia
# Create necessary directories with proper permissions
RUN mkdir -p /app /config /data /media && \
chown -R mydia:mydia /app /config /data /media
# Set working directory
WORKDIR /app
# Copy release from builder
COPY --from=builder --chown=mydia:mydia /app/_build/prod/rel/mydia ./
# Copy entrypoint script
COPY docker-entrypoint-prod.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
# Copy CLI wrapper script
COPY scripts/mydia-cli.sh /usr/local/bin/mydia-cli
RUN chmod +x /usr/local/bin/mydia-cli
# Set environment variables
# Note: DATABASE_TYPE is NOT set here - it's a build-time argument only
# The database adapter is compiled into the release and cannot be changed at runtime
ENV HOME=/app \
MIX_ENV=prod \
PHX_SERVER=true \
DATABASE_PATH=/config/mydia.db \
P2P_KEYPAIR_PATH=/config/p2p_keypair.bin \
PORT=4000 \
PUID=1000 \
PGID=1000 \
TZ=UTC
# Expose HTTP and HTTPS ports
EXPOSE 4000 4443
# Declare volumes following LSIO conventions
VOLUME ["/config", "/data", "/media"]
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
CMD curl -f http://localhost:4000/health || exit 1
# Set entrypoint and default command
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/app/bin/mydia", "start"]