14
14
layout/presentation here has been adjusted so that it looks reasonable when rendered,
15
15
at the slight expense of how it looks here.
16
16
*/ %>
17
+ <% if (docker_base == "ubi") { %>
17
18
################################################################################
18
19
# Build stage 0 `builder`:
19
20
# Extract Elasticsearch artifact
20
21
################################################################################
21
22
22
23
FROM ${base_image} AS builder
23
- <% if (docker_base == ' ubi ') { %>
24
+
24
25
# Install required packages to extract the Elasticsearch distribution
25
26
RUN ${package_manager} install -y tar gzip
26
- <% } %>
27
+
27
28
# `tini` is a tiny but valid init for containers. This is used to cleanly
28
29
# control how ES and any child processes are shut down.
29
30
#
@@ -41,21 +42,167 @@ RUN set -eux ; \\
41
42
curl --retry 8 -S -L -O https://github.com/krallin/tini/releases/download/v0.19.0/\$ {tini_bin}.sha256sum ; \\
42
43
sha256sum -c \$ {tini_bin}.sha256sum ; \\
43
44
rm \$ {tini_bin}.sha256sum ; \\
44
- mv \$ {tini_bin} /tini ; \\
45
- chmod +x /tini
45
+ mv \$ {tini_bin} /bin/tini ; \\
46
+ chmod +x /bin/tini
47
+ <% } else { %>
48
+ ################################################################################
49
+ # Stage 1. Build curl statically. Installing it from RPM on CentOS pulls in too
50
+ # many dependencies.
51
+ ################################################################################
52
+ FROM alpine:latest AS curl
53
+
54
+ ENV VERSION 7.71.0
55
+ ENV TARBALL_URL https://curl.haxx.se/download/curl-\$ {VERSION}.tar.xz
56
+ ENV TARBALL_PATH curl-\$ {VERSION}.tar.xz
57
+
58
+ # Install dependencies
59
+ RUN apk add gnupg gcc make musl-dev openssl-dev openssl-libs-static file
60
+
61
+ RUN mkdir /work
62
+ WORKDIR /work
63
+
64
+ # Fetch curl sources and files for validation
65
+ RUN wget "https://daniel.haxx.se/mykey.asc" -O "curl-gpg.pub" && \\
66
+ wget "\$ {TARBALL_URL}.asc" -O "\$ {TARBALL_PATH}.asc" && \\
67
+ wget "\$ {TARBALL_URL}" -O "\$ {TARBALL_PATH}"
68
+
69
+ # Validate source
70
+ RUN gpg --import --always-trust "curl-gpg.pub" && \\
71
+ gpg --verify "\$ {TARBALL_PATH}.asc" "\$ {TARBALL_PATH}"
72
+
73
+ # Unpack and build
74
+ RUN tar xfJ "\$ {TARBALL_PATH}" && \\
75
+ cd "curl-\$ {VERSION}" && \\
76
+ ./configure --disable-shared --with-ca-fallback --with-ca-bundle=/etc/pki/tls/certs/ca-bundle.crt && \\
77
+ make curl_LDFLAGS="-all-static" && \\
78
+ cp src/curl /work/curl && \\
79
+ strip /work/curl
80
+
81
+ ################################################################################
82
+ # Step 2. Create a minimal root filesystem directory. This will form the basis
83
+ # for our image.
84
+ ################################################################################
85
+ FROM ${base_image} AS rootfs
86
+
87
+ ENV BUSYBOX_VERSION 1.31.0
88
+ ENV TINI_VERSION 0.19.0
89
+
90
+ # Start off with an up-to-date system
91
+ RUN ${package_manager} update --setopt=tsflags=nodocs -y
92
+
93
+ # Create a directory into which we will install files
94
+ RUN mkdir /rootfs
95
+
96
+ # Create required devices
97
+ RUN mkdir -m 755 /rootfs/dev && \\
98
+ mknod -m 600 /rootfs/dev/console c 5 1 && \\
99
+ mknod -m 600 /rootfs/dev/initctl p && \\
100
+ mknod -m 666 /rootfs/dev/full c 1 7 && \\
101
+ mknod -m 666 /rootfs/dev/null c 1 3 && \\
102
+ mknod -m 666 /rootfs/dev/ptmx c 5 2 && \\
103
+ mknod -m 666 /rootfs/dev/random c 1 8 && \\
104
+ mknod -m 666 /rootfs/dev/tty c 5 0 && \\
105
+ mknod -m 666 /rootfs/dev/tty0 c 4 0 && \\
106
+ mknod -m 666 /rootfs/dev/urandom c 1 9 && \\
107
+ mknod -m 666 /rootfs/dev/zero c 1 5
108
+
109
+ # Install a minimal set of dependencies, and some for Elasticsearch
110
+ RUN ${package_manager} --installroot=/rootfs --releasever=/ --setopt=tsflags=nodocs \\
111
+ --setopt=group_package_types=mandatory -y \\
112
+ --skip-broken \\
113
+ install basesystem bash zip zlib
114
+
115
+ # `tini` is a tiny but valid init for containers. This is used to cleanly
116
+ # control how ES and any child processes are shut down.
117
+ #
118
+ # The tini GitHub page gives instructions for verifying the binary using
119
+ # gpg, but the keyservers are slow to return the key and this can fail the
120
+ # build. Instead, we check the binary against the published checksum.
121
+ #
122
+ # Also, we use busybox instead of installing utility RPMs, which pulls in
123
+ # all kinds of stuff we don' t want.
124
+ RUN set -e ; \\
125
+ TINI_BIN="" ; \\
126
+ BUSYBOX_ARCH="" ; \\
127
+ case "\$ (arch)" in \\
128
+ aarch64) \\
129
+ BUSYBOX_ARCH='armv8l' ; \\
130
+ TINI_BIN='tini-arm64' ; \\
131
+ ;; \\
132
+ x86_64) \\
133
+ BUSYBOX_ARCH='x86_64' ; \\
134
+ TINI_BIN='tini-amd64' ; \\
135
+ ;; \\
136
+ *) echo >&2 "Unsupported architecture \$ (arch)" ; exit 1 ;; \\
137
+ esac ; \\
138
+ curl --retry 8 -S -L -O "https://github.com/krallin/tini/releases/download/v0.19.0/\$ {TINI_BIN}" ; \\
139
+ curl --retry 8 -S -L -O "https://github.com/krallin/tini/releases/download/v0.19.0/\$ {TINI_BIN}.sha256sum" ; \\
140
+ sha256sum -c "\$ {TINI_BIN}.sha256sum" ; \\
141
+ rm "\$ {TINI_BIN}.sha256sum" ; \\
142
+ mv "\$ {TINI_BIN}" /rootfs/bin/tini ; \\
143
+ chmod +x /rootfs/bin/tini ; \\
144
+ curl --retry 10 -L -o /rootfs/bin/busybox \\
145
+ "https://busybox.net/downloads/binaries/\$ {BUSYBOX_VERSION}-defconfig-multiarch-musl/busybox-\$ {BUSYBOX_ARCH}" ; \\
146
+ chmod +x /rootfs/bin/busybox
147
+
148
+ # Add links for most of the Busybox utilities
149
+ RUN set -e ; \\
150
+ for path in \$ ( /rootfs/bin/busybox --list-full | grep -v bin/sh | grep -v telnet | grep -v unzip); do \\
151
+ ln /rootfs/bin/busybox /rootfs/\$ path ; \\
152
+ done
153
+
154
+ # Curl needs files under here. More importantly, we change Elasticsearch's
155
+ # bundled JDK to use /etc/pki/ca-trust/extracted/java/cacerts instead of
156
+ # the bundled cacerts.
157
+ RUN mkdir -p /rootfs/etc && \\
158
+ cp -a /etc/pki /rootfs/etc/
159
+
160
+ # Cleanup the filesystem
161
+ RUN ${package_manager} --installroot=/rootfs -y clean all && \\
162
+ cd /rootfs && \\
163
+ rm -rf \\
164
+ etc/{X11,centos-release*,csh*,profile*,skel*,yum*} \\
165
+ sbin/sln \\
166
+ usr/bin/rpm \\
167
+ {usr,var}/games \\
168
+ usr/lib/{dracut,systemd,udev} \\
169
+ usr/lib64/X11 \\
170
+ usr/local \\
171
+ usr/share/{awk,centos-release,cracklib,desktop-directories,gcc-*,i18n,icons,licenses,xsessions,zoneinfo} \\
172
+ usr/share/{man,doc,info,games,gdb,ghostscript,gnome,groff,icons,pixmaps,sounds,backgrounds,themes,X11} \\
173
+ usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive} \\
174
+ var/cache/yum \\
175
+ var/lib/{rpm,yum} \\
176
+ var/log/yum.log
177
+
178
+ # ldconfig
179
+ RUN rm -rf /rootfs/etc/ld.so.cache /rootfs/var/cache/ldconfig && \\
180
+ mkdir -p --mode=0755 /rootfs/var/cache/ldconfig
181
+
182
+ COPY --from=curl /work/curl /rootfs/usr/bin/curl
183
+
184
+ # ###############################################################################
185
+ # Step 3. Fetch the Elasticsearch distribution and configure it for Docker
186
+ # ###############################################################################
187
+ FROM ${base_image} AS builder
188
+ <% } %>
46
189
47
190
RUN mkdir /usr/share/elasticsearch
48
191
WORKDIR /usr/share/elasticsearch
49
192
193
+ # Fetch the appropriate Elasticsearch distribution for this architecture
50
194
${source_elasticsearch}
51
195
52
196
RUN tar zxf /opt/elasticsearch.tar.gz --strip-components=1
197
+
198
+ # Configure the distribution for Docker
53
199
RUN sed -i -e 's/ES_DISTRIBUTION_TYPE=tar/ES_DISTRIBUTION_TYPE=docker/' /usr/share/elasticsearch/bin/elasticsearch-env
54
200
RUN mkdir -p config config/jvm.options.d data logs
55
201
RUN chmod 0775 config config/jvm.options.d data logs
56
202
COPY config/elasticsearch.yml config/log4j2.properties config/
57
203
RUN chmod 0660 config/elasticsearch.yml config/log4j2.properties
58
204
205
+ <% if (docker_base == "ubi" ) { %>
59
206
# ###############################################################################
60
207
# Build stage 1 (the actual Elasticsearch image):
61
208
#
@@ -65,12 +212,10 @@ RUN chmod 0660 config/elasticsearch.yml config/log4j2.properties
65
212
66
213
FROM ${base_image}
67
214
68
- ENV ELASTIC_CONTAINER true
69
-
70
215
RUN for iter in {1..10}; do \\
71
216
${package_manager} update --setopt=tsflags=nodocs -y && \\
72
217
${package_manager} install --setopt=tsflags=nodocs -y \\
73
- nc shadow-utils zip unzip <%= docker_base == ' ubi ' ? ' findutils procps-ng' : '' %> && \\
218
+ nc shadow-utils zip unzip findutils procps-ng && \\
74
219
${package_manager} clean all && exit_code=0 && break || exit_code=\$ ? && echo "${package_manager} error: retry \$ iter in 10s" && \\
75
220
sleep 10; \\
76
221
done; \\
@@ -80,10 +225,30 @@ RUN groupadd -g 1000 elasticsearch && \\
80
225
adduser -u 1000 -g 1000 -G 0 -d /usr/share/elasticsearch elasticsearch && \\
81
226
chmod 0775 /usr/share/elasticsearch && \\
82
227
chown -R 1000:0 /usr/share/elasticsearch
228
+ <% } else { %>
229
+ # ###############################################################################
230
+ # Stage 4. Build the final image, using the rootfs above as the basis, and
231
+ # copying in the Elasticsearch distribution
232
+ # ###############################################################################
233
+ FROM scratch
234
+
235
+ # Setup the initial filesystem.
236
+ COPY --from=rootfs /rootfs /
237
+
238
+ RUN addgroup -g 1000 elasticsearch && \\
239
+ adduser -D -u 1000 -G elasticsearch -g elasticsearch -h /usr/share/elasticsearch elasticsearch && \\
240
+ addgroup elasticsearch root && \\
241
+ chmod 0775 /usr/share/elasticsearch && \\
242
+ chgrp 0 /usr/share/elasticsearch
243
+ <% } %>
244
+
245
+ ENV ELASTIC_CONTAINER true
83
246
84
247
WORKDIR /usr/share/elasticsearch
85
248
COPY --from=builder --chown=1000:0 /usr/share/elasticsearch /usr/share/elasticsearch
86
- COPY --from=builder --chown=0:0 /tini /tini
249
+ <% if (docker_base == "ubi" ) { %>
250
+ COPY --from=builder --chown=0:0 /bin/tini /bin/tini
251
+ <% } %>
87
252
88
253
# Replace OpenJDK's built-in CA certificate keystore with the one from the OS
89
254
# vendor. The latter is superior in several ways.
@@ -94,14 +259,15 @@ ENV PATH /usr/share/elasticsearch/bin:\$PATH
94
259
95
260
COPY bin/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
96
261
97
- # The JDK's directories' permissions don't allow `java` to be executed under a different
98
- # group to the default. Fix this.
262
+ # 1. The JDK's directories' permissions don't allow `java` to be executed under a different
263
+ # group to the default. Fix this.
264
+ # 2. Sync the user and group permissions of /etc/passwd
265
+ # 3. Set correct permissions of the entrypoint
266
+ # 4. Ensure that there are no files with setuid or setgid, in order to mitigate "stackclash" attacks.
99
267
RUN find /usr/share/elasticsearch/jdk -type d -exec chmod 0755 '{}' \\ ; && \\
100
268
chmod g=u /etc/passwd && \\
101
- chmod 0775 /usr/local/bin/docker-entrypoint.sh
102
-
103
- # Ensure that there are no files with setuid or setgid, in order to mitigate "stackclash" attacks.
104
- RUN find / -xdev -perm -4000 -exec chmod ug-s {} +
269
+ chmod 0775 /usr/local/bin/docker-entrypoint.sh && \\
270
+ find / -xdev -perm -4000 -exec chmod ug-s {} +
105
271
106
272
EXPOSE 9200 9300
107
273
@@ -138,7 +304,10 @@ RUN mkdir /licenses && \\
138
304
<% } %>
139
305
USER elasticsearch:root
140
306
141
- ENTRYPOINT ["/tini" , "--" , "/usr/local/bin/docker-entrypoint.sh" ]
307
+ # Our actual entrypoint is `tini`, a minimal but functional init program. It
308
+ # calls the entrypoint we provide, while correctly forwarding signals.
309
+ ENTRYPOINT ["/bin/tini" , "--" , "/usr/local/bin/docker-entrypoint.sh" ]
310
+
142
311
# Dummy overridable parameter parsed by entrypoint
143
312
CMD ["eswrapper" ]
144
313
0 commit comments