Repository navigation
Expand file tree
/
Copy pathDockerfile
More file actions
117 lines (95 loc) · 4.08 KB
/
Copy pathDockerfile
File metadata and controls
117 lines (95 loc) · 4.08 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
# syntax=docker/dockerfile:1-labs
ARG BUILDER_BASE_IMAGE=ghcr.io/cattr-app/server-runtime
ARG BUILDER_BASE_IMAGE_TAG=builder-latest
ARG RUNTIME_BASE_IMAGE=ghcr.io/cattr-app/server-runtime
ARG RUNTIME_BASE_IMAGE_TAG=runtime-latest
FROM ${BUILDER_BASE_IMAGE}:${BUILDER_BASE_IMAGE_TAG} AS builder
ARG APP_VERSION
ARG APP_ENV=production
ARG REVERB_SCHEME=http
ARG REVERB_PORT=8081
ENV IMAGE_VERSION=6.0.0 \
APP_VERSION=${APP_VERSION} \
APP_ENV=${APP_ENV} \
REVERB_APP_KEY=cattr \
REVERB_HOST=127.0.0.1 \
REVERB_SCHEME=${REVERB_SCHEME} \
REVERB_PORT=${REVERB_PORT}
# builder-latest is itself configured with run-as: 10000. Keep this explicit
# so a future base-image change cannot silently make application build steps root.
USER 10000:10000
WORKDIR /opt/cattr/app
COPY --chown=10000:10000 . /opt/cattr/app
RUN set -eux; \
composer install \
--no-interaction \
--no-dev \
--no-cache \
--no-ansi \
--no-autoloader; \
composer dump-autoload \
--no-interaction \
--optimize \
--apcu \
--classmap-authoritative
RUN set -eux; \
pnpm install --frozen-lockfile; \
pnpm prod; \
rm -rf node_modules
RUN set -eux; \
php artisan storage:link; \
rm -rf build runtime init
FROM ${RUNTIME_BASE_IMAGE}:${RUNTIME_BASE_IMAGE_TAG} AS runtime
ARG APP_VERSION
ARG APP_ENV=production
ARG REVERB_SCHEME=http
ARG REVERB_PORT=8081
# REVERB_APP_SECRET, APP_KEY and DB credentials must be supplied at runtime.
ENV IMAGE_VERSION=6.0.0 \
APP_VERSION=${APP_VERSION} \
APP_ENV=${APP_ENV} \
REVERB_HOST=127.0.0.1 \
REVERB_SCHEME=${REVERB_SCHEME} \
REVERB_PORT=${REVERB_PORT} \
DB_CONNECTION=mysql \
DB_HOST=db \
LOG_CHANNEL=stderr \
PEBBLE=/opt/cattr/.pebble
# REVERB_APP_KEY is a public identifier compiled into the frontend bundle, not
# a secret. Kept as its own instruction so the ignore below covers only it.
# trivy:ignore:DS-0031
ENV REVERB_APP_KEY=cattr
WORKDIR /opt/cattr/app
# Keep application code immutable to the runtime UID. Only Laravel's mutable
# directories are overlaid with UID/GID 10000 ownership below.
COPY --from=builder --chown=0:0 /opt/cattr/app/ /opt/cattr/app/
COPY --from=builder --chown=10000:10000 /opt/cattr/app/bootstrap/cache/ /opt/cattr/app/bootstrap/cache/
COPY --from=builder --chown=10000:10000 /opt/cattr/app/storage/ /opt/cattr/app/storage/
# The runtime base image uses UID 10000 by default, so chown must run as root.
# Recursively fix both directory and file ownership for Laravel's writable paths.
USER 0:0
RUN chown -R 10000:10000 /opt/cattr/app/bootstrap/cache /opt/cattr/app/storage
USER 10000:10000
# Cattr-specific configuration lives under /opt/cattr/etc. Program-specific
# system configuration remains in the conventional /etc/php and /etc/caddy.
COPY --chown=0:0 --chmod=0644 runtime/supercronic/crontab /opt/cattr/crontab
COPY --chown=0:0 --chmod=0644 runtime/php/conf.d/99-cattr.ini /etc/php/conf.d/99-cattr.ini
COPY --chown=0:0 --chmod=0644 runtime/caddy/Caddyfile /etc/caddy/Caddyfile
RUN caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
# Pebble needs a writable per-user state directory; the base image creates it
# as UID/GID 10000. The layer itself is application data copied at image build.
COPY --chown=10000:10000 --chmod=0644 init/pebble/001-cattr.yaml /opt/cattr/.pebble/layers/001-cattr.yaml
# Optional restart-policy layer; the entrypoint installs it into the layers
# directory when CATTR_RESTART_POLICY=shutdown (default for split roles).
COPY --chown=0:0 --chmod=0644 init/pebble/002-shutdown-policy.yaml /opt/cattr/etc/pebble/002-shutdown-policy.yaml
COPY --chown=0:0 --chmod=0755 init/container-entrypoint.sh /opt/cattr/entrypoint
# Hard guarantee for the final image: PID 1 and every supervised process start
# as the unprivileged Cattr user. No runtime privilege drop is required.
USER 10000:10000
VOLUME ["/opt/cattr/app/storage"]
# 8080 Caddy, 8081 Reverb, 8090 Octane. The latter two matter when a role is
# deployed without Caddy in front of it.
EXPOSE 8080 8081 8090
STOPSIGNAL SIGTERM
ENTRYPOINT ["/opt/cattr/entrypoint"]
CMD ["all"]