Skip to content
This repository has been archived by the owner on Apr 12, 2022. It is now read-only.

Commit

Permalink
Refactor Dockerfile to use multi-stage builds
Browse files Browse the repository at this point in the history
Ensuring all files under /usr/share/elasticsearch have GID=0 **and**
the same group permissions as those of the user is tricky. `-R`
options of `chmod`/`chgrp` increase the image size with a large layer
and introduce slowness in the build process. `tar` doesn't give us any
option to force `gid` while extracting and of course we'd still need to
match the group permissions.

One solution is to prepare the needed files using multi-stage
builds[1] in a separate stage. Unfortunately `COPY` will always use
0:0[2] overriding `USER`, so even if prepare the files at another
stage, we'll still need to mangle ownership+perms or COPY and then
extract an archive, which again increases image size.

docker-ce 17.09 introduced the `--chown`[3] parameter, which solves
this problem.

Move code to extract elasticsearch, adjust ownership + group
permissions, install x-pack and plugins to a stage
`prep_es_files`. This allows have a very clean stage to build the
final elasticsearch image, with a clean history and reasonable size.

IMPORTANT: With this commit, the minimum docker-ce version on the building
machine needs to be `17.09`.

[1]
https://docs.docker.com/engine/userguide/eng-image/multistage-build/
[2] moby/moby#7537 (comment)
[3] moby/moby#34263
  • Loading branch information
dliappis committed Oct 9, 2017
1 parent a952118 commit 0440fa0
Showing 1 changed file with 67 additions and 53 deletions.
120 changes: 67 additions & 53 deletions templates/Dockerfile.j2
@@ -1,4 +1,9 @@
################################################################################
# This Dockerfile was generated from the template at templates/Dockerfile.j2
#
# Beginning of multi stage Dockerfile
################################################################################

{% set ingest_plugins = 'ingest-user-agent ingest-geoip' %}
{% set version_tag = elastic_version -%}
{% set tarball = 'elasticsearch-%s.tar.gz' % elastic_version -%}
Expand All @@ -16,18 +21,19 @@
{% set url_root = 'https://artifacts.elastic.co/downloads/elasticsearch' -%}
{% endif -%}

{# Use a centos base that has openjdk-1.8.0.b141 pre-installed and excluded from yum.conf,
until potential issues with build 144 have been troubleshooted #}
FROM docker.elastic.co/elasticsearch/centos-base:7.3-jvm141
LABEL maintainer "Elastic Docker Team <docker@elastic.co>"
################################################################################
# Build stage 0 `prep_es_files`:
# Extract elasticsearch artifact
# Install required plugins
# Set gid=0 and make group perms==owner perms
################################################################################

FROM docker.elastic.co/elasticsearch/centos-base:7.3-jvm141 AS prep_es_files

ENV ELASTIC_CONTAINER true
ENV PATH /usr/share/elasticsearch/bin:$PATH
ENV JAVA_HOME /usr/lib/jvm/jre-1.8.0-openjdk

RUN yum update -y && \
yum install -y java-1.8.0-openjdk-headless unzip wget which && \
yum clean all
RUN yum install -y unzip

RUN groupadd -g 1000 elasticsearch && \
adduser -u 1000 -g 1000 -d /usr/share/elasticsearch elasticsearch
Expand Down Expand Up @@ -69,62 +75,70 @@ RUN for PLUGIN in {{ ingest_plugins }}; do \
elasticsearch-plugin install --batch "$PLUGIN"; done
{%- endif %}

USER 0

{# A fair bit of duplication here, but making line breaks and '\' consistent
coupled with jinja2 conditionals is complicated.
-#}
COPY --chown=1000:0 elasticsearch.yml log4j2.properties config/

{% if image_flavor == 'oss' -%}
COPY elasticsearch.yml log4j2.properties config/
COPY bin/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
{% if image_flavor == 'platinum' -%}
COPY --chown=1000:0 certgen_instances.yml log4j2.properties config/
COPY --chown=1000:0 x-pack/log4j2.properties config/x-pack/
RUN echo 'xpack.license.self_generated.type: trial' >>config/elasticsearch.yml
RUN bin/x-pack/certgen -s -in config/certgen_instances.yml --out config/certs.zip && \
unzip -d config/x-pack/ config/certs.zip && \
rm config/certs.zip config/certgen_instances.yml

RUN chown elasticsearch:elasticsearch \
config/elasticsearch.yml \
config/log4j2.properties && \
chgrp -R 0 . /usr/local/bin/docker-entrypoint.sh && \
chmod -R g=u . && \
chmod g=u /etc/passwd && \
chmod 0775 /usr/local/bin/docker-entrypoint.sh
{% elif image_flavor == 'basic' -%}
COPY elasticsearch.yml log4j2.properties config/
RUN echo 'xpack.license.self_generated.type: basic' >>config/elasticsearch.yml
COPY x-pack/log4j2.properties config/x-pack/
COPY bin/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
{% endif -%}

# Openshift overrides USER and uses ones with randomly uid>1024 and gid=0
# Allow ES to run even with a different user
RUN chown elasticsearch:elasticsearch \
config/elasticsearch.yml \
config/log4j2.properties \
config/x-pack/log4j2.properties && \
chgrp -R 0 . /usr/local/bin/docker-entrypoint.sh && \
chmod -R g=u . && \
chmod g=u /etc/passwd && \
chmod 0775 /usr/local/bin/docker-entrypoint.sh
{% elif image_flavor == 'platinum' -%}
COPY elasticsearch.yml certgen_instances.yml log4j2.properties config/
COPY x-pack/log4j2.properties config/x-pack/
COPY bin/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
USER 0

RUN echo 'xpack.license.self_generated.type: trial' >>config/elasticsearch.yml
# Set gid to 0 for elasticsearch and make group permission similar to that of user
# This is needed, for example, for Openshift Open: https://docs.openshift.org/latest/creating_images/guidelines.html
# and allows ES to run with an uid
RUN chown -R elasticsearch:0 . && \
chmod -R g=u /usr/share/elasticsearch

################################################################################
# Build stage 1 (the actual elasticsearch image):
# Copy elasticsearch from stage 0
# Add entrypoint
################################################################################

RUN chown elasticsearch:elasticsearch \
config/certgen_instances.yml \
config/elasticsearch.yml \
config/log4j2.properties \
config/x-pack/log4j2.properties && \
chgrp -R 0 . /usr/local/bin/docker-entrypoint.sh && \
chmod -R g=u . && \
# Use a centos base that has openjdk-1.8.0.b141 pre-installed and excluded from yum.conf
# until potential issues with build 144 have been troubleshooted
FROM docker.elastic.co/elasticsearch/centos-base:7.3-jvm141
LABEL maintainer "Elastic Docker Team <docker@elastic.co>"

ENV ELASTIC_CONTAINER true
ENV PATH /usr/share/elasticsearch/bin:$PATH
ENV JAVA_HOME /usr/lib/jvm/jre-1.8.0-openjdk

RUN yum update -y && \
yum install -y java-1.8.0-openjdk-headless unzip wget which && \
yum clean all

RUN groupadd -g 1000 elasticsearch && \
adduser -u 1000 -g 1000 -G 0 -d /usr/share/elasticsearch elasticsearch && \
chmod 0775 /usr/share/elasticsearch && \
chgrp 0 /usr/share/elasticsearch

WORKDIR /usr/share/elasticsearch

COPY --from=prep_es_files --chown=1000:0 /usr/share/elasticsearch /usr/share/elasticsearch

COPY --chown=1000:0 bin/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh

# Openshift overrides USER and uses ones with randomly uid>1024 and gid=0
# Allow ENTRYPOINT (and ES) to run even with a different user
RUN chgrp 0 /usr/local/bin/docker-entrypoint.sh && \
chmod g=u /etc/passwd && \
chmod 0775 /usr/local/bin/docker-entrypoint.sh

RUN bin/x-pack/certgen -s -in config/certgen_instances.yml --out config/certs.zip && \
unzip -d config/x-pack/ config/certs.zip && \
rm config/certs.zip config/certgen_instances.yml
{% endif %}

EXPOSE 9200 9300

ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
# Dummy overridable parameter parsed by entrypoint
CMD ["eswrapper"]

################################################################################
# End of multi-stage Dockerfile
################################################################################

0 comments on commit 0440fa0

Please sign in to comment.