Skip to content

Commit

Permalink
Reduce default Docker image size in 7.x (#75079)
Browse files Browse the repository at this point in the history
The `centos:8` image hasn't been updated for a while, and now the image
layer for updating it via `yum` is larger than the base image. Address
this by adopting the strategy for 8.0, where we build a custom base
image from `centos:8` and use that instead. The implementation here
differs in that `yum` is still available in the custom image, making it
more like the CentOS image, and therefore less breaking than the 8.0
changes.

Before: 1.04GB
After: 806MB
  • Loading branch information
pugnascotia authored Jul 22, 2021
1 parent 3a6e90c commit d581766
Showing 1 changed file with 135 additions and 21 deletions.
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

0 comments on commit d581766

Please sign in to comment.