Skip to content
Closed
Show file tree
Hide file tree
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
43 changes: 30 additions & 13 deletions test/convert.bats
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,14 @@ EOF

@test "alpine" {
skip_slow_test
git clone https://github.com/alpinelinux/docker-alpine.git
chmod -R a+rwx docker-alpine
cd docker-alpine
# https://raw.githubusercontent.com/alpinelinux/docker-alpine/refs/heads/master/Dockerfile
cat > Dockerfile << EOF
FROM alpine:3.16
RUN apk add --no-cache lua5.3 lua-filesystem lua-lyaml lua-http
COPY fetch-latest-releases.lua /usr/local/bin
VOLUME /out
ENTRYPOINT [ "/usr/local/bin/fetch-latest-releases.lua" ]
EOF
TEMPDIR=$(mktemp -d)
stacker convert --docker-file Dockerfile --output-file stacker.yaml --substitute-file stacker-subs.yaml
stacker build -f stacker.yaml --substitute-file stacker-subs.yaml --substitute IMAGE=alpine --substitute STACKER_VOL1="$TEMPDIR"
Expand All @@ -72,26 +77,38 @@ EOF

@test "elasticsearch" {
skip_slow_test
git clone --branch v8.17.10 --depth 1 https://github.com/elastic/dockerfiles.git
chmod -R a+rwx dockerfiles
cd dockerfiles/elasticsearch
stacker convert --docker-file Dockerfile --output-file stacker.yaml --substitute-file stacker-subs.yaml
# https://github.com/elastic/dockerfiles/archive/refs/tags/v8.17.10.tar.gz
# SHA256SUM=75f89195b53c9d02d6a45d2bc9d51a11d92b079dcc046893615b04455269ba1a dockerfiles-8.17.10/elasticsearch/Dockerfile
DOCKERFILE="elasticsearch-8.17.10.Dockerfile"

# copy data file into TEST_TMPDIR
import_test_data_file "${DOCKERFILE}"
DOCKERFILE=${TEST_TMPDIR}/${DOCKERFILE}

stacker convert --docker-file $DOCKERFILE --output-file stacker.yaml --substitute-file stacker-subs.yaml
stacker build -f stacker.yaml --substitute-file stacker-subs.yaml --substitute IMAGE=elasticsearch
if [ -nz "${REGISTRY_URL}" ]; then
stacker publish -f stacker.yaml --substitute-file stacker-subs.yaml --substitute IMAGE=elasticsearch --skip-tls --url docker://${REGISTRY_URL} --image elasticsearch --tag latest
fi
rm -f stacker.yaml stacker-subs.yaml
stacker clean
}

@test "python" {
skip_slow_test
git clone https://github.com/docker-library/python.git
cd python
# git clone https://github.com/docker-library/python.git
# cd python
# pick a specific commit so we don't get broken by upstream changes:
git reset --hard aad39d215779f27b410b25f612b6680a75781edb
cd 3.11/alpine3.22
chmod -R a+rw .
stacker convert --docker-file Dockerfile --output-file stacker.yaml --substitute-file stacker-subs.yaml
# git reset --hard aad39d215779f27b410b25f612b6680a75781edb
# cd 3.11/alpine3.22
# SHA256SUM=ada7a604a8359de5914158bca13f539ea24c13d8a3492f511a68444a511a1db8 data/python-3.11-alpine-3.22-Dockerfile
DOCKERFILE="python-3.11-alpine-3.22-Dockerfile"

# copy data file into TEST_TMPDIR
import_test_data_file "${DOCKERFILE}"
DOCKERFILE=${TEST_TMPDIR}/${DOCKERFILE}

stacker convert --docker-file $DOCKERFILE --output-file stacker.yaml --substitute-file stacker-subs.yaml
stacker build -f stacker.yaml --substitute-file stacker-subs.yaml --substitute IMAGE=python
if [ -nz "${REGISTRY_URL}" ]; then
stacker publish -f stacker.yaml --substitute-file stacker-subs.yaml --substitute IMAGE=python --skip-tls --url docker://${REGISTRY_URL} --image python --tag latest
Expand Down
171 changes: 171 additions & 0 deletions test/data/elasticsearch-8.17.10.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
################################################################################
# This Dockerfile was generated from the template at distribution/src/docker/Dockerfile
#
# Beginning of multi stage Dockerfile
################################################################################

################################################################################
# Build stage 1 `builder`:
# Extract Elasticsearch artifact
################################################################################

FROM ubuntu:24.04 AS builder

# Install required packages to extract the Elasticsearch distribution

RUN for iter in 1 2 3 4 5 6 7 8 9 10; do \
apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y curl && \
exit_code=0 && break || \
exit_code=$? && echo "apt-get error: retry $iter in 10s" && sleep 10; \
done; \
exit $exit_code

# `tini` is a tiny but valid init for containers. This is used to cleanly
# control how ES and any child processes are shut down.
# For wolfi we pick it from the blessed wolfi package registry.
#
# 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 -eux ; \
tini_bin="" ; \
case "$(arch)" in \
aarch64) tini_bin='tini-arm64' ;; \
x86_64) tini_bin='tini-amd64' ;; \
*) echo >&2 ; echo >&2 "Unsupported architecture $(arch)" ; echo >&2 ; 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} /bin/tini ; \
chmod 0555 /bin/tini

RUN mkdir /usr/share/elasticsearch
WORKDIR /usr/share/elasticsearch

RUN curl --retry 10 -S -L --output /tmp/elasticsearch.tar.gz https://artifacts-no-kpi.elastic.co/downloads/elasticsearch/elasticsearch-8.17.10-linux-$(arch).tar.gz

RUN tar -zxf /tmp/elasticsearch.tar.gz --strip-components=1

# The distribution includes a `config` directory, no need to create it
COPY config/elasticsearch.yml config/
COPY config/log4j2.properties config/log4j2.docker.properties

# 1. Configure the distribution for Docker
# 2. Create required directory
# 3. Move the distribution's default logging config aside
# 4. Move the generated docker logging config so that it is the default
# 5. Reset permissions on all directories
# 6. Reset permissions on all files
# 7. Make CLI tools executable
# 8. Make some directories writable. `bin` must be writable because
# plugins can install their own CLI utilities.
# 9. Make some files writable
RUN sed -i -e 's/ES_DISTRIBUTION_TYPE=tar/ES_DISTRIBUTION_TYPE=docker/' bin/elasticsearch-env && \
mkdir data && \
mv config/log4j2.properties config/log4j2.file.properties && \
mv config/log4j2.docker.properties config/log4j2.properties && \
find . -type d -exec chmod 0555 {} + && \
find . -type f -exec chmod 0444 {} + && \
chmod 0555 bin/* jdk/bin/* jdk/lib/jspawnhelper modules/x-pack-ml/platform/linux-*/bin/* && \
chmod 0775 bin config config/jvm.options.d data logs plugins && \
find config -type f -exec chmod 0664 {} +

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

FROM ubuntu:24.04

# Change default shell to bash, then install required packages with retries.
RUN yes no | dpkg-reconfigure dash && \
for iter in 1 2 3 4 5 6 7 8 9 10; do \
export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
apt-get upgrade -y && \
apt-get install -y --no-install-recommends \
ca-certificates curl netcat-openbsd p11-kit unzip zip && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
exit_code=0 && break || \
exit_code=$? && echo "apt-get error: retry $iter in 10s" && sleep 10; \
done; \
exit $exit_code

RUN userdel -r ubuntu && \
groupadd -g 1000 elasticsearch && \
useradd --uid 1000 --gid 1000 --home-dir /usr/share/elasticsearch --create-home elasticsearch && \
usermod -aG root elasticsearch && \
chown -R 0:0 /usr/share/elasticsearch

ENV ELASTIC_CONTAINER true

WORKDIR /usr/share/elasticsearch

COPY --from=builder --chown=0:0 /usr/share/elasticsearch /usr/share/elasticsearch

COPY --from=builder --chown=0:0 /bin/tini /bin/tini

ENV PATH /usr/share/elasticsearch/bin:$PATH
ENV SHELL /bin/bash
COPY bin/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh

# 1. Sync the user and group permissions of /etc/passwd
# 2. Set correct permissions of the entrypoint
# 3. Ensure that there are no files with setuid or setgid, in order to mitigate "stackclash" attacks.
# We've already run this in previous layers so it ought to be a no-op.
# 4. Replace OpenJDK's built-in CA certificate keystore with the one from the OS
# vendor. The latter is superior in several ways.
# REF: https://github.com/elastic/elasticsearch-docker/issues/171
# 5. Tighten up permissions on the ES home dir (the permissions of the contents are handled earlier)
# 6. You can't install plugins that include configuration when running as `elasticsearch` and the `config`
# dir is owned by `root`, because the installed tries to manipulate the permissions on the plugin's
# config directory.
RUN chmod g=u /etc/passwd && \
chmod 0555 /usr/local/bin/docker-entrypoint.sh && \
find / -xdev -perm -4000 -exec chmod ug-s {} + && \
chmod 0775 /usr/share/elasticsearch && \
chown elasticsearch bin config config/jvm.options.d data logs plugins

# Update "cacerts" bundle to use Ubuntu's CA certificates (and make sure it
# stays up-to-date with changes to Ubuntu's store)
COPY bin/docker-openjdk /etc/ca-certificates/update.d/docker-openjdk
RUN /etc/ca-certificates/update.d/docker-openjdk

EXPOSE 9200 9300

LABEL org.label-schema.build-date="2025-08-08T08:36:52.872377389Z" \
org.label-schema.license="Elastic-License-2.0" \
org.label-schema.name="Elasticsearch" \
org.label-schema.schema-version="1.0" \
org.label-schema.url="https://www.elastic.co/products/elasticsearch" \
org.label-schema.usage="https://www.elastic.co/guide/en/elasticsearch/reference/index.html" \
org.label-schema.vcs-ref="e5c4b2af120c131ea2885730f6693cb7d40a0a63" \
org.label-schema.vcs-url="https://github.com/elastic/elasticsearch" \
org.label-schema.vendor="Elastic" \
org.label-schema.version="8.17.10" \
org.opencontainers.image.created="2025-08-08T08:36:52.872377389Z" \
org.opencontainers.image.documentation="https://www.elastic.co/guide/en/elasticsearch/reference/index.html" \
org.opencontainers.image.licenses="Elastic-License-2.0" \
org.opencontainers.image.revision="e5c4b2af120c131ea2885730f6693cb7d40a0a63" \
org.opencontainers.image.source="https://github.com/elastic/elasticsearch" \
org.opencontainers.image.title="Elasticsearch" \
org.opencontainers.image.url="https://www.elastic.co/products/elasticsearch" \
org.opencontainers.image.vendor="Elastic" \
org.opencontainers.image.version="8.17.10"

# 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"]

USER 1000:0

################################################################################
# End of multi-stage Dockerfile
################################################################################
140 changes: 140 additions & 0 deletions test/data/python-3.11-alpine-3.22-Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#
# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh"
#
# PLEASE DO NOT EDIT IT DIRECTLY.
#

FROM alpine:3.22

# ensure local python is preferred over distribution python
ENV PATH /usr/local/bin:$PATH

# cannot remove LANG even though https://bugs.python.org/issue19846 is fixed
# last attempted removal of LANG broke many users:
# https://github.com/docker-library/python/pull/570
ENV LANG C.UTF-8

# runtime dependencies
RUN set -eux; \
apk add --no-cache \
ca-certificates \
tzdata \
;

ENV GPG_KEY A035C8C19219BA821ECEA86B64E628F8D684696D
ENV PYTHON_VERSION 3.11.14
ENV PYTHON_SHA256 8d3ed8ec5c88c1c95f5e558612a725450d2452813ddad5e58fdb1a53b1209b78

RUN set -eux; \
\
apk add --no-cache --virtual .build-deps \
bluez-dev \
bzip2-dev \
dpkg-dev dpkg \
findutils \
gcc \
gdbm-dev \
gnupg \
libc-dev \
libffi-dev \
libnsl-dev \
libtirpc-dev \
linux-headers \
make \
ncurses-dev \
openssl-dev \
pax-utils \
readline-dev \
sqlite-dev \
tar \
tcl-dev \
tk \
tk-dev \
util-linux-dev \
xz \
xz-dev \
zlib-dev \
; \
\
wget -O python.tar.xz "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz"; \
echo "$PYTHON_SHA256 *python.tar.xz" | sha256sum -c -; \
wget -O python.tar.xz.asc "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc"; \
GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; \
gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$GPG_KEY"; \
gpg --batch --verify python.tar.xz.asc python.tar.xz; \
gpgconf --kill all; \
rm -rf "$GNUPGHOME" python.tar.xz.asc; \
mkdir -p /usr/src/python; \
tar --extract --directory /usr/src/python --strip-components=1 --file python.tar.xz; \
rm python.tar.xz; \
\
cd /usr/src/python; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--enable-loadable-sqlite-extensions \
--enable-option-checking=fatal \
--enable-shared \
$(test "${gnuArch%%-*}" != 'riscv64' && echo '--with-lto') \
--with-ensurepip \
; \
nproc="$(nproc)"; \
# set thread stack size to 1MB so we don't segfault before we hit sys.getrecursionlimit()
# https://github.com/alpinelinux/aports/commit/2026e1259422d4e0cf92391ca2d3844356c649d0
EXTRA_CFLAGS="-DTHREAD_STACK_SIZE=0x100000"; \
LDFLAGS="${LDFLAGS:--Wl},--strip-all"; \
make -j "$nproc" \
"EXTRA_CFLAGS=${EXTRA_CFLAGS:-}" \
"LDFLAGS=${LDFLAGS:-}" \
; \
# https://github.com/docker-library/python/issues/784
# prevent accidental usage of a system installed libpython of the same version
rm python; \
make -j "$nproc" \
"EXTRA_CFLAGS=${EXTRA_CFLAGS:-}" \
"LDFLAGS=${LDFLAGS:--Wl},-rpath='\$\$ORIGIN/../lib'" \
python \
; \
make install; \
\
cd /; \
rm -rf /usr/src/python; \
\
find /usr/local -depth \
\( \
\( -type d -a \( -name test -o -name tests -o -name idle_test \) \) \
-o \( -type f -a \( -name '*.pyc' -o -name '*.pyo' -o -name 'libpython*.a' \) \) \
\) -exec rm -rf '{}' + \
; \
\
find /usr/local -type f -executable -not \( -name '*tkinter*' \) -exec scanelf --needed --nobanner --format '%n#p' '{}' ';' \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
| xargs -rt apk add --no-network --virtual .python-rundeps \
; \
apk del --no-network .build-deps; \
\
export PYTHONDONTWRITEBYTECODE=1; \
python3 --version; \
\
pip3 install \
--disable-pip-version-check \
--no-cache-dir \
--no-compile \
'setuptools==79.0.1' \
# https://github.com/docker-library/python/issues/1023
'wheel<0.46' \
; \
pip3 --version

# make some useful symlinks that are expected to exist ("/usr/local/bin/python" and friends)
RUN set -eux; \
for src in idle3 pip3 pydoc3 python3 python3-config; do \
dst="$(echo "$src" | tr -d 3)"; \
[ -s "/usr/local/bin/$src" ]; \
[ ! -e "/usr/local/bin/$dst" ]; \
ln -svT "$src" "/usr/local/bin/$dst"; \
done

CMD ["python3"]
10 changes: 10 additions & 0 deletions test/helpers.bash
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ if [ "$(id -u)" != "0" ]; then
exit 1
fi

function import_test_data_file() {
export TEST_TMPDIR=$(tmpd $BATS_TEST_NAME)
cd $TEST_TMPDIR

if ! cp "${ROOT_DIR}/test/data/${1}" .; then
echo "Failed to import ${ROOT}/test/data/${1} to $TEST_TMPDIR";
exit 1
fi
}

function give_user_ownership() {
if [ "$PRIVILEGE_LEVEL" = "priv" ]; then
return
Expand Down
Loading