-
Notifications
You must be signed in to change notification settings - Fork 150
Expand file tree
/
Copy pathDockerfile
More file actions
328 lines (200 loc) · 10.2 KB
/
Copy pathDockerfile
File metadata and controls
328 lines (200 loc) · 10.2 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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
FROM maven:3.9-eclipse-temurin-21 AS maven
# download and extract Jena
ARG JENA_VERSION=6.1.0
ARG JENA_TAR_URL="https://archive.apache.org/dist/jena/binaries/apache-jena-${JENA_VERSION}.tar.gz"
RUN mkdir /jena && \
curl -SL "$JENA_TAR_URL" | \
tar -xzf - -C /jena
# copy platform source code and POM
WORKDIR /usr/src/platform
COPY src /usr/src/platform/src
COPY pom.xml /usr/src/platform/pom.xml
RUN mvn -Pstandalone clean install
# ==============================
# SEF compiler: composes each dataspace's client stylesheet with its imported package
# stylesheets and compiles the result to a SEF.
#
# Out-of-process because the compile peaks around 1.5 GB resident - measured 1,495,990,272
# bytes for client.xsl - which is fatal beside a Tomcat heap sized at 75% of a 2 GB limit.
#
# The static tree comes from the same Maven stage the WAR does, so the modules compiled here
# are the deployed bytes by construction: no mount, no shared volume, and no way for the
# compiler to drift from the application it compiles for.
FROM node:22-alpine AS sef-compiler
# must match the SaxonJS runtime shipped in the webapp (js/saxon-js/SaxonJS3.js). A skew
# between compiler and runtime surfaces as "Cannot read properties of undefined (reading
# 'principalResult')" with the compile succeeding and only the export failing
ARG XSLT3_VERSION=3.0.0-beta2
RUN npm install -g "xslt3-he@${XSLT3_VERSION}"
COPY --from=maven /usr/src/platform/target/ROOT/static /static
COPY platform/sef-compiler/server.js /opt/sef-compiler/server.js
ENV XSL_DIR=/static/com/atomgraph/linkeddatahub/xsl
ENV PORT=8080
# the service writes the generated wrapper and the package modules beside client.xsl, then
# removes them again, so the stylesheet directory has to be writable by the runtime user
RUN chown -R node:node /static
USER node
EXPOSE 8080
HEALTHCHECK --start-period=10s --retries=3 \
CMD wget -q -O- http://localhost:8080/health || exit 1
CMD [ "node", "/opt/sef-compiler/server.js" ]
# ==============================
FROM atomgraph/letsencrypt-tomcat:10.1.52
LABEL maintainer="martynas@atomgraph.com"
# hash of the current commit
ARG SOURCE_COMMIT=
ARG UPLOAD_ROOT=/var/www/linkeddatahub/uploads
ARG UPLOAD_CONTAINER_PATH=uploads
# composed client stylesheets are served from here through a Tomcat alias, not from the WAR,
# so they survive redeploys and stay outside the packaged application
ARG SEF_ROOT=/var/www/linkeddatahub/sef
# the compiler runs as its own service: the compile peaks near 1.5 GB and must not share this
# container's memory limit with Tomcat
ARG SEF_COMPILER=http://sef-compiler:8080/compile
# webapp path of the client stylesheet the page bootstraps, which the package SEF is composed from: a
# deployment that mounts its own client stylesheet importing the platform's points this at it, so its
# rules and the packages' reach the browser together
ARG CLIENT_STYLESHEET=/static/com/atomgraph/linkeddatahub/xsl/client.xsl
# one generated sitemap and robots.txt per dataspace, kept outside the WAR for the same reason and
# mounted under /static/sitemaps, where WEB-INF/rewrite.config sends the requests for them
ARG SITEMAP_ROOT=/var/www/linkeddatahub/sitemaps
# an imported package's stylesheet is copied here and served from the application's own origin, so it
# resolves like every other stylesheet the platform compiles: an absolute URL under /static/ that never
# leaves the container. Outside the WAR for the same reason as the others - a copy taken at import
# outlives a redeploy, and nothing an application imports is baked into the packaged application
ARG PACKAGE_ROOT=/var/www/linkeddatahub/packages
# settings a dataspace's owner changes at runtime - installing a package, for one. The context dataset
# cannot hold them: entrypoint.sh regenerates it from config/*.trig on every boot, so a write into it
# is discarded at the next start. Kept here, outside the deployed application and on a volume, and
# applied over the context dataset as it loads
ARG SETTINGS_ROOT=/var/www/linkeddatahub/settings
ENV SOURCE_COMMIT=$SOURCE_COMMIT
WORKDIR $CATALINA_HOME
ENV STYLESHEET=static/com/atomgraph/linkeddatahub/xsl/layout.xsl
ENV CACHE_STYLESHEET=true
ENV UPLOAD_ROOT=$UPLOAD_ROOT
ENV SEF_ROOT=$SEF_ROOT
ENV SEF_COMPILER=$SEF_COMPILER
ENV CLIENT_STYLESHEET=$CLIENT_STYLESHEET
ENV SITEMAP_ROOT=$SITEMAP_ROOT
ENV PACKAGE_ROOT=$PACKAGE_ROOT
ENV SETTINGS_ROOT=$SETTINGS_ROOT
ENV PROXY_HOST=
ENV PROXY_HTTP_PORT=
ENV PROXY_HTTPS_PORT=
ENV TIMEOUT=20
ENV PROTOCOL=https
ENV HOST=localhost
ENV HTTP_REDIRECT_PORT=443
ENV HTTP_COMPRESSION=on
ENV HTTPS=false
ENV SERVER_CERT=/var/linkeddatahub/ssl/server/server.crt
ENV OWNER_CERT_ALIAS=root-owner
ENV OWNER_KEYSTORE=/var/linkeddatahub/ssl/owner/keystore.p12
ENV OWNER_CERT=/var/linkeddatahub/ssl/owner/cert.pem
ENV OWNER_PUBLIC_KEY=/var/linkeddatahub/ssl/owner/public.pem
ENV SECRETARY_COMMON_NAME=LinkedDataHub
ENV SECRETARY_CERT_ALIAS=root-secretary
ENV SECRETARY_KEYSTORE=/var/linkeddatahub/ssl/secretary/keystore.p12
ENV SECRETARY_CERT=/var/linkeddatahub/ssl/secretary/cert.pem
ENV SECRETARY_PUBLIC_KEY=/var/linkeddatahub/ssl/secretary/public.pem
ENV CLIENT_KEYSTORE_MOUNT=/var/linkeddatahub/ssl/secretary/keystore.p12
ENV CLIENT_KEYSTORE="$CATALINA_HOME/webapps/ROOT/WEB-INF/keystore.p12"
ENV CLIENT_TRUSTSTORE="$CATALINA_HOME/webapps/ROOT/WEB-INF/client.truststore"
ENV CERT_VALIDITY=3650
ENV SIGN_UP_CERT_VALIDITY=
ENV LOAD_DATASETS=
ENV CONTEXT_DATASET_URL=file:///var/linkeddatahub/datasets/dataspaces.trig
ENV SERVICES_DATASET_URL=file:///var/linkeddatahub/datasets/system.trig
ENV ADMIN_DATASET_URL=file:///var/linkeddatahub/datasets/admin.trig
ENV END_USER_DATASET_URL=file:///var/linkeddatahub/datasets/end-user.trig
ENV UPLOAD_CONTAINER_PATH=$UPLOAD_CONTAINER_PATH
ENV OIDC_REFRESH_TOKENS=/var/linkeddatahub/oidc/refresh_tokens.properties
ENV MAX_CONTENT_LENGTH=2097152
# sized to the connector's 200 threads: a request thread that calls back into this instance holds one pooled
# connection while it waits for another thread to answer, so a pool smaller than the connector queues
# those calls behind each other, one bounded wait at a time, and a burst of renders drains one slot at a time
ENV MAX_CONN_PER_ROUTE=200
ENV MAX_TOTAL_CONN=400
ENV MAX_REQUEST_RETRIES=3
ENV CONNECTION_REQUEST_TIMEOUT=30000
ENV CLIENT_SOCKET_TIMEOUT=120000
ENV CLIENT_CONNECT_TIMEOUT=10000
# for requests to this instance's own URLs, answered by its own request threads: a label lookup takes milliseconds
# through the proxy, and this is also the longest a burst of renders can hold every thread waiting on each other
# (a render makes up to three in sequence)
ENV CLIENT_SELF_REQUEST_TIMEOUT=5000
ENV CLIENT_CONNECTION_TIME_TO_LIVE=300000
ENV CLIENT_VALIDATE_AFTER_INACTIVITY=10000
ENV WEBID_CACHE_EXPIRATION=86400
ENV JWKS_CACHE_EXPIRATION=86400
ENV IMPORT_KEEPALIVE=
ENV MAX_IMPORT_THREADS=10
ENV SERVLET_NAME=
ENV GENERATE_SITEMAP=true
# remove default Tomcat webapps and install xmlstarlet (used for XPath queries) and envsubst (for variable substitution)
RUN apt-get update --allow-releaseinfo-change && \
apt-get install -y acl && \
apt-get install -y xmlstarlet && \
apt-get install -y gettext-base && \
apt-get install -y uuid-runtime && \
rm -rf webapps/* && \
rm -rf /var/lib/apt/lists/*
# add XSLT stylesheet that makes changes to ROOT.xml
COPY platform/context.xsl /var/linkeddatahub/xsl/context.xsl
# add XSLT stylesheet that makes changes to web.xml
COPY platform/web.xsl /var/linkeddatahub/xsl/web.xsl
# add XSLT stylesheet that makes changes to server.xml, after letsencrypt-tomcat.xsl has generated it
COPY platform/server.xsl /var/linkeddatahub/xsl/server.xsl
# copy entrypoint
COPY platform/entrypoint.sh entrypoint.sh
# copy certificate import script
COPY platform/import-letsencrypt-stg-roots.sh import-letsencrypt-stg-roots.sh
# copy SPARQL query used to get metadata of the root app service from the system dataset
COPY platform/select-root-services.rq select-root-services.rq
COPY platform/select-agent-metadata.rq select-agent-metadata.rq
# copy the metadata of built-in agents
COPY platform/root-secretary.trig.template root-secretary.trig.template
COPY platform/root-owner.trig.template root-owner.trig.template
COPY platform/root-secretary-authorization.trig.template root-secretary-authorization.trig.template
COPY platform/root-owner-authorization.trig.template root-owner-authorization.trig.template
# copy the metadata of the namespace ontology
COPY platform/namespace-ontology.trig.template namespace-ontology.trig.template
# copy default datasets
COPY platform/datasets/admin.trig /var/linkeddatahub/datasets/admin.trig
COPY platform/datasets/end-user.trig /var/linkeddatahub/datasets/end-user.trig
# copy sitemap queries & stylesheet
COPY platform/sitemap/public-rules.rq /var/linkeddatahub/sitemap/public-rules.rq
COPY platform/sitemap/sitemap.rq.template /var/linkeddatahub/sitemap/sitemap.rq.template
COPY platform/sitemap/sitemap.xsl /var/linkeddatahub/sitemap/sitemap.xsl
# copy webapp config
COPY platform/conf/ROOT.xml conf/Catalina/localhost/ROOT.xml
# copy platform webapp (exploded) from the maven stage of the build
COPY --from=maven /usr/src/platform/target/ROOT webapps/ROOT/
# copy extracted Jena from the maven stage of the build
COPY --from=maven /jena/* /jena
# setup Jena
ENV JENA_HOME=/jena
ENV PATH="${PATH}:${JENA_HOME}/bin"
# add non-root user "ldh" and give it access to $CATALINA_HOME
RUN useradd --no-log-init -U ldh && \
chown -R ldh:ldh . && \
mkdir -p "$(dirname "$OIDC_REFRESH_TOKENS")" && \
chown -R ldh:ldh /var/linkeddatahub && \
mkdir -p "${UPLOAD_ROOT}/${UPLOAD_CONTAINER_PATH}" && \
chown -R ldh:ldh "$UPLOAD_ROOT" && \
mkdir -p "$SEF_ROOT" && \
chown -R ldh:ldh "$SEF_ROOT" && \
mkdir -p "$SITEMAP_ROOT" && \
chown -R ldh:ldh "$SITEMAP_ROOT" && \
mkdir -p "$PACKAGE_ROOT" && \
chown -R ldh:ldh "$PACKAGE_ROOT" && \
mkdir -p "$SETTINGS_ROOT" && \
chown -R ldh:ldh "$SETTINGS_ROOT" && \
mkdir -p /etc/letsencrypt/staging && \
chown -R ldh:ldh /etc/letsencrypt/staging
RUN ./import-letsencrypt-stg-roots.sh
HEALTHCHECK --start-period=80s --retries=5 \
CMD curl -f -I "http://localhost:7070/ns" -H "Accept: application/n-triples" || exit 1 # relies on public access to the namespace document
USER ldh
ENTRYPOINT ["/bin/bash", "entrypoint.sh"]