Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce default Docker image size in 7.x #75079

Merged
merged 3 commits into from
Jul 22, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 135 additions & 21 deletions distribution/docker/src/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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):
#
Expand All @@ -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 /

<% } %>

Expand All @@ -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

Expand Down Expand Up @@ -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"]

Expand Down