-
Notifications
You must be signed in to change notification settings - Fork 144
/
Dockerfile.elastic-agent.tmpl
305 lines (269 loc) · 12.5 KB
/
Dockerfile.elastic-agent.tmpl
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
{{- $beatHome := printf "%s/%s" "/usr/share" .BeatName }}
{{- $beatBinary := printf "%s/%s" $beatHome .BeatName }}
{{- $repoInfo := repo }}
# Prepare home in a different stage to avoid creating additional layers on
# the final image because of permission changes.
FROM {{ .buildFrom }} AS home
{{- if contains .buildFrom "wolfi" }}
RUN for iter in {1..10}; do \
apk update && \
apk add --no-cache shadow libcap-utils && \
exit_code=0 && break || exit_code=$? && echo "apk error: retry $iter in 10s" && sleep 10; \
done; \
(exit $exit_code)
{{- end }}
COPY beat {{ $beatHome }}
RUN true && \
# ECE needs to create config here under non-1000 user
chmod 0777 {{ $beatHome}} && \
mkdir -p {{ $beatHome }}/data {{ $beatHome }}/data/elastic-agent-{{ commit_short }}/logs && \
find {{ $beatHome }} -type d -exec chmod 0755 {} \; && \
find {{ $beatHome }} -type f -exec chmod 0644 {} \; && \
find {{ $beatHome }}/data -type d -exec chmod 0777 {} \; && \
find {{ $beatHome }}/data -type f -exec chmod 0666 {} \; && \
rm {{ $beatBinary }} && \
ln -s {{ $beatHome }}/data/elastic-agent-{{ commit_short }}/elastic-agent {{ $beatBinary }} && \
chmod 0755 {{ $beatHome }}/data/elastic-agent-*/elastic-agent && \
chmod 0755 {{ $beatHome }}/data/elastic-agent-*/components/*beat && \
(chmod 0755 {{ $beatHome }}/data/elastic-agent-*/components/osquery* || true) && \
(chmod 0755 {{ $beatHome }}/data/elastic-agent-*/components/apm-server || true) && \
(chmod 0755 {{ $beatHome }}/data/elastic-agent-*/components/endpoint-security || true) && \
(chmod 0755 {{ $beatHome }}/data/elastic-agent-*/components/fleet-server || true) && \
(chmod 0755 {{ $beatHome }}/data/elastic-agent-*/components/pf-elastic-collector || true) && \
(chmod 0755 {{ $beatHome }}/data/elastic-agent-*/components/pf-elastic-symbolizer || true) && \
(chmod 0755 {{ $beatHome }}/data/elastic-agent-*/components/pf-host-agent || true) && \
find {{ $beatHome }}/data/elastic-agent-{{ commit_short }}/components -name "*.yml*" -type f -exec chmod 0644 {} \; && \
{{- range $i, $modulesd := .ModulesDirs }}
chmod 0775 {{ $beatHome}}/{{ $modulesd }} && \
{{- end }}
{{- if eq .Variant "cloud" }}
mkdir -p /opt/agentbeat /opt/filebeat /opt/metricbeat && \
cp -f {{ $beatHome }}/data/cloud_downloads/filebeat.sh /opt/filebeat/filebeat && \
chmod +x /opt/filebeat/filebeat && \
cp -f {{ $beatHome }}/data/cloud_downloads/metricbeat.sh /opt/metricbeat/metricbeat && \
chmod +x /opt/metricbeat/metricbeat && \
tar xf {{ $beatHome }}/data/cloud_downloads/agentbeat-*.tar.gz -C /opt/agentbeat --strip-components=1 && \
rm -rf {{ $beatHome }}/data/cloud_downloads && \
{{- end }}
true
# Keep this after any chown command, chown resets any applied capabilities
RUN setcap =p {{ $beatHome }}/data/elastic-agent-{{ commit_short }}/elastic-agent && \
{{- if .linux_capabilities }}
# Since the beat is stored at the other end of a symlink we must follow the symlink first
# For security reasons setcap does not support symlinks. This is smart in the general case
# but in our specific case since we're building a trusted image from trusted binaries this is
# fine. Thus, we use readlink to follow the link and setcap on the actual binary
setcap {{ .linux_capabilities }} $(readlink -f {{ $beatBinary }}) && \
{{- end }}
true
FROM {{ .from }}
ENV BEAT_SETUID_AS={{ .user }}
{{- if contains .from "ubi-minimal" }}
RUN for iter in {1..10}; do microdnf update -y && microdnf install -y tar gzip findutils shadow-utils && microdnf clean all && exit_code=0 && break || exit_code=$? && echo "microdnf error: retry $iter in 10s" && sleep 10; done; (exit $exit_code)
{{- end }}
{{- if contains .from "ubuntu" }}
# Delete the existing "ubuntu" user to prevent conflict with the user that is added later.
# See https://bugs.launchpad.net/cloud-images/+bug/2005129/comments/2.
RUN touch /var/mail/ubuntu && chown ubuntu /var/mail/ubuntu && userdel -r ubuntu
RUN for iter in {1..10}; do \
apt-get update -y && \
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes ca-certificates curl gawk xz-utils && \
apt-get clean all && \
exit_code=0 && break || exit_code=$? && echo "apt-get error: retry $iter in 10s" && sleep 10; \
done; \
(exit $exit_code)
{{- end }}
{{- if contains .from "wolfi" }}
RUN for iter in {1..10}; do \
apk update && \
apk add --no-cache ca-certificates curl gawk shadow bash && \
exit_code=0 && break || exit_code=$? && echo "apk error: retry $iter in 10s" && sleep 10; \
done; \
(exit $exit_code)
{{- end }}
LABEL \
org.label-schema.build-date="{{ date }}" \
org.label-schema.schema-version="1.0" \
org.label-schema.vendor="{{ .BeatVendor }}" \
org.label-schema.license="{{ .License }}" \
org.label-schema.name="{{ .BeatName }}" \
org.label-schema.version="{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}" \
org.label-schema.url="{{ .BeatURL }}" \
org.label-schema.vcs-url="{{ $repoInfo.RootImportPath }}" \
org.label-schema.vcs-ref="{{ commit }}" \
io.k8s.description="{{ .BeatDescription }}" \
io.k8s.display-name="{{ .BeatName | title }} image" \
org.opencontainers.image.created="{{ date }}" \
org.opencontainers.image.licenses="{{ .License }}" \
org.opencontainers.image.title="{{ .BeatName | title }}" \
org.opencontainers.image.vendor="{{ .BeatVendor }}" \
org.opencontainers.image.authors="infra@elastic.co" \
name="{{ .BeatName }}" \
vendor="{{ .BeatVendor }}" \
version="{{ beat_version }}{{if .Snapshot}}-SNAPSHOT{{end}}" \
release="1" \
url="{{ .BeatURL }}" \
summary="{{ .BeatName }}" \
license="{{ .License }}" \
description="{{ .BeatDescription }}"
ENV ELASTIC_CONTAINER="true"
ENV PATH={{ $beatHome }}:$PATH
ENV GODEBUG="madvdontneed=1"
# Add an init process, check the checksum to make sure it's a match
RUN set -e ; \
TINI_BIN=""; \
TINI_SHA256=""; \
TINI_VERSION="v0.19.0"; \
case "$(arch)" in \
x86_64) \
TINI_BIN="tini-amd64"; \
TINI_SHA256="93dcc18adc78c65a028a84799ecf8ad40c936fdfc5f2a57b1acda5a8117fa82c"; \
;; \
aarch64) \
TINI_BIN="tini-arm64"; \
TINI_SHA256="07952557df20bfd2a95f9bef198b445e006171969499a1d361bd9e6f8e5e0e81"; \
;; \
*) \
echo >&2 ; echo >&2 "Unsupported architecture \$(arch)" ; echo >&2 ; exit 1 ; \
;; \
esac ; \
curl --retry 8 -S -L -O "https://github.com/krallin/tini/releases/download/${TINI_VERSION}/${TINI_BIN}" ; \
echo "${TINI_SHA256} ${TINI_BIN}" | sha256sum -c - ; \
mv "${TINI_BIN}" /usr/bin/tini ; \
chmod +x /usr/bin/tini
COPY docker-entrypoint /usr/local/bin/docker-entrypoint
# We do not want to add the agent user to the root group and because of backwards compatibility we can do it only for the new Wolfi image
RUN groupadd --gid 1000 {{ .BeatName }} && \
{{- if contains .from "wolfi" }}
useradd -M --uid 1000 --gid 1000 {{ .user }} && \
{{- else }}
useradd -M --uid 1000 --gid 1000 --groups 0 {{ .user }} && \
{{- end }}
chmod 755 /usr/local/bin/docker-entrypoint && \
true
COPY --chown={{ .user }}:{{ .user }} --from=home {{ $beatHome }} {{ $beatHome }}
# Elastic Agent needs group permissions in the home itself to be able to
# create fleet.yml when running as non-root.
RUN chmod 0777 {{ $beatHome }} && \
usermod -d {{ $beatHome}} {{ .user }} && \
find {{ $beatHome }}/data/elastic-agent-{{ commit_short }}/components -name "*.yml*" -type f -exec chown {{ .user }}:{{ .user }} {} \; && \
true
RUN mkdir /licenses
COPY --from=home {{ $beatHome }}/LICENSE.txt /licenses
COPY --from=home {{ $beatHome }}/NOTICE.txt /licenses
{{- if eq .Variant "cloud" }}
COPY --from=home /opt /opt
# Generate folder for a stub command that will be overwritten at runtime
RUN mkdir /app && \
chown {{ .user }}:{{ .user }} /app
{{- end }}
{{- if eq .Variant "service" }}
RUN apk add --no-cache git make python-3.11 py3.11-pip && \
unzip {{ $beatHome }}/data/service/connectors-*.zip -d {{ $beatHome }}/data/service && \
mv {{ $beatHome }}/data/service/elasticsearch_connectors-* /usr/share/connectors && \
PYTHON=python3.11 make -C /usr/share/connectors clean install install-agent && \
chmod 0755 {{ $beatHome }}/data/elastic-agent-*/components/connectors
{{- end }}
{{- if (and (eq .Variant "complete") (contains .from "ubuntu")) }}
USER root
ENV NODE_PATH={{ $beatHome }}/.node
RUN echo \
$NODE_PATH \
{{ $beatHome }}/.config \
{{ $beatHome }}/.synthetics \
{{ $beatHome }}/.npm \
{{ $beatHome }}/.cache \
| xargs -IDIR sh -c 'mkdir -p DIR && chmod 0775 DIR'
# Setup synthetics env vars
ENV ELASTIC_SYNTHETICS_CAPABLE=true
ENV ELASTIC_AGENT_COMPLETE=true
ENV TZ=UTC
ENV NODE_VERSION=18.20.4
ENV PATH="$NODE_PATH/node/bin:$PATH"
# Install the latest version of @elastic/synthetics forcefully ignoring the previously
# cached node_modules, heartbeat then calls the global executable to run test suites
# Setup node
RUN cd {{$beatHome}}/.node \
&& NODE_DOWNLOAD_URL="" \
&& case "$(arch)" in \
arm64) \
NODE_DOWNLOAD_URL=https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.xz \
;; \
x86_64) \
NODE_DOWNLOAD_URL=https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.xz \
;; \
aarch64) \
NODE_DOWNLOAD_URL=https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-arm64.tar.xz \
;; \
*) \
echo >&2 ; echo >&2 "Unsupported architecture \$(arch)" ; echo >&2 ; exit 1 ; \
;; \
esac \
&& mkdir -p node \
&& curl ${NODE_DOWNLOAD_URL} | tar -xJ --strip 1 -C node \
&& chmod ugo+rwX -R $NODE_PATH \
# Install synthetics as a regular user, installing npm deps as root odesn't work
# fix .node .npm and .synthetics
&& chown -R {{ .user }}:{{ .user }} $NODE_PATH
USER {{ .user }}
# If this fails dump the NPM logs
RUN (npm i -g --loglevel verbose --production --engine-strict @elastic/synthetics@stack_release || sh -c 'tail -n +1 /root/.npm/_logs/* && exit 1') && \
chmod ugo+rwX -R $NODE_PATH
USER root
# Install the deps as needed by the exact version of playwright elastic synthetics uses
# We don't use npx playwright install-deps because that could pull a newer version
# Install additional fonts as well
RUN for iter in {1..10}; do \
apt-get update -y && \
$NODE_PATH/node/lib/node_modules/@elastic/synthetics/node_modules/.bin/playwright install-deps chromium && \
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes \
fonts-noto \
fonts-noto-cjk && \
exit_code=0 && break || exit_code=$? && echo "apt-get error: retry $iter in 10s" && sleep 10; \
done; \
(exit $exit_code)
{{- end }}
{{- if (and (eq .Variant "complete-wolfi") (contains .from "wolfi")) }}
USER root
# Install required dependencies from wolfi repository
RUN for iter in {1..10}; do \
apk update && \
apk add --no-interactive --no-progress --no-cache nodejs-18=18.20.4-r0 npm=10.8.3-r0 glib dbus-glib libatk-1.0 \
libatk-bridge-2.0 cups-libs libxcomposite libxdamage libxrandr libxkbcommon pango alsa-lib \
font-opensans fontconfig gtk icu-data-full libnss mesa font-noto-cjk font-noto-emoji && \
exit_code=0 && break || exit_code=$? && echo "apk error: retry $iter in 10s" && sleep 10; \
done; \
(exit $exit_code)
# Setup synthetics env vars
ENV ELASTIC_SYNTHETICS_CAPABLE=true
ENV TZ=UTC
ENV NPM_CONFIG_PREFIX={{ $beatHome }}/.npm
ENV PATH="$NPM_CONFIG_PREFIX/bin:$PATH"
RUN echo \
$NPM_CONFIG_PREFIX \
{{ $beatHome }}/.config \
{{ $beatHome }}/.synthetics \
{{ $beatHome }}/.npm \
{{ $beatHome }}/.cache \
| xargs -IDIR sh -c 'mkdir -m 0770 -p DIR && chown -R {{ .user }} DIR'
USER {{ .user }}
RUN (npm i -g --loglevel verbose --production --engine-strict @elastic/synthetics@stack_release || sh -c 'tail -n +1 ${NPM_CONFIG_PREFIX}/_logs/* && exit 1')
{{- end }}
USER {{ .user }}
{{- range $i, $port := .ExposePorts }}
EXPOSE {{ $port }}
{{- end }}
# When running under Docker, we must ensure libbeat monitoring pulls cgroup
# metrics from /sys/fs/cgroup/<subsystem>/, ignoring any paths found in
# /proc/self/cgroup.
ENV LIBBEAT_MONITORING_CGROUPS_HIERARCHY_OVERRIDE=/
WORKDIR {{ $beatHome }}
{{- if eq .Variant "cloud" }}
ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["/app/apm.sh"]
# Generate a stub command that will be overwritten at runtime
RUN echo -e '#!/bin/sh\nexec /usr/local/bin/docker-entrypoint' > /app/apm.sh && \
chmod 0555 /app/apm.sh
{{- else }}
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/docker-entrypoint"]
{{- end }}