Create Dockerfile
Browse files- Dockerfile +341 -0
Dockerfile
ADDED
@@ -0,0 +1,341 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
ARG ALPINE_BASE_IMAGE=3.19
|
2 |
+
ARG TARGETPLATFORM
|
3 |
+
ARG BUILDPLATFORM
|
4 |
+
|
5 |
+
# Use buildx native support for multi-arch builds
|
6 |
+
FROM alpine:${ALPINE_BASE_IMAGE} AS builder
|
7 |
+
|
8 |
+
ARG VERSION="1.5.5"
|
9 |
+
|
10 |
+
# FreeRDP version (default to version 3)
|
11 |
+
ARG FREERDP_VERSION=2
|
12 |
+
|
13 |
+
ENV \
|
14 |
+
GUAC_VER=${VERSION}
|
15 |
+
|
16 |
+
# Install build dependencies
|
17 |
+
RUN apk add --no-cache \
|
18 |
+
alsa-lib-dev \
|
19 |
+
alsa-tools-dev \
|
20 |
+
autoconf \
|
21 |
+
automake \
|
22 |
+
bsd-compat-headers \
|
23 |
+
build-base \
|
24 |
+
cairo-dev \
|
25 |
+
cmake \
|
26 |
+
cups-dev \
|
27 |
+
faac-dev \
|
28 |
+
faad2-dev \
|
29 |
+
ffmpeg4-dev \
|
30 |
+
fuse3-dev \
|
31 |
+
git \
|
32 |
+
grep \
|
33 |
+
gsm-dev \
|
34 |
+
gst-plugins-base-dev \
|
35 |
+
gstreamer-dev \
|
36 |
+
krb5-dev \
|
37 |
+
libjpeg-turbo-dev \
|
38 |
+
libpng-dev \
|
39 |
+
libtool \
|
40 |
+
libusb-dev \
|
41 |
+
libwebp-dev \
|
42 |
+
libxcursor-dev \
|
43 |
+
libxdamage-dev \
|
44 |
+
libxi-dev \
|
45 |
+
libxinerama-dev \
|
46 |
+
libxkbcommon-dev \
|
47 |
+
libxkbfile-dev \
|
48 |
+
libxv-dev \
|
49 |
+
linux-headers \
|
50 |
+
make \
|
51 |
+
openh264-dev \
|
52 |
+
openssl-dev>3 \
|
53 |
+
pango-dev \
|
54 |
+
pcsc-lite-dev \
|
55 |
+
pulseaudio-dev \
|
56 |
+
samurai \
|
57 |
+
uriparser-dev \
|
58 |
+
util-linux-dev \
|
59 |
+
wayland-dev
|
60 |
+
|
61 |
+
|
62 |
+
# Copy source to container for sake of build
|
63 |
+
ARG BUILD_DIR=/tmp/guacamole-server
|
64 |
+
RUN cd /tmp && \
|
65 |
+
git clone --branch=${GUAC_VER} https://github.com/apache/guacamole-server.git guacamole-server
|
66 |
+
|
67 |
+
#
|
68 |
+
# Base directory for installed build artifacts.
|
69 |
+
#
|
70 |
+
# NOTE: Due to limitations of the Docker image build process, this value is
|
71 |
+
# duplicated in an ARG in the second stage of the build.
|
72 |
+
#
|
73 |
+
ARG PREFIX_DIR=/opt/guacamole
|
74 |
+
|
75 |
+
#
|
76 |
+
# Automatically select the latest versions of each core protocol support
|
77 |
+
# library (these can be overridden at build time if a specific version is
|
78 |
+
# needed)
|
79 |
+
#
|
80 |
+
ARG WITH_FREERDP="${FREERDP_VERSION}(\.\d+)+"
|
81 |
+
ARG WITH_LIBSSH2='libssh2-\d+(\.\d+)+'
|
82 |
+
ARG WITH_LIBTELNET='\d+(\.\d+)+'
|
83 |
+
ARG WITH_LIBVNCCLIENT='LibVNCServer-\d+(\.\d+)+'
|
84 |
+
ARG WITH_LIBWEBSOCKETS='v\d+(\.\d+)+'
|
85 |
+
|
86 |
+
#
|
87 |
+
# Default build options for each core protocol support library, as well as
|
88 |
+
# guacamole-server itself (these can be overridden at build time if different
|
89 |
+
# options are needed)
|
90 |
+
#
|
91 |
+
|
92 |
+
ARG FREERDP_OPTS_COMMON="\
|
93 |
+
-DALLOW_IN_SOURCE_BUILD=ON \
|
94 |
+
-DBUILTIN_CHANNELS=OFF \
|
95 |
+
-DWITH_JPEG=ON \
|
96 |
+
-DWITH_OPENH264=ON \
|
97 |
+
-DWITH_GSM=ON \
|
98 |
+
-DWITH_FAAD2=ON \
|
99 |
+
-DWITH_FAAC=ON \
|
100 |
+
-DWITH_GSSAPI=ON \
|
101 |
+
-DWITH_LIBSYSTEMD=OFF"
|
102 |
+
|
103 |
+
ARG GUACAMOLE_SERVER_OPTS="\
|
104 |
+
--disable-guaclog"
|
105 |
+
|
106 |
+
ARG LIBSSH2_OPTS="\
|
107 |
+
-DBUILD_EXAMPLES=OFF \
|
108 |
+
-DBUILD_SHARED_LIBS=ON"
|
109 |
+
|
110 |
+
ARG LIBTELNET_OPTS="\
|
111 |
+
--disable-static \
|
112 |
+
--disable-util"
|
113 |
+
|
114 |
+
ARG LIBVNCCLIENT_OPTS=""
|
115 |
+
|
116 |
+
ARG LIBWEBSOCKETS_OPTS="\
|
117 |
+
-DDISABLE_WERROR=ON \
|
118 |
+
-DLWS_WITHOUT_SERVER=ON \
|
119 |
+
-DLWS_WITHOUT_TESTAPPS=ON \
|
120 |
+
-DLWS_WITHOUT_TEST_CLIENT=ON \
|
121 |
+
-DLWS_WITHOUT_TEST_PING=ON \
|
122 |
+
-DLWS_WITHOUT_TEST_SERVER=ON \
|
123 |
+
-DLWS_WITHOUT_TEST_SERVER_EXTPOLL=ON \
|
124 |
+
-DLWS_WITH_STATIC=OFF"
|
125 |
+
|
126 |
+
# Build guacamole-server and its core protocol library dependencies
|
127 |
+
RUN case "${TARGETPLATFORM}" in \
|
128 |
+
"linux/amd64") \
|
129 |
+
export FREERDP_OPTS="${FREERDP_OPTS_COMMON} -DWITH_SSE2=ON" \
|
130 |
+
;; \
|
131 |
+
"linux/arm64") \
|
132 |
+
export FREERDP_OPTS="${FREERDP_OPTS_COMMON} -DWITH_SSE2=OFF" \
|
133 |
+
;; \
|
134 |
+
"linux/ppc64le") \
|
135 |
+
export FREERDP_OPTS="${FREERDP_OPTS_COMMON} -DWITH_SSE2=OFF" \
|
136 |
+
;; \
|
137 |
+
*) \
|
138 |
+
export FREERDP_OPTS="${FREERDP_OPTS_COMMON}" \
|
139 |
+
;; \
|
140 |
+
esac && \
|
141 |
+
${BUILD_DIR}/src/guacd-docker/bin/build-all.sh
|
142 |
+
|
143 |
+
# Record the packages of all runtime library dependencies
|
144 |
+
RUN ${BUILD_DIR}/src/guacd-docker/bin/list-dependencies.sh \
|
145 |
+
${PREFIX_DIR}/sbin/guacd \
|
146 |
+
${PREFIX_DIR}/lib/libguac-client-*.so \
|
147 |
+
${PREFIX_DIR}/lib/freerdp2/*guac*.so \
|
148 |
+
> ${PREFIX_DIR}/DEPENDENCIES
|
149 |
+
|
150 |
+
|
151 |
+
# Use same Alpine version as the base for the runtime image
|
152 |
+
FROM alpine:${ALPINE_BASE_IMAGE}
|
153 |
+
|
154 |
+
ARG PREFIX_DIR=/opt/guacamole
|
155 |
+
|
156 |
+
ARG APPLICATION="guacamole"
|
157 |
+
ARG BUILD_RFC3339="2023-04-04T13:00:00Z"
|
158 |
+
ARG REVISION="local"
|
159 |
+
ARG DESCRIPTION="Fully Packaged and Multi-Arch Guacamole container"
|
160 |
+
ARG PACKAGE="flcontainers/guacamole"
|
161 |
+
ARG VERSION="1.5.5"
|
162 |
+
|
163 |
+
LABEL org.opencontainers.image.ref.name="${PACKAGE}" \
|
164 |
+
org.opencontainers.image.created=$BUILD_RFC3339 \
|
165 |
+
org.opencontainers.image.authors="MaxWaldorf" \
|
166 |
+
org.opencontainers.image.documentation="https://github.com/${PACKAGE}/README.md" \
|
167 |
+
org.opencontainers.image.description="${DESCRIPTION}" \
|
168 |
+
org.opencontainers.image.licenses="GPLv3" \
|
169 |
+
org.opencontainers.image.source="https://github.com/${PACKAGE}" \
|
170 |
+
org.opencontainers.image.revision=$REVISION \
|
171 |
+
org.opencontainers.image.version=$VERSION \
|
172 |
+
org.opencontainers.image.url="https://hub.docker.com/r/${PACKAGE}/"
|
173 |
+
|
174 |
+
ENV \
|
175 |
+
GUAC_VER=${VERSION} \
|
176 |
+
GUACAMOLE_HOME=/app/guacamole \
|
177 |
+
CATALINA_HOME=/opt/tomcat \
|
178 |
+
PG_MAJOR=13 \
|
179 |
+
TOMCAT_VER=9.0.105 \
|
180 |
+
PGDATA=/config/postgres \
|
181 |
+
POSTGRES_USER=guacamole \
|
182 |
+
POSTGRES_DB=guacamole_db
|
183 |
+
|
184 |
+
# Runtime environment
|
185 |
+
ENV LC_ALL=C.UTF-8
|
186 |
+
ENV LD_LIBRARY_PATH=${PREFIX_DIR}/lib
|
187 |
+
ENV GUACD_LOG_LEVEL=info
|
188 |
+
ENV TZ=UTC
|
189 |
+
|
190 |
+
# Copy build artifacts into this stage
|
191 |
+
COPY --from=builder ${PREFIX_DIR} ${PREFIX_DIR}
|
192 |
+
|
193 |
+
# Set working DIR
|
194 |
+
RUN mkdir -p /config
|
195 |
+
RUN mkdir -p ${GUACAMOLE_HOME}/extensions ${GUACAMOLE_HOME}/extensions-available ${GUACAMOLE_HOME}/lib
|
196 |
+
RUN mkdir /docker-entrypoint-initdb.d
|
197 |
+
WORKDIR ${GUACAMOLE_HOME}
|
198 |
+
|
199 |
+
# Bring runtime environment up to date and install runtime dependencies
|
200 |
+
RUN apk add --no-cache \
|
201 |
+
bash \
|
202 |
+
bash-completion \
|
203 |
+
ca-certificates \
|
204 |
+
curl \
|
205 |
+
ghostscript \
|
206 |
+
netcat-openbsd \
|
207 |
+
openjdk11-jdk \
|
208 |
+
postgresql${PG_MAJOR} \
|
209 |
+
pwgen \
|
210 |
+
shadow \
|
211 |
+
supervisor \
|
212 |
+
terminus-font \
|
213 |
+
ttf-dejavu \
|
214 |
+
ttf-liberation \
|
215 |
+
tzdata \
|
216 |
+
util-linux-login && \
|
217 |
+
xargs apk add --no-cache < ${PREFIX_DIR}/DEPENDENCIES
|
218 |
+
|
219 |
+
RUN apk add --no-cache -X https://dl-cdn.alpinelinux.org/alpine/edge/community gosu
|
220 |
+
|
221 |
+
# Create a new user guacd
|
222 |
+
ARG UID=1000
|
223 |
+
ARG GID=1000
|
224 |
+
RUN groupadd --gid $GID guacd
|
225 |
+
RUN useradd --system --create-home --shell /sbin/nologin --uid $UID --gid $GID guacd
|
226 |
+
|
227 |
+
RUN chown guacd:guacd -R ${PREFIX_DIR}
|
228 |
+
|
229 |
+
# Install tomcat
|
230 |
+
RUN mkdir ${CATALINA_HOME}
|
231 |
+
ADD https://dlcdn.apache.org/tomcat/tomcat-9/v${TOMCAT_VER}/bin/apache-tomcat-${TOMCAT_VER}.tar.gz /tmp/
|
232 |
+
RUN tar xvzf /tmp/apache-tomcat-${TOMCAT_VER}.tar.gz --strip-components 1 --directory ${CATALINA_HOME}
|
233 |
+
RUN chmod +x ${CATALINA_HOME}/bin/*.sh
|
234 |
+
|
235 |
+
RUN groupadd tomcat && \
|
236 |
+
useradd -s /bin/false -g tomcat -d ${CATALINA_HOME} tomcat
|
237 |
+
|
238 |
+
RUN chgrp -R tomcat ${CATALINA_HOME} && \
|
239 |
+
chmod -R g+r ${CATALINA_HOME}/conf && \
|
240 |
+
chmod g+x ${CATALINA_HOME}/conf && \
|
241 |
+
chown -R tomcat ${CATALINA_HOME}/webapps/ ${CATALINA_HOME}/work/ ${CATALINA_HOME}/temp/ ${CATALINA_HOME}/logs/ && \
|
242 |
+
chmod 777 -R ${CATALINA_HOME}/logs/
|
243 |
+
|
244 |
+
# Install guacamole-client and postgres auth adapter
|
245 |
+
RUN set -x \
|
246 |
+
&& rm -rf ${CATALINA_HOME}/webapps/ROOT \
|
247 |
+
&& curl -SLo ${CATALINA_HOME}/webapps/ROOT.war "http://apache.org/dyn/closer.cgi?action=download&filename=guacamole/${GUAC_VER}/binary/guacamole-${GUAC_VER}.war" \
|
248 |
+
&& curl -SLo ${GUACAMOLE_HOME}/lib/postgresql-42.6.2.jar "https://jdbc.postgresql.org/download/postgresql-42.6.2.jar" \
|
249 |
+
&& curl -SLo ${GUACAMOLE_HOME}/guacamole-auth-jdbc-${GUAC_VER}.tar.gz "http://apache.org/dyn/closer.cgi?action=download&filename=guacamole/${GUAC_VER}/binary/guacamole-auth-jdbc-${GUAC_VER}.tar.gz" \
|
250 |
+
&& tar -xzf ${GUACAMOLE_HOME}/guacamole-auth-jdbc-${GUAC_VER}.tar.gz \
|
251 |
+
&& cp -R ${GUACAMOLE_HOME}/guacamole-auth-jdbc-${GUAC_VER}/postgresql/guacamole-auth-jdbc-postgresql-${GUAC_VER}.jar ${GUACAMOLE_HOME}/extensions/ \
|
252 |
+
&& cp -R ${GUACAMOLE_HOME}/guacamole-auth-jdbc-${GUAC_VER}/postgresql/schema ${GUACAMOLE_HOME}/ \
|
253 |
+
&& rm -rf ${GUACAMOLE_HOME}/guacamole-auth-jdbc-${GUAC_VER} ${GUACAMOLE_HOME}/guacamole-auth-jdbc-${GUAC_VER}.tar.gz
|
254 |
+
|
255 |
+
###############################################################################
|
256 |
+
################################# EXTENSIONS ##################################
|
257 |
+
###############################################################################
|
258 |
+
|
259 |
+
# Download all extensions
|
260 |
+
RUN set -xe \
|
261 |
+
&& for ext_name in auth-duo auth-header auth-jdbc auth-json auth-ldap auth-quickconnect auth-sso auth-totp vault history-recording-storage; do \
|
262 |
+
curl -SLo ${GUACAMOLE_HOME}/guacamole-${ext_name}-${GUAC_VER}.tar.gz "http://apache.org/dyn/closer.cgi?action=download&filename=guacamole/${GUAC_VER}/binary/guacamole-${ext_name}-${GUAC_VER}.tar.gz" \
|
263 |
+
&& tar -xzf ${GUACAMOLE_HOME}/guacamole-${ext_name}-${GUAC_VER}.tar.gz \
|
264 |
+
;done
|
265 |
+
|
266 |
+
# Copy standalone extensions over to extensions-available folder
|
267 |
+
RUN set -xe \
|
268 |
+
&& for ext_name in auth-duo auth-header auth-json auth-ldap auth-quickconnect auth-totp history-recording-storage; do \
|
269 |
+
cp ${GUACAMOLE_HOME}/guacamole-${ext_name}-${GUAC_VER}/guacamole-${ext_name}-${GUAC_VER}.jar ${GUACAMOLE_HOME}/extensions-available/ \
|
270 |
+
;done
|
271 |
+
|
272 |
+
# Copy SSO extensions over to extensions-available folder
|
273 |
+
RUN set -xe \
|
274 |
+
&& for ext_name in openid saml cas; do \
|
275 |
+
cp ${GUACAMOLE_HOME}/guacamole-auth-sso-${GUAC_VER}/${ext_name}/guacamole-auth-sso-${ext_name}-${GUAC_VER}.jar ${GUACAMOLE_HOME}/extensions-available/ \
|
276 |
+
;done
|
277 |
+
|
278 |
+
# Copy JDBC extensions over to extensions-available folder
|
279 |
+
RUN set -xe \
|
280 |
+
&& for ext_name in mysql postgresql sqlserver; do \
|
281 |
+
cp ${GUACAMOLE_HOME}/guacamole-auth-jdbc-${GUAC_VER}/${ext_name}/guacamole-auth-jdbc-${ext_name}-${GUAC_VER}.jar ${GUACAMOLE_HOME}/extensions-available/ \
|
282 |
+
;done
|
283 |
+
|
284 |
+
# Copy vault extensions over to extensions-available folder
|
285 |
+
RUN set -xe \
|
286 |
+
&& for ext_name in ksm; do \
|
287 |
+
cp ${GUACAMOLE_HOME}/guacamole-vault-${GUAC_VER}/${ext_name}/guacamole-vault-${ext_name}-${GUAC_VER}.jar ${GUACAMOLE_HOME}/extensions-available/ \
|
288 |
+
;done
|
289 |
+
|
290 |
+
# Clear all extensions leftovers
|
291 |
+
RUN set -xe \
|
292 |
+
&& for ext_name in auth-duo auth-header auth-jdbc auth-json auth-ldap auth-quickconnect auth-sso auth-totp vault history-recording-storage; do \
|
293 |
+
rm -rf ${GUACAMOLE_HOME}/guacamole-${ext_name}-${GUAC_VER} ${GUACAMOLE_HOME}/guacamole-${ext_name}-${GUAC_VER}.tar.gz \
|
294 |
+
;done
|
295 |
+
|
296 |
+
###############################################################################
|
297 |
+
###############################################################################
|
298 |
+
###############################################################################
|
299 |
+
|
300 |
+
# Finishing Container configuration
|
301 |
+
RUN chown tomcat:tomcat -R ${GUACAMOLE_HOME}
|
302 |
+
|
303 |
+
ENV PATH=/usr/lib/postgresql/${PG_MAJOR}/bin:$PATH
|
304 |
+
ENV GUACAMOLE_HOME=/config/guacamole
|
305 |
+
ENV CATALINA_PID=/tmp/tomcat.pid
|
306 |
+
ENV POSTGRES_PID=/config/postgresql/postmaster.pid
|
307 |
+
ENV GUACD_PID=/tmp/guacd.pid
|
308 |
+
|
309 |
+
# Copy files
|
310 |
+
COPY filefs /
|
311 |
+
RUN chmod +x /usr/local/bin/*.sh
|
312 |
+
RUN chmod +x /startup.sh
|
313 |
+
|
314 |
+
# Copy Scripts
|
315 |
+
COPY scripts/tomcat ${CATALINA_HOME}/bin
|
316 |
+
RUN chown tomcat:tomcat ${CATALINA_HOME}/bin/wrapper_supervisor.sh
|
317 |
+
RUN chmod +x ${CATALINA_HOME}/bin/wrapper_supervisor.sh
|
318 |
+
|
319 |
+
COPY scripts/guacd ${PREFIX_DIR}
|
320 |
+
RUN chown guacd:guacd ${PREFIX_DIR}/wrapper_supervisor.sh
|
321 |
+
RUN chmod +x ${PREFIX_DIR}/wrapper_supervisor.sh
|
322 |
+
|
323 |
+
RUN mkdir -p /scripts/postgres
|
324 |
+
RUN chmod 755 -R /scripts
|
325 |
+
COPY scripts/postgres /scripts/postgres
|
326 |
+
RUN chown postgres:postgres -R /scripts/postgres
|
327 |
+
RUN chmod +x /scripts/postgres/wrapper_supervisor.sh
|
328 |
+
|
329 |
+
# Prepare logs folder for supervisor
|
330 |
+
RUN mkdir -p /var/log/supervisor
|
331 |
+
RUN chmod 755 -R /var/log/supervisor
|
332 |
+
|
333 |
+
# Stop Signal type
|
334 |
+
STOPSIGNAL SIGTERM
|
335 |
+
|
336 |
+
EXPOSE 8080
|
337 |
+
|
338 |
+
WORKDIR /config
|
339 |
+
|
340 |
+
# Set the entrypoint
|
341 |
+
ENTRYPOINT ["/startup.sh"]
|