diff --git a/distribution/docker/src/docker/Dockerfile b/distribution/docker/src/docker/Dockerfile index 0b553f5b7513f..b24496dfc0908 100644 --- a/distribution/docker/src/docker/Dockerfile +++ b/distribution/docker/src/docker/Dockerfile @@ -18,26 +18,16 @@ Note that this file is also filtered to squash together newlines, so we can add as many newlines here as necessary to improve legibility. */ %> + +<% if (docker_base == "ubi") { %> ################################################################################ # Build stage 0 `builder`: # Extract Elasticsearch artifact ################################################################################ - -${build_args} - FROM ${base_image} AS builder -<% if (docker_base == 'ubi') { %> # Install required packages to extract the Elasticsearch distribution RUN <%= retry.loop(package_manager, "${package_manager} install -y findutils tar gzip") %> -<% } %> - -<% if (docker_base == 'iron_bank') { %> -# `tini` is a tiny but valid init for containers. This is used to cleanly -# control how ES and any child processes are shut down. -COPY tini /bin/tini -RUN chmod 0755 /bin/tini -<% } else { %> # `tini` is a tiny but valid init for containers. This is used to cleanly # control how ES and any child processes are shut down. @@ -59,6 +49,108 @@ RUN set -eux ; \\ mv \${tini_bin} /bin/tini ; \\ chmod +x /bin/tini +<% } else if (docker_base == 'iron_bank') { %> +################################################################################ +# Build stage 0 `builder`: +# Extract Elasticsearch artifact +################################################################################ + +${build_args} + +FROM ${base_image} AS builder + +# `tini` is a tiny but valid init for containers. This is used to cleanly +# control how ES and any child processes are shut down. +COPY tini /bin/tini +RUN chmod 0755 /bin/tini + +<% } else { %> + +<% /* CentOS builds are actaully a custom base image with a minimal set of dependencies */ %> + +################################################################################ +# Step 1. Create a minimal root filesystem directory. This will form the basis +# for our image. +################################################################################ +FROM ${base_image} AS rootfs + +ENV TINI_VERSION 0.19.0 + +# Start off with an up-to-date system +RUN ${package_manager} update --setopt=tsflags=nodocs -y + +# Create a directory into which we will install files +RUN mkdir /rootfs + +# Create required devices +RUN mkdir -m 755 /rootfs/dev && \\ + mknod -m 600 /rootfs/dev/console c 5 1 && \\ + mknod -m 600 /rootfs/dev/initctl p && \\ + mknod -m 666 /rootfs/dev/full c 1 7 && \\ + mknod -m 666 /rootfs/dev/null c 1 3 && \\ + mknod -m 666 /rootfs/dev/ptmx c 5 2 && \\ + mknod -m 666 /rootfs/dev/random c 1 8 && \\ + mknod -m 666 /rootfs/dev/tty c 5 0 && \\ + mknod -m 666 /rootfs/dev/tty0 c 4 0 && \\ + mknod -m 666 /rootfs/dev/urandom c 1 9 && \\ + mknod -m 666 /rootfs/dev/zero c 1 5 + +# Install a minimal set of dependencies, and some for Elasticsearch +RUN ${package_manager} --installroot=/rootfs --releasever=/ --setopt=tsflags=nodocs \\ + --setopt=group_package_types=mandatory -y \\ + install bash curl findutils nc procps-ng shadow-utils unzip yum zip + +# `tini` is a tiny but valid init for containers. This is used to cleanly +# control how ES and any child processes are shut down. +# +# The tini GitHub page gives instructions for verifying the binary using +# gpg, but the keyservers are slow to return the key and this can fail the +# build. Instead, we check the binary against the published checksum. +RUN set -e ; \\ + TINI_BIN="" ; \\ + case "\$(arch)" in \\ + aarch64) \\ + TINI_BIN='tini-arm64' ; \\ + ;; \\ + x86_64) \\ + TINI_BIN='tini-amd64' ; \\ + ;; \\ + *) echo >&2 "Unsupported architecture \$(arch)" ; exit 1 ;; \\ + esac ; \\ + curl --retry 10 -S -L -O "https://github.com/krallin/tini/releases/download/v0.19.0/\${TINI_BIN}" ; \\ + curl --retry 10 -S -L -O "https://github.com/krallin/tini/releases/download/v0.19.0/\${TINI_BIN}.sha256sum" ; \\ + sha256sum -c "\${TINI_BIN}.sha256sum" ; \\ + rm "\${TINI_BIN}.sha256sum" ; \\ + mv "\${TINI_BIN}" /rootfs/bin/tini ; \\ + chmod +x /rootfs/bin/tini + +RUN echo "NETWORKING=yes" > /rootfs/etc/sysconfig/network && \\ + echo "HOSTNAME=localhost.localdomain" >> /rootfs/etc/sysconfig/network + +# Cleanup the filesystem +RUN ${package_manager} --installroot=/rootfs -y clean all && \\ + cd /rootfs && \\ + rm -rf \\ + sbin/sln \\ + usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive} \\ + usr/share/{man,doc,info,gnome/help} \\ + usr/share/cracklib \\ + usr/share/i18n \\ + var/cache/yum && \\ + mkdir -p --mode=0755 var/cache/yum + +# ldconfig +RUN rm -rf /rootfs/etc/ld.so.cache /rootfs/var/cache/ldconfig && \\ + mkdir -p --mode=0755 /rootfs/var/cache/ldconfig + +# Ensure that there are no files with setuid or setgid, in order to mitigate "stackclash" attacks. +RUN find /rootfs -xdev -perm -4000 -exec chmod ug-s {} + + +################################################################################ +# Step 2. Fetch the Elasticsearch distribution and configure it for Docker +################################################################################ +FROM ${base_image} AS builder + <% } %> RUN mkdir /usr/share/elasticsearch @@ -100,6 +192,8 @@ RUN sed -i -e 's/ES_DISTRIBUTION_TYPE=tar/ES_DISTRIBUTION_TYPE=docker/' bin/elas find . -xdev -perm -4000 -exec chmod ug-s {} + && \\ find . -type f -exec chmod o+r {} + +<% if (docker_base == "ubi" || docker_base == "iron_bank") { %> + ################################################################################ # Build stage 1 (the actual Elasticsearch image): # @@ -109,25 +203,39 @@ RUN sed -i -e 's/ES_DISTRIBUTION_TYPE=tar/ES_DISTRIBUTION_TYPE=docker/' bin/elas FROM ${base_image} -<% if (docker_base == "iron_bank") { %> +<% if (docker_base == "ubi") { %> + +RUN <%= retry.loop( + package_manager, + "${package_manager} update --setopt=tsflags=nodocs -y && \n" + + " ${package_manager} install --setopt=tsflags=nodocs -y \n" + + " nc shadow-utils zip unzip findutils procps-ng && \n" + + " ${package_manager} clean all" + ) %> + +<% } else { %> + <% /* Reviews of the Iron Bank Dockerfile said that they preferred simpler */ -/* scripting so this version doesn't have the retry loop featured below. */ +/* scripting so this version doesn't have the retry loop featured above. */ %> RUN ${package_manager} update --setopt=tsflags=nodocs -y && \\ ${package_manager} install --setopt=tsflags=nodocs -y \\ nc shadow-utils zip findutils unzip procps-ng && \\ ${package_manager} clean all +<% } %> + <% } else { %> -RUN <%= retry.loop( - package_manager, - "${package_manager} update --setopt=tsflags=nodocs -y && \n" + - " ${package_manager} install --setopt=tsflags=nodocs -y \n" + - " nc shadow-utils zip unzip ${docker_base == 'ubi' ? 'findutils procps-ng' : ''} && \n" + - " ${package_manager} clean all" - ) %> +################################################################################ +# Stage 3. Build the final image, using the rootfs above as the basis, and +# copying in the Elasticsearch distribution +################################################################################ +FROM scratch + +# Setup the initial filesystem. +COPY --from=rootfs /rootfs / <% } %> @@ -140,7 +248,10 @@ ENV ELASTIC_CONTAINER true WORKDIR /usr/share/elasticsearch COPY --from=builder --chown=1000:0 /usr/share/elasticsearch /usr/share/elasticsearch + +<% if (docker_base == "ubi" || docker_base == "iron_bank") { %> COPY --from=builder --chown=0:0 /bin/tini /bin/tini +<% } %> ENV PATH /usr/share/elasticsearch/bin:\$PATH @@ -203,7 +314,10 @@ COPY LICENSE /licenses/LICENSE.addendum USER elasticsearch:root <% } %> +# Our actual entrypoint is `tini`, a minimal but functional init program. It +# calls the entrypoint we provide, while correctly forwarding signals. ENTRYPOINT ["/bin/tini", "--", "/usr/local/bin/docker-entrypoint.sh"] + # Dummy overridable parameter parsed by entrypoint CMD ["eswrapper"]