5
5
# ###############################################################################
6
6
7
7
# ###############################################################################
8
- # Build stage 0 `builder`:
9
- # Extract Elasticsearch artifact
8
+ # Stage 1. Build curl statically. Installing it from RPM on CentOS pulls in too
9
+ # many dependencies.
10
10
# ###############################################################################
11
+ FROM alpine:3.13 AS curl
11
12
12
- FROM centos:8 AS builder
13
+ ENV VERSION 7.71.0
14
+ ENV TARBALL_URL https://curl.haxx.se/download/curl-${VERSION}.tar.xz
15
+ ENV TARBALL_PATH curl-${VERSION}.tar.xz
16
+
17
+ # Install dependencies
18
+ RUN for iter in {1..10}; do \
19
+ apk add gnupg gcc make musl-dev openssl-dev openssl-libs-static file && \
20
+ exit_code=0 && break || \
21
+ exit_code=$? && echo "apk error: retry $iter in 10s" && sleep 10; \
22
+ done; \
23
+ exit $exit_code
24
+
25
+ RUN mkdir /work
26
+ WORKDIR /work
27
+
28
+ # Fetch curl sources and files for validation. Note that alpine's `wget` doesn't have retry options.
29
+ RUN function retry_wget() { \
30
+ local URL="$1" ; \
31
+ local DEST="$2" ; \
32
+ for iter in {1..10}; do \
33
+ wget "$URL" -O "$DEST" && \
34
+ exit_code=0 && break || \
35
+ exit_code=$? && echo "wget error: retry $iter in 10s" && sleep 10; \
36
+ done; \
37
+ return $exit_code ; \
38
+ } ; \
39
+ retry_wget "https://daniel.haxx.se/mykey.asc" "curl-gpg.pub" && \
40
+ retry_wget "${TARBALL_URL}.asc" "${TARBALL_PATH}.asc" && \
41
+ retry_wget "${TARBALL_URL}" "${TARBALL_PATH}"
42
+
43
+ # Validate source
44
+ RUN gpg --import --always-trust "curl-gpg.pub" && \
45
+ gpg --verify "${TARBALL_PATH}.asc" "${TARBALL_PATH}"
46
+
47
+ # Unpack and build
48
+ RUN set -e ; \
49
+ tar xfJ "${TARBALL_PATH}" ; \
50
+ cd "curl-${VERSION}" ; \
51
+ if ! ./configure --disable-shared --with-ca-fallback --with-ca-bundle=/etc/pki/tls/certs/ca-bundle.crt ; then \
52
+ [[ -e config.log ]] && cat config.log ; \
53
+ exit 1 ; \
54
+ fi ; \
55
+ make curl_LDFLAGS="-all-static" ; \
56
+ cp src/curl /work/curl ; \
57
+ strip /work/curl
58
+
59
+ # ###############################################################################
60
+ # Step 2. Create a minimal root filesystem directory. This will form the basis
61
+ # for our image.
62
+ # ###############################################################################
63
+ FROM centos:8 AS rootfs
64
+
65
+ ENV TINI_VERSION 0.19.0
66
+
67
+ # Start off with an up-to-date system
68
+ RUN yum update --setopt=tsflags=nodocs -y
69
+
70
+ # Create a directory into which we will install files
71
+ RUN mkdir /rootfs
72
+
73
+ # Create required devices
74
+ RUN mkdir -m 755 /rootfs/dev && \
75
+ mknod -m 600 /rootfs/dev/console c 5 1 && \
76
+ mknod -m 600 /rootfs/dev/initctl p && \
77
+ mknod -m 666 /rootfs/dev/full c 1 7 && \
78
+ mknod -m 666 /rootfs/dev/null c 1 3 && \
79
+ mknod -m 666 /rootfs/dev/ptmx c 5 2 && \
80
+ mknod -m 666 /rootfs/dev/random c 1 8 && \
81
+ mknod -m 666 /rootfs/dev/tty c 5 0 && \
82
+ mknod -m 666 /rootfs/dev/tty0 c 4 0 && \
83
+ mknod -m 666 /rootfs/dev/urandom c 1 9 && \
84
+ mknod -m 666 /rootfs/dev/zero c 1 5
85
+
86
+ # Install a minimal set of dependencies, and some for Elasticsearch
87
+ RUN yum --installroot=/rootfs --releasever=/ --setopt=tsflags=nodocs \
88
+ --setopt=group_package_types=mandatory -y \
89
+ --skip-broken \
90
+ install basesystem bash zip zlib
13
91
14
92
# `tini` is a tiny but valid init for containers. This is used to cleanly
15
93
# control how ES and any child processes are shut down.
16
94
#
17
95
# The tini GitHub page gives instructions for verifying the binary using
18
96
# gpg, but the keyservers are slow to return the key and this can fail the
19
97
# build. Instead, we check the binary against the published checksum.
20
- RUN set -eux ; \
21
- tini_bin="" ; \
98
+ #
99
+ # Also, we use busybox instead of installing utility RPMs, which pulls in
100
+ # all kinds of stuff we don't want.
101
+ RUN set -e ; \
102
+ TINI_BIN="" ; \
103
+ BUSYBOX_COMMIT="" ; \
22
104
case "$(arch)" in \
23
- aarch64) tini_bin='tini-arm64' ;; \
24
- x86_64) tini_bin='tini-amd64' ;; \
25
- *) echo >&2 ; echo >&2 "Unsupported architecture $(arch)" ; echo >&2 ; exit 1 ;; \
105
+ aarch64) \
106
+ BUSYBOX_COMMIT='8a500845daeaeb926b25f73089c0668cac676e97' ; \
107
+ TINI_BIN='tini-arm64' ; \
108
+ ;; \
109
+ x86_64) \
110
+ BUSYBOX_COMMIT='cc81bf8a3c979f596af2d811a3910aeaa230e8ef' ; \
111
+ TINI_BIN='tini-amd64' ; \
112
+ ;; \
113
+ *) echo >&2 "Unsupported architecture $(arch)" ; exit 1 ;; \
26
114
esac ; \
27
- curl --retry 10 -S -L -O https://github.com/krallin/tini/releases/download/v0.19.0/${tini_bin} ; \
28
- curl --retry 10 -S -L -O https://github.com/krallin/tini/releases/download/v0.19.0/${tini_bin}.sha256sum ; \
29
- sha256sum -c ${tini_bin}.sha256sum ; \
30
- rm ${tini_bin}.sha256sum ; \
31
- mv ${tini_bin} /bin/tini ; \
32
- chmod +x /bin/tini
115
+ curl --retry 10 -S -L -O "https://github.com/krallin/tini/releases/download/v0.19.0/${TINI_BIN}" ; \
116
+ curl --retry 10 -S -L -O "https://github.com/krallin/tini/releases/download/v0.19.0/${TINI_BIN}.sha256sum" ; \
117
+ sha256sum -c "${TINI_BIN}.sha256sum" ; \
118
+ rm "${TINI_BIN}.sha256sum" ; \
119
+ mv "${TINI_BIN}" /rootfs/bin/tini ; \
120
+ chmod 0555 /rootfs/bin/tini ; \
121
+ curl --retry 10 -L -O \
122
+ # Here we're fetching the same binaries used for the official busybox docker image from their GtiHub repository
123
+ "https://github.com/docker-library/busybox/raw/${BUSYBOX_COMMIT}/stable/musl/busybox.tar.xz" ; \
124
+ tar -xf busybox.tar.xz -C /rootfs/bin --strip=2 ./bin ; \
125
+ rm busybox.tar.xz ;
126
+
127
+ # Curl needs files under here. More importantly, we change Elasticsearch's
128
+ # bundled JDK to use /etc/pki/ca-trust/extracted/java/cacerts instead of
129
+ # the bundled cacerts.
130
+ RUN mkdir -p /rootfs/etc && \
131
+ cp -a /etc/pki /rootfs/etc/
132
+
133
+ # Cleanup the filesystem
134
+ RUN yum --installroot=/rootfs -y clean all && \
135
+ cd /rootfs && \
136
+ rm -rf \
137
+ etc/{X11,centos-release*,csh*,profile*,skel*,yum*} \
138
+ sbin/sln \
139
+ usr/bin/rpm \
140
+ {usr,var}/games \
141
+ usr/lib/{dracut,systemd,udev} \
142
+ usr/lib64/X11 \
143
+ usr/local \
144
+ usr/share/{awk,centos-release,cracklib,desktop-directories,gcc-*,i18n,icons,licenses,xsessions,zoneinfo} \
145
+ usr/share/{man,doc,info,games,gdb,ghostscript,gnome,groff,icons,pixmaps,sounds,backgrounds,themes,X11} \
146
+ usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive} \
147
+ var/cache/yum \
148
+ var/lib/{rpm,yum} \
149
+ var/log/yum.log
150
+
151
+ # ldconfig
152
+ RUN rm -rf /rootfs/etc/ld.so.cache /rootfs/var/cache/ldconfig && \
153
+ mkdir -p --mode=0755 /rootfs/var/cache/ldconfig
154
+
155
+ COPY --from=curl /work/curl /rootfs/usr/bin/curl
156
+
157
+ # Ensure that there are no files with setuid or setgid, in order to mitigate "stackclash" attacks.
158
+ RUN find /rootfs -xdev -perm -4000 -exec chmod ug-s {} +
159
+
160
+ # ###############################################################################
161
+ # Step 3. Fetch the Elasticsearch distribution and configure it for Docker
162
+ # ###############################################################################
163
+ FROM centos:8 AS builder
33
164
34
165
RUN mkdir /usr/share/elasticsearch
35
166
WORKDIR /usr/share/elasticsearch
36
167
37
- RUN curl --retry 10 -S -L --output /opt/elasticsearch.tar.gz https://artifacts-no-kpi.elastic.co/downloads/elasticsearch/elasticsearch-7.14.0 -linux-$(arch).tar.gz
168
+ RUN curl --retry 10 -S -L --output /opt/elasticsearch.tar.gz https://artifacts-no-kpi.elastic.co/downloads/elasticsearch/elasticsearch-8.0.0-alpha1 -linux-$(arch).tar.gz
38
169
39
170
RUN tar -zxf /opt/elasticsearch.tar.gz --strip-components=1
40
171
@@ -43,57 +174,43 @@ COPY config/elasticsearch.yml config/
43
174
COPY config/log4j2.properties config/log4j2.docker.properties
44
175
45
176
# 1. Configure the distribution for Docker
46
- # 2. Ensure directories are created. Most already are, but make sure
47
- # 3. Apply correct permissions
48
- # 4. Move the distribution's default logging config aside
49
- # 5. Generate a docker logging config, to be used by default
50
- # 6. Apply more correct permissions
51
- # 7. The JDK's directories' permissions don't allow `java` to be executed under a different
52
- # group to the default. Fix this.
53
- # 8. Remove write permissions from all files under `lib`, `bin`, `jdk` and `modules`
54
- # 9. Ensure that there are no files with setuid or setgid, in order to mitigate "stackclash" attacks.
55
- # 10. Ensure all files are world-readable by default. It should be possible to
56
- # examine the contents of the image under any UID:GID
177
+ # 2. Create required directory
178
+ # 3. Move the distribution's default logging config aside
179
+ # 4. Move the generated docker logging config so that it is the default
180
+ # 5. Reset permissions on all directories
181
+ # 6. Reset permissions on all files
182
+ # 7. Make CLI tools executable
183
+ # 8. Make some directories writable. `bin` must be writable because
184
+ # plugins can install their own CLI utilities.
185
+ # 9. Make some files writable
57
186
RUN sed -i -e 's/ES_DISTRIBUTION_TYPE=tar/ES_DISTRIBUTION_TYPE=docker/' bin/elasticsearch-env && \
58
- mkdir -p config/jvm.options.d data logs plugins && \
59
- chmod 0775 config config/jvm.options.d data logs plugins && \
187
+ mkdir data && \
60
188
mv config/log4j2.properties config/log4j2.file.properties && \
61
189
mv config/log4j2.docker.properties config/log4j2.properties && \
62
- chmod 0660 config/elasticsearch.yml config/log4j2*.properties && \
63
- find ./jdk -type d -exec chmod 0755 {} + && \
64
- chmod -R a-w lib bin jdk modules && \
65
- find . -xdev -perm -4000 -exec chmod ug-s {} + && \
66
- find . -type f -exec chmod o+r {} +
190
+ find . -type d -exec chmod 0555 {} + && \
191
+ find . -type f -exec chmod 0444 {} + && \
192
+ chmod 0555 bin/* jdk/ bin/* jdk/lib/jspawnhelper modules/x-pack-ml/platform/linux-*/bin/* && \
193
+ chmod 0775 bin config config/jvm.options.d data logs plugins && \
194
+ find config -type f -exec chmod 0664 {} +
67
195
68
196
# ###############################################################################
69
- # Build stage 1 (the actual Elasticsearch image):
70
- #
71
- # Copy elasticsearch from stage 0
72
- # Add entrypoint
197
+ # Stage 4. Build the final image, using the rootfs above as the basis, and
198
+ # copying in the Elasticsearch distribution
73
199
# ###############################################################################
200
+ FROM scratch
74
201
75
- FROM centos:8
202
+ # Setup the initial filesystem.
203
+ COPY --from=rootfs /rootfs /
76
204
77
- RUN for iter in {1..10}; do \
78
- yum update --setopt=tsflags=nodocs -y && \
79
- yum install --setopt=tsflags=nodocs -y \
80
- nc shadow-utils zip unzip && \
81
- yum clean all && \
82
- exit_code=0 && break || \
83
- exit_code=$? && echo "yum error: retry $iter in 10s" && sleep 10; \
84
- done; \
85
- exit $exit_code
86
-
87
- RUN groupadd -g 1000 elasticsearch && \
88
- adduser -u 1000 -g 1000 -G 0 -d /usr/share/elasticsearch elasticsearch && \
89
- chmod 0775 /usr/share/elasticsearch && \
90
- chown -R 1000:0 /usr/share/elasticsearch
205
+ RUN addgroup -g 1000 elasticsearch && \
206
+ adduser -D -u 1000 -G elasticsearch -g elasticsearch -h /usr/share/elasticsearch elasticsearch && \
207
+ addgroup elasticsearch root && \
208
+ chown -R 0:0 /usr/share/elasticsearch
91
209
92
210
ENV ELASTIC_CONTAINER true
93
211
94
212
WORKDIR /usr/share/elasticsearch
95
- COPY --from=builder --chown=1000:0 /usr/share/elasticsearch /usr/share/elasticsearch
96
- COPY --from=builder --chown=0:0 /bin/tini /bin/tini
213
+ COPY --from=builder --chown=0:0 /usr/share/elasticsearch /usr/share/elasticsearch
97
214
98
215
ENV PATH /usr/share/elasticsearch/bin:$PATH
99
216
@@ -106,34 +223,45 @@ COPY bin/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
106
223
# 4. Replace OpenJDK's built-in CA certificate keystore with the one from the OS
107
224
# vendor. The latter is superior in several ways.
108
225
# REF: https://github.com/elastic/elasticsearch-docker/issues/171
226
+ # 5. Tighten up permissions on the ES home dir (the permissions of the contents are handled earlier)
227
+ # 6. You can't install plugins that include configuration when running as `elasticsearch` and the `config`
228
+ # dir is owned by `root`, because the installed tries to manipulate the permissions on the plugin's
229
+ # config directory.
109
230
RUN chmod g=u /etc/passwd && \
110
- chmod 0775 /usr/local/bin/docker-entrypoint.sh && \
231
+ chmod 0555 /usr/local/bin/docker-entrypoint.sh && \
111
232
find / -xdev -perm -4000 -exec chmod ug-s {} + && \
112
- ln -sf /etc/pki/ca-trust/extracted/java/cacerts /usr/share/elasticsearch/jdk/lib/security/cacerts
233
+ ln -sf /etc/pki/ca-trust/extracted/java/cacerts /usr/share/elasticsearch/jdk/lib/security/cacerts && \
234
+ chmod 0775 /usr/share/elasticsearch && \
235
+ chown elasticsearch bin config config/jvm.options.d data logs plugins
113
236
114
237
EXPOSE 9200 9300
115
238
116
- LABEL org.label-schema.build-date="2021-07-29T20:49:32.864135063Z " \
239
+ LABEL org.label-schema.build-date="2021-08-03T20:46:41.477290628Z " \
117
240
org.label-schema.license="Elastic-License-2.0" \
118
241
org.label-schema.name="Elasticsearch" \
119
242
org.label-schema.schema-version="1.0" \
120
243
org.label-schema.url="https://www.elastic.co/products/elasticsearch" \
121
244
org.label-schema.usage="https://www.elastic.co/guide/en/elasticsearch/reference/index.html" \
122
- org.label-schema.vcs-ref="dd5a0a2acaa2045ff9624f3729fc8a6f40835aa1 " \
245
+ org.label-schema.vcs-ref="b11c15b7e0af64f90c3eb9c52c2534b4f143a070 " \
123
246
org.label-schema.vcs-url="https://github.com/elastic/elasticsearch" \
124
247
org.label-schema.vendor="Elastic" \
125
- org.label-schema.version="7.14.0 " \
126
- org.opencontainers.image.created="2021-07-29T20:49:32.864135063Z " \
248
+ org.label-schema.version="8.0.0-alpha1 " \
249
+ org.opencontainers.image.created="2021-08-03T20:46:41.477290628Z " \
127
250
org.opencontainers.image.documentation="https://www.elastic.co/guide/en/elasticsearch/reference/index.html" \
128
251
org.opencontainers.image.licenses="Elastic-License-2.0" \
129
- org.opencontainers.image.revision="dd5a0a2acaa2045ff9624f3729fc8a6f40835aa1 " \
252
+ org.opencontainers.image.revision="b11c15b7e0af64f90c3eb9c52c2534b4f143a070 " \
130
253
org.opencontainers.image.source="https://github.com/elastic/elasticsearch" \
131
254
org.opencontainers.image.title="Elasticsearch" \
132
255
org.opencontainers.image.url="https://www.elastic.co/products/elasticsearch" \
133
256
org.opencontainers.image.vendor="Elastic" \
134
- org.opencontainers.image.version="7.14.0 "
257
+ org.opencontainers.image.version="8.0.0-alpha1 "
135
258
259
+ USER elasticsearch:root
260
+
261
+ # Our actual entrypoint is `tini`, a minimal but functional init program. It
262
+ # calls the entrypoint we provide, while correctly forwarding signals.
136
263
ENTRYPOINT ["/bin/tini" , "--" , "/usr/local/bin/docker-entrypoint.sh" ]
264
+
137
265
# Dummy overridable parameter parsed by entrypoint
138
266
CMD ["eswrapper" ]
139
267
0 commit comments