mirror of
https://github.com/pgsty/minio.git
synced 2026-08-09 07:43:29 +03:00
build(docker): ship the silo binary and translate the legacy argv command
Dockerfile.goreleaser now copies silo to /usr/bin/silo, defaults to CMD ["silo"], and labels the image as Silo. MINIO_UPDATE_MINISIGN_PUBKEY is removed from the image environment: with the updater permanently disabled it was dead weight, and leaving upstream's verification key in a Silo image implied a trust relationship that does not exist. The MINIO_* runtime environment variables, ports, volume and health endpoints are unchanged. The image keeps shipping mcli with an /usr/bin/mc symlink. That is the client, not a MinIO-branded alias for the server binary, and the Helm post-install job and existing container scripts call it by name. docker-entrypoint.sh translates a legacy first argument: `minio server /data` becomes `silo server /data`, so an existing `command: minio server ...` in compose or a Pod spec keeps working across the image swap. The translation is argv-level only - no file named minio is installed, and an explicitly overridden `entrypoint: /usr/bin/minio` still fails, which is the honest outcome since that path genuinely no longer exists. The entrypoint also fixes an unrelated startup hazard it was already carrying: when the image runs under an arbitrary UID, HOME points at an unreadable /root and the server probes its default config directory during initialization. It now falls back to /tmp when HOME is unset, /root, missing or unwritable. docker-entrypoint_test.sh pins all of it - empty argv, legacy minio, native silo, bare flags, and an explicit shell command that must stay explicit. It is wired into make rebrand-guard and into the go.yml, release.yml and test-release.yml gates, so removing the shim breaks CI rather than breaking users. Passing locally. download-static-curl.sh gains checksum verification for the curl it fetches into the build stage. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+17
-10
@@ -6,7 +6,9 @@ ENV GOPATH=/go
|
|||||||
ENV CGO_ENABLED=0
|
ENV CGO_ENABLED=0
|
||||||
|
|
||||||
ARG MC_REPO=pgsty/mc
|
ARG MC_REPO=pgsty/mc
|
||||||
ARG MC_VERSION=latest
|
ARG MC_VERSION=RELEASE.2026-08-04T00-00-00Z
|
||||||
|
ARG MC_AMD64_SHA256=4aa1fa83ea153025a3f60684e13f453749dd17587257ccb7f0dde42b560120be
|
||||||
|
ARG MC_ARM64_SHA256=18f7bd442aec24c5eb5ffd1ef368eb44f94045e2da109a344ad184f34641e273
|
||||||
|
|
||||||
RUN apk add -U --no-cache \
|
RUN apk add -U --no-cache \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
@@ -14,8 +16,8 @@ RUN apk add -U --no-cache \
|
|||||||
curl \
|
curl \
|
||||||
jq && \
|
jq && \
|
||||||
case "${TARGETARCH}" in \
|
case "${TARGETARCH}" in \
|
||||||
amd64) MC_ARCH=amd64 ;; \
|
amd64) MC_ARCH=amd64; MC_PINNED_SHA256="${MC_AMD64_SHA256}" ;; \
|
||||||
arm64) MC_ARCH=arm64 ;; \
|
arm64) MC_ARCH=arm64; MC_PINNED_SHA256="${MC_ARM64_SHA256}" ;; \
|
||||||
*) echo "Unsupported TARGETARCH=${TARGETARCH}"; exit 1 ;; \
|
*) echo "Unsupported TARGETARCH=${TARGETARCH}"; exit 1 ;; \
|
||||||
esac && \
|
esac && \
|
||||||
if [ "${MC_VERSION}" = "latest" ]; then \
|
if [ "${MC_VERSION}" = "latest" ]; then \
|
||||||
@@ -39,7 +41,8 @@ RUN apk add -U --no-cache \
|
|||||||
EXPECTED=$(grep " ${ARCHIVE_NAME}$" /tmp/mcli_checksums.txt | awk '{print $1}') && \
|
EXPECTED=$(grep " ${ARCHIVE_NAME}$" /tmp/mcli_checksums.txt | awk '{print $1}') && \
|
||||||
ACTUAL=$(sha256sum /tmp/mcli.tar.gz | awk '{print $1}') && \
|
ACTUAL=$(sha256sum /tmp/mcli.tar.gz | awk '{print $1}') && \
|
||||||
[ -n "${EXPECTED}" ] || { echo "Checksum entry not found for ${ARCHIVE_NAME}"; exit 1; } && \
|
[ -n "${EXPECTED}" ] || { echo "Checksum entry not found for ${ARCHIVE_NAME}"; exit 1; } && \
|
||||||
[ "${EXPECTED}" = "${ACTUAL}" ] || { echo "Checksum mismatch: expected ${EXPECTED}, got ${ACTUAL}"; exit 1; } && \
|
[ "${EXPECTED}" = "${MC_PINNED_SHA256}" ] || { echo "Published checksum drift for ${ARCHIVE_NAME}"; exit 1; } && \
|
||||||
|
[ "${MC_PINNED_SHA256}" = "${ACTUAL}" ] || { echo "Checksum mismatch: expected ${MC_PINNED_SHA256}, got ${ACTUAL}"; exit 1; } && \
|
||||||
echo "Checksum OK: ${ACTUAL}" && \
|
echo "Checksum OK: ${ACTUAL}" && \
|
||||||
mkdir -p /tmp/mcli-extract && \
|
mkdir -p /tmp/mcli-extract && \
|
||||||
tar -xzf /tmp/mcli.tar.gz -C /tmp/mcli-extract/ && \
|
tar -xzf /tmp/mcli.tar.gz -C /tmp/mcli-extract/ && \
|
||||||
@@ -66,31 +69,35 @@ RUN dnf -y install ca-certificates && \
|
|||||||
|
|
||||||
FROM registry.access.redhat.com/ubi9/ubi-micro:latest
|
FROM registry.access.redhat.com/ubi9/ubi-micro:latest
|
||||||
|
|
||||||
LABEL maintainer="pgsty <https://github.com/pgsty/minio>" \
|
LABEL org.opencontainers.image.title="Silo" \
|
||||||
description="MinIO community fork, build by pgsty"
|
org.opencontainers.image.description="S3-Interface Libre Object Storage" \
|
||||||
|
org.opencontainers.image.url="https://silo.pgsty.com" \
|
||||||
|
org.opencontainers.image.source="https://github.com/pgsty/minio" \
|
||||||
|
org.opencontainers.image.licenses="AGPL-3.0-or-later" \
|
||||||
|
maintainer="PGSTY <https://silo.pgsty.com>"
|
||||||
|
|
||||||
ENV MINIO_ACCESS_KEY_FILE=access_key \
|
ENV MINIO_ACCESS_KEY_FILE=access_key \
|
||||||
MINIO_SECRET_KEY_FILE=secret_key \
|
MINIO_SECRET_KEY_FILE=secret_key \
|
||||||
MINIO_ROOT_USER_FILE=access_key \
|
MINIO_ROOT_USER_FILE=access_key \
|
||||||
MINIO_ROOT_PASSWORD_FILE=secret_key \
|
MINIO_ROOT_PASSWORD_FILE=secret_key \
|
||||||
MINIO_KMS_SECRET_KEY_FILE=kms_master_key \
|
MINIO_KMS_SECRET_KEY_FILE=kms_master_key \
|
||||||
MINIO_UPDATE_MINISIGN_PUBKEY="RWTx5Zr1tiHQLwG9keckT0c45M3AGeHD6IvimQHpyRywVWGbP1aVSGav" \
|
|
||||||
MINIO_CONFIG_ENV_FILE=config.env \
|
MINIO_CONFIG_ENV_FILE=config.env \
|
||||||
|
HOME=/tmp \
|
||||||
MC_CONFIG_DIR=/tmp/.mc
|
MC_CONFIG_DIR=/tmp/.mc
|
||||||
|
|
||||||
COPY --from=certs /tmp/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
COPY --from=certs /tmp/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||||
COPY minio /usr/bin/minio
|
COPY silo /usr/bin/silo
|
||||||
COPY --from=build /go/bin/mcli /usr/bin/mcli
|
COPY --from=build /go/bin/mcli /usr/bin/mcli
|
||||||
COPY --from=build /go/bin/curl* /usr/bin/
|
COPY --from=build /go/bin/curl* /usr/bin/
|
||||||
COPY dockerscripts/docker-entrypoint.sh /usr/bin/docker-entrypoint.sh
|
COPY dockerscripts/docker-entrypoint.sh /usr/bin/docker-entrypoint.sh
|
||||||
COPY LICENSE /licenses/LICENSE
|
COPY LICENSE /licenses/LICENSE
|
||||||
COPY CREDITS /licenses/CREDITS
|
COPY CREDITS /licenses/CREDITS
|
||||||
|
|
||||||
RUN chmod +x /usr/bin/minio /usr/bin/mcli /usr/bin/docker-entrypoint.sh && \
|
RUN chmod +x /usr/bin/silo /usr/bin/mcli /usr/bin/docker-entrypoint.sh && \
|
||||||
ln -sf mcli /usr/bin/mc
|
ln -sf mcli /usr/bin/mc
|
||||||
|
|
||||||
EXPOSE 9000
|
EXPOSE 9000
|
||||||
VOLUME ["/data"]
|
VOLUME ["/data"]
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"]
|
ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"]
|
||||||
CMD ["minio"]
|
CMD ["silo"]
|
||||||
|
|||||||
@@ -1,21 +1,43 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
|
|
||||||
# If command starts with an option, prepend minio.
|
# Run Silo by default, while translating the legacy argv-level command name.
|
||||||
if [ "${1}" != "minio" ]; then
|
# An explicitly supplied shell or utility remains an explicit entrypoint command.
|
||||||
if [ -n "${1}" ]; then
|
case "${1:-}" in
|
||||||
set -- minio "$@"
|
"")
|
||||||
fi
|
set -- silo
|
||||||
|
;;
|
||||||
|
minio)
|
||||||
|
shift
|
||||||
|
set -- silo "$@"
|
||||||
|
;;
|
||||||
|
silo)
|
||||||
|
;;
|
||||||
|
-*|server|fmt-gen)
|
||||||
|
set -- silo "$@"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ensure_writable_home() {
|
||||||
|
# The image is commonly run with an arbitrary UID or with the legacy
|
||||||
|
# MINIO_USERNAME drop-user path. Do not leave those processes pointing at
|
||||||
|
# root's inaccessible home: Silo probes its default configuration directory
|
||||||
|
# during process initialization.
|
||||||
|
if [ -z "${HOME:-}" ] || [ "${HOME}" = /root ] || [ ! -d "${HOME}" ] || [ ! -w "${HOME}" ]; then
|
||||||
|
HOME=/tmp
|
||||||
|
export HOME
|
||||||
fi
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
docker_switch_user() {
|
docker_switch_user() {
|
||||||
|
ensure_writable_home
|
||||||
if [ -n "${MINIO_USERNAME}" ] && [ -n "${MINIO_GROUPNAME}" ]; then
|
if [ -n "${MINIO_USERNAME}" ] && [ -n "${MINIO_GROUPNAME}" ]; then
|
||||||
if [ -n "${MINIO_UID}" ] && [ -n "${MINIO_GID}" ]; then
|
if [ -n "${MINIO_UID}" ] && [ -n "${MINIO_GID}" ]; then
|
||||||
exec chroot --userspec=${MINIO_UID}:${MINIO_GID} / "$@"
|
exec chroot --userspec="${MINIO_UID}:${MINIO_GID}" / "$@"
|
||||||
else
|
else
|
||||||
echo "${MINIO_USERNAME}:x:1000:1000:${MINIO_USERNAME}:/:/sbin/nologin" >>/etc/passwd
|
echo "${MINIO_USERNAME}:x:1000:1000:${MINIO_USERNAME}:/:/sbin/nologin" >>/etc/passwd
|
||||||
echo "${MINIO_GROUPNAME}:x:1000" >>/etc/group
|
echo "${MINIO_GROUPNAME}:x:1000" >>/etc/group
|
||||||
exec chroot --userspec=${MINIO_USERNAME}:${MINIO_GROUPNAME} / "$@"
|
exec chroot --userspec="${MINIO_USERNAME}:${MINIO_GROUPNAME}" / "$@"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|||||||
Executable
+75
@@ -0,0 +1,75 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
work_dir="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "${work_dir}"' EXIT
|
||||||
|
|
||||||
|
mkdir -p "${work_dir}/bin"
|
||||||
|
cat >"${work_dir}/bin/silo" <<'EOF'
|
||||||
|
#!/bin/sh
|
||||||
|
printf '%s\n' silo "$@" >"${ENTRYPOINT_CAPTURE}"
|
||||||
|
if [ -n "${ENTRYPOINT_HOME_CAPTURE:-}" ]; then
|
||||||
|
printf '%s\n' "${HOME:-}" >"${ENTRYPOINT_HOME_CAPTURE}"
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
chmod +x "${work_dir}/bin/silo"
|
||||||
|
|
||||||
|
cat >"${work_dir}/bin/chroot" <<'EOF'
|
||||||
|
#!/bin/sh
|
||||||
|
printf '%s\n' "$1" "$2" >"${ENTRYPOINT_CHROOT_CAPTURE}"
|
||||||
|
shift 2
|
||||||
|
exec "$@"
|
||||||
|
EOF
|
||||||
|
chmod +x "${work_dir}/bin/chroot"
|
||||||
|
|
||||||
|
run_case() {
|
||||||
|
local name="$1"
|
||||||
|
local expected="$2"
|
||||||
|
shift 2
|
||||||
|
local capture="${work_dir}/${name}.actual"
|
||||||
|
local expected_file="${work_dir}/${name}.expected"
|
||||||
|
|
||||||
|
ENTRYPOINT_CAPTURE="${capture}" PATH="${work_dir}/bin:${PATH}" \
|
||||||
|
"${script_dir}/docker-entrypoint.sh" "$@"
|
||||||
|
printf '%s' "${expected}" >"${expected_file}"
|
||||||
|
diff -u "${expected_file}" "${capture}"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_case default $'silo\n'
|
||||||
|
run_case server $'silo\nserver\n/data\n' server /data
|
||||||
|
run_case option $'silo\n--version\n' --version
|
||||||
|
run_case explicit-silo $'silo\nserver\n/data\n' silo server /data
|
||||||
|
run_case legacy-minio $'silo\nserver\n/data\n' minio server /data
|
||||||
|
|
||||||
|
shell_capture="${work_dir}/shell.actual"
|
||||||
|
# shellcheck disable=SC2016 # ENTRYPOINT_CAPTURE is expanded by the child shell.
|
||||||
|
ENTRYPOINT_CAPTURE="${shell_capture}" PATH="${work_dir}/bin:${PATH}" \
|
||||||
|
"${script_dir}/docker-entrypoint.sh" sh -c 'printf "%s\n" shell >"${ENTRYPOINT_CAPTURE}"'
|
||||||
|
test "$(cat "${shell_capture}")" = shell
|
||||||
|
|
||||||
|
rootless_capture="${work_dir}/rootless.actual"
|
||||||
|
rootless_home_capture="${work_dir}/rootless-home.actual"
|
||||||
|
rootless_chroot_capture="${work_dir}/rootless-chroot.actual"
|
||||||
|
ENTRYPOINT_CAPTURE="${rootless_capture}" \
|
||||||
|
ENTRYPOINT_HOME_CAPTURE="${rootless_home_capture}" \
|
||||||
|
ENTRYPOINT_CHROOT_CAPTURE="${rootless_chroot_capture}" \
|
||||||
|
HOME=/root MINIO_USERNAME=silo-user MINIO_GROUPNAME=silo-group \
|
||||||
|
MINIO_UID=1001 MINIO_GID=1002 PATH="${work_dir}/bin:${PATH}" \
|
||||||
|
"${script_dir}/docker-entrypoint.sh" silo --version
|
||||||
|
test "$(cat "${rootless_home_capture}")" = /tmp
|
||||||
|
test "$(sed -n '1p' "${rootless_chroot_capture}")" = --userspec=1001:1002
|
||||||
|
test "$(sed -n '2p' "${rootless_chroot_capture}")" = /
|
||||||
|
test "$(cat "${rootless_capture}")" = $'silo\n--version'
|
||||||
|
|
||||||
|
arbitrary_uid_capture="${work_dir}/arbitrary-uid.actual"
|
||||||
|
arbitrary_uid_home_capture="${work_dir}/arbitrary-uid-home.actual"
|
||||||
|
ENTRYPOINT_CAPTURE="${arbitrary_uid_capture}" \
|
||||||
|
ENTRYPOINT_HOME_CAPTURE="${arbitrary_uid_home_capture}" \
|
||||||
|
HOME="${work_dir}/missing-home" PATH="${work_dir}/bin:${PATH}" \
|
||||||
|
"${script_dir}/docker-entrypoint.sh" silo --version
|
||||||
|
test "$(cat "${arbitrary_uid_home_capture}")" = /tmp
|
||||||
|
test "$(cat "${arbitrary_uid_capture}")" = $'silo\n--version'
|
||||||
|
|
||||||
|
echo "docker entrypoint argv compatibility tests passed"
|
||||||
@@ -4,21 +4,23 @@
|
|||||||
# v8.17.0 (current latest) dropped the aarch64 build.
|
# v8.17.0 (current latest) dropped the aarch64 build.
|
||||||
STATIC_CURL_VERSION="v8.11.0"
|
STATIC_CURL_VERSION="v8.11.0"
|
||||||
|
|
||||||
function download_arch_specific_executable {
|
case ${TARGETARCH:?TARGETARCH is required} in
|
||||||
curl -f -L -s -q \
|
amd64)
|
||||||
"https://github.com/moparisthebest/static-curl/releases/download/${STATIC_CURL_VERSION}/curl-$1" \
|
asset=curl-amd64
|
||||||
-o /go/bin/curl || exit 1
|
expected=d18aa1f4e03b50b649491ca2c401cd8c5e89e72be91ff758952ad2ab5a83135d
|
||||||
chmod +x /go/bin/curl
|
|
||||||
}
|
|
||||||
|
|
||||||
case $TARGETARCH in
|
|
||||||
"arm64")
|
|
||||||
download_arch_specific_executable aarch64
|
|
||||||
;;
|
;;
|
||||||
"s390x")
|
arm64)
|
||||||
echo "Not downloading static cURL because it does not exist for the $TARGETARCH architecture."
|
asset=curl-aarch64
|
||||||
|
expected=1b050abd1669f9a2ac29b34eb022cdeafb271dce5a4fb57d8ef8fadff6d7be1f
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
download_arch_specific_executable "$TARGETARCH"
|
echo "Unsupported static cURL architecture: ${TARGETARCH}" >&2
|
||||||
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
curl --fail --location --silent --show-error --retry 3 \
|
||||||
|
"https://github.com/moparisthebest/static-curl/releases/download/${STATIC_CURL_VERSION}/${asset}" \
|
||||||
|
--output /go/bin/curl
|
||||||
|
printf '%s %s\n' "${expected}" /go/bin/curl | sha256sum -c
|
||||||
|
chmod +x /go/bin/curl
|
||||||
|
|||||||
Reference in New Issue
Block a user