From 1040212c01171cf94d8a04a95f6a9361dbdf48af Mon Sep 17 00:00:00 2001 From: Daniele Monti <62102073+Monska85@users.noreply.github.com> Date: Wed, 7 Aug 2024 13:22:17 +0200 Subject: [PATCH] refs platform/#2978: implement init filesystem and seed archives feature --- .gitignore | 6 ++ Dockerfile | 5 +- Makefile | 26 +++--- README.md | 114 ++++++++++++++++++++----- initarchives/.gitkeep | 0 initfilesystem/.gitkeep | 0 scripts/common.sh | 183 ++++++++++++++++++++++++++++++++++------ scripts/entrypoint.sh | 67 +++++++++++---- 8 files changed, 325 insertions(+), 76 deletions(-) create mode 100644 initarchives/.gitkeep create mode 100644 initfilesystem/.gitkeep diff --git a/.gitignore b/.gitignore index bbe99b2..6f5ff9f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,11 @@ +/initarchives/** +!/initarchives/.gitkeep /initfiles/** !/initfiles/.gitkeep +/initfilesystem/** +!/initfilesystem/.gitkeep + +/tmp # IDE files .idea diff --git a/Dockerfile b/Dockerfile index f2f188b..4ed9e24 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,8 @@ FROM alpine:3.20 -RUN apk add --no-cache minio minio-client bash date && \ - ln -fs /usr/bin/mcli /usr/bin/mc +RUN apk add --no-cache minio minio-client \ + bash date file rsync tar unzip xz \ + && ln -fs /usr/bin/mcli /usr/bin/mc # Copy scripts folder COPY scripts /scripts diff --git a/Makefile b/Makefile index 482791b..9f223c5 100644 --- a/Makefile +++ b/Makefile @@ -8,16 +8,8 @@ MINIO_ROOT_PASSWORD ?= minioadmin build: docker build -t $(IMAGE_NAME):$(IMAGE_TAG) . -cli: build - @docker run --rm -it \ - -e BUCKET_NAME=$(BUCKET_NAME) \ - -e MINIO_ROOT_USER=$(MINIO_ROOT_USER) \ - -e MINIO_ROOT_PASSWORD=$(MINIO_ROOT_PASSWORD) \ - --network host \ - $(IMAGE_NAME):$(IMAGE_TAG) mc ls minio/$(BUCKET_NAME) - start: build - @docker run \ + @docker run --rm \ -e BUCKET_NAME=$(BUCKET_NAME) \ -e MINIO_ROOT_USER=$(MINIO_ROOT_USER) \ -e MINIO_ROOT_PASSWORD=$(MINIO_ROOT_PASSWORD) \ @@ -25,9 +17,20 @@ start: build -e MINIO_VERSION_ENABLED=1 \ -p 9000:9000 \ -p 9001:9001 \ + -v ./initfilesystem:/docker-entrypoint-initfs.d \ + -v ./initarchives:/docker-entrypoint-initarchives.d \ -v ./initfiles:/docker-entrypoint-initfiles.d \ $(IMAGE_NAME):$(IMAGE_TAG) +mc: build + @docker run --rm -it \ + -e BUCKET_NAME=$(BUCKET_NAME) \ + -e MINIO_ROOT_USER=$(MINIO_ROOT_USER) \ + -e MINIO_ROOT_PASSWORD=$(MINIO_ROOT_PASSWORD) \ + --network host \ + --entrypoint bash \ + $(IMAGE_NAME):$(IMAGE_TAG) -ilc 'mc config host add minio http://localhost:9000 $(MINIO_ROOT_USER) $(MINIO_ROOT_PASSWORD) && bash -il' + aws-cli: @docker run --rm -it \ -e AWS_ACCESS_KEY_ID=$(MINIO_ROOT_USER) \ @@ -36,4 +39,7 @@ aws-cli: -e AWS_ENDPOINT_URL=http://localhost:9000 \ --network host \ --entrypoint bash \ - amazon/aws-cli -il \ No newline at end of file + amazon/aws-cli -il + +minio-console: + xdg-open http://localhost:9001 diff --git a/README.md b/README.md index 6a3e975..671fc4c 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,102 @@ # Docker MinIO -This is a simple docker image for running a minio server. It is based on alpine linux and uses the minio and minio-client packages from the alpine package repository. +This is a simple docker image for running a MinIO server. It is based on alpine linux and uses the `minio` and `minio-client` packages from the alpine package repository. -The `/scripts/entrypoint.sh` script is used to start the minio server. It is possible to configure the container to create and populate the new bucket at startup by setting the `BUCKET_NAME` environment variable and adding the seed files to the folder defined by the `INITFILES_FOLDER` environment variable. +The `/scripts/entrypoint.sh` script is used to start the MinIO server. It is possible to configure the container to create and populate the new bucket at startup by setting the `BUCKET_NAME` environment variable. + +## Bucket initialization + +**The bucket initialization is processed only if the bucket does not exist or is empty.** In any other case, the initialization is skipped. + +You can use two different methods to initialize the bucket: the `FileSystem` initialization and the `Seed` initialization. The two methods can be used together, and the `Seed` initialization is processed after the `FileSystem` initialization. + +The order of the initialization is the following: + +1. The `FileSystem` initialization is processed first, so the entire _MinIO filesystem structure_ is copied to the `BUCKET_ROOT` destination folder. +1. The `Seed` initialization is processed starting from the archives, so the archives are extracted and the files are uploaded in the bucket defined by the `BUCKET_NAME` environment variable. +1. The `Seed` initialization continues with the files, so the files in the `INITFILES_DIR` folder are uploaded in the bucket defined by the `BUCKET_NAME` environment variable. + +If the versioning is enabled, the newer files will overwrite the older files, and the previous versions are preserved. See the [Versioning enabled example](#versioning-enabled-example) for more details. + +## FileSystem initialization + +If the `INITFILESYSTEM_DIR` path is not empty, the files in the folder are copied to the `BUCKET_ROOT` destination folder as a startup filesystem for the MinIO server. **The folder must contain a valid MinIO filesystem structure.** **ATTENTION**: when the `INITFILESYSTEM_DIR` is used, the startup process takes care of checking that the `BUCKET_NAME` is configured accordingly with the final MinIO server configuration, performing the filesystem check (the `BUCKET_NAME` folder is present in the `BUCKET_ROOT` folder) and the MinIO client check (the `mc ls ${MC_ALIAS}/${BUCKET_NAME}` command does not return an error). + +## Seed initialization + +This initialization method is used to populate the bucket with **seed archives and files**. Both the archives and the files are processed at startup, and the resulting bucket content is the union of the archives and files content. + +The archives are processed first, and then the files. So, if the file with the same name is present in one or more archives and in the `INITFILES_DIR` folder, the file in the `INITFILES_DIR` will overwrite the files in the archives. If the bucket has a versioning enabled, the previous versions of the files are preserved. See the [Versioning enabled example](#versioning-enabled-example) for more details. + +If the `DO_NOT_PROCESS_INITFILES` environment variable is set to `1`, the seed archives and files are not processed at startup. + +### Process the seed archives + +If the `INITARCHIVES_DIR` path is not empty, the archives in the folder are extracted in a temporary folder and all the resulting files and folders are uploaded in the bucket defined by the `BUCKET_NAME` environment variable using the MinIO client (`mc cp --recursive`). The archives are extracted and files are uploaded sequentially in the alphabetical order of the filenames, using the output of the `ls -A ${INITARCHIVES_DIR}` command. So, if the archives contain the same files, the last archive extracted will overwrite the files extracted by the previous archives. If the bucket has a versioning enabled, the previous versions of the files are preserved. + +**The supported archive formats are `.zip`, `.tar`, `.tar.gz`, `.tar.bz2` and `.tar.xz`.** + +### Process the seed files + +If the `INITFILES_DIR` path is not empty, the files in the folder are uploaded in the bucket defined by the `BUCKET_NAME` environment variable using the MinIO client (`mc cp --recursive`). As for the archives, if the `INITFILES_DIR` contains files with the same name of one or more files already present in the bucket (processed by the `INITARCHIVES_DIR`), the files in the `INITFILES_DIR` will overwrite the files in the bucket. If the bucket has a versioning enabled, the previous versions of the files are preserved. + +## Versioning enabled example + +To be more clear, here is an example of the initialization process if the versioning is enabled: + +1. The `INITFILESYSTEM_DIR` populates the bucket with these files: + - `file1.txt` + - `file2.txt` +1. The `INITARCHIVES_DIR` contains the following archives: + - `archive1.zip` with the files `file2.txt`, `file3.txt` + - `archive2.tar.xz` with the files `file3.txt` and `file4.txt` +1. The `INITFILES_DIR` contains the following files: + - `file3.txt` + - `file4.txt` + - `file5.txt` + +The resulting bucket content will be: + +- `file1.txt`: + - single version, is the content of the `INITFILESYSTEM_DIR` _MinIO filesystem structure_. +- `file2.txt`: + - in the first version, is the content of the `INITFILESYSTEM_DIR` _MinIO filesystem structure_. + - in the current version, is the content of the `archive1.zip` file. +- `file3.txt`: + - in the first version, is the content of the `archive1.zip` file. + - in the second version, is the content of the `archive2.tar.xz` file. + - in the current version, is the content of the `INITFILES_DIR` file. +- `file4.txt`: + - in the first version, is the content of the `archive2.tar.xz` file. + - in the current version, is the content of the `INITFILES_DIR` file. +- `file5.txt`: + - single version, is the content of the `INITFILES_DIR` file. ## Environment Variables -| Variable | Description | Default | -| -------------------------- | ----------------------------------------------------------- | -------------------------------- | -| `BUCKET_NAME` | The name of the bucket to create and populate at startup. | `-` | -| `BUCKET_ROOT` | The folder used by the minio server to store the files. | `/data` | -| `INITFILES_FOLDER` | The folder where the seed files are stored. | `/docker-entrypoint-initfiles.d` | -| `DO_NOT_PROCESS_INITFILES` | If set to `1`, the seed files are not processed at startup. | `0` | -| `MINIO_VERSION_ENABLED` | If set to `1`, the minio version is enabled. | `0` | -| `MINIO_ROOT_USER` | The access key used to authenticate with the minio server. | `-` | -| `MINIO_ROOT_PASSWORD` | The secret key used to authenticate with the minio server. | `-` | -| `MINIO_BROWSER` | If set to `on`, the minio console is enabled. | `off` | -| `MINIO_CONSOLE_PORT` | The port used by the minio console. | `9001` | -| `MINIO_OPTS` | Additional options to pass to the minio server. | `-` | -| `MC_ALIAS` | The alias used by the minio client. | `minio` | -| `MINIO_PROTO` | The protocol used to connect to the minio server. | `http` | -| `MINIO_HOST` | The host used to connect to the minio server. | `localhost` | -| `MINIO_PORT` | The port used to connect to the minio server. | `9000` | +| Variable | Description | Default | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | +| `DEBUG` | If set to `1`, the script prints the debug information. | `0` | +| `BUCKET_NAME` | The name of the bucket to create and populate at startup. | `-` | +| `BUCKET_ROOT` | The folder used by the MinIO server to store the files. | `/data` | +| `INITFILESYSTEM_DIR` | The folder where the root init filesystem is stored. If not empty, the files are copied to the `BUCKET_ROOT` folder. | `/docker-entrypoint-initfs.d` | +| `INITARCHIVES_DIR` | The folder where the seed archives are stored. | `/docker-entrypoint-initarchives.d` | +| `INITFILES_DIR` | The folder where the seed files are stored. | `/docker-entrypoint-initfiles.d` | +| `DO_NOT_PROCESS_INITFILES` | If set to `1`, the seed archives and files are not processed at startup. | `0` | +| `MINIO_ROOT_USER` | The access key used to authenticate with the MinIO server. | `-` | +| `MINIO_ROOT_PASSWORD` | The secret key used to authenticate with the MinIO server. | `-` | +| `MINIO_VERSION_ENABLED` | If set to `1`, the MinIO version is enabled. | `0` | +| `MINIO_OPTS` | Additional options to pass to the MinIO server. | `-` | +| `MINIO_BROWSER` | If set to `on`, the MinIO console is enabled. | `off` | +| `MINIO_CONSOLE_PORT` | The port used by the MinIO console. | `9001` | +| `MC_ALIAS` | The alias used by the MinIO client. | `minio` | +| `MINIO_PROTO` | The protocol used to connect to the MinIO server. | `http` | +| `MINIO_HOST` | The host used to connect to the MinIO server. | `localhost` | +| `MINIO_PORT` | The port used to connect to the MinIO server. | `9000` | ### Deprecated Variables -| Variable | Description | | ------------------ | ------------------------------------------------------------------------------------------------- | -| `OSB_BUCKET` | The name of the bucket to create and populate at startup. **Use `BUCKET_NAME` instead.** | -| `MINIO_ACCESS_KEY` | The access key used to authenticate with the minio server. **Use `MINIO_ROOT_USER` instead.** | -| `MINIO_SECRET_KEY` | The secret key used to authenticate with the minio server. **Use `MINIO_ROOT_PASSWORD` instead.** | +| `OSB_BUCKET` | The name of the bucket to create and populate at startup. **Use `BUCKET_NAME` instead.** | +| `MINIO_ACCESS_KEY` | The access key used to authenticate with the MinIO server. **Use `MINIO_ROOT_USER` instead.** | +| `MINIO_SECRET_KEY` | The secret key used to authenticate with the MinIO server. **Use `MINIO_ROOT_PASSWORD` instead.** | diff --git a/initarchives/.gitkeep b/initarchives/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/initfilesystem/.gitkeep b/initfilesystem/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/scripts/common.sh b/scripts/common.sh index 435b5d2..f1c30f9 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -1,17 +1,33 @@ # Helper functions for the entrypoint script. minio_start_temp_server() { + if [ -n "${MINIO_TEMP_PID}" ]; then + minio_log_debug "Temporary Minio server is already running (PID: ${MINIO_TEMP_PID})." + return + fi + # Start minio server. We need to start it to create the bucket and eventually upload files. - /usr/bin/minio server "${BUCKET_ROOT}" &>/dev/null & + exec /usr/bin/minio server "${BUCKET_ROOT}" &>/dev/null & MINIO_TEMP_PID=$! sleep 1 } minio_stop_temp_server() { if [ -z "${MINIO_TEMP_PID}" ]; then - minio_error "MINIO_TEMP_PID is not set." + minio_log_warn "MINIO_TEMP_PID is not set." + return fi + # Stop minio server. + minio_log_debug "Stopping temporary Minio server (PID: ${MINIO_TEMP_PID})." kill -9 "${MINIO_TEMP_PID}" + MINIO_TEMP_PID="" + minio_log_debug "Temporary Minio server has been stopped." +} + +minio_restart_temp_server() { + minio_log_debug "Restarting temporary Minio server." + mc admin service restart "${MC_ALIAS}" &>/dev/null + minio_log_debug "Temporary Minio server has been restarted." } minio_wait_for_readiness() { @@ -20,49 +36,156 @@ minio_wait_for_readiness() { TRESHOLD=10 while [ "${CNT}" -lt 10 ]; do if mc config host add "${MC_ALIAS}" "${MINIO_PROTO}://${MINIO_HOST}:${MINIO_PORT}" "${MINIO_ROOT_USER}" "${MINIO_ROOT_PASSWORD}" &>/dev/null && mc admin info "${MC_ALIAS}" &>/dev/null; then - minio_note "Minio server is ready." + minio_log_debug "Minio server is ready." return 0 fi - minio_note "Minio server is not ready. Waiting..." + minio_log_debug "Minio server is not ready. Waiting..." CNT=$((CNT + 1)) sleep 1 done - minio_error "Minio server is not ready in ${TRESHOLD} seconds." + minio_log_error "Minio server is not ready in ${TRESHOLD} seconds." +} + +minio_initialization_is_needed() { + if [ "$(mc ls "${MC_ALIAS}/${BUCKET_NAME}/" 2>/dev/null | wc -l)" -ne 0 ]; then + return 1 + fi + return 0 +} + +minio_process_init_filesystem() { + # Copy the contents of the initfs folder to the bucket root. + minio_log_note "Copying the contents of '${INITFILESYSTEM_DIR}' to '${BUCKET_ROOT}'." + minio_log_note "Please wait, this may take a while..." + rsync -a --delete "${INITFILESYSTEM_DIR}/" "${BUCKET_ROOT}/" + minio_log_note "The contents of '${INITFILESYSTEM_DIR}' have been copied to '${BUCKET_ROOT}'." } -docker_create_bucket() { +minio_check_initialized_filesystem() { + # Check if the configured BUCKET_NAME is consistent with the imported filesystem using filesystem folder name. + if [ ! -d "${BUCKET_ROOT}/${BUCKET_NAME}" ]; then + minio_log_error "The folder '${BUCKET_NAME}' does not exist in the filesystem. The init filesystem is not consistent with the BUCKET_NAME variable. Please configure the BUCKET_NAME variable to match the bucket present in the init filesystem." + fi + + # Check if the configured BUCKET_NAME is consistent with the imported filesystem using MinIO client. + if ! mc ls "${MC_ALIAS}/${BUCKET_NAME}" &>/dev/null; then + minio_log_error "The bucket '${BUCKET_NAME}' does not exist in the MinIO server. The init filesystem is not consistent with the BUCKET_NAME variable. Please configure the BUCKET_NAME variable to match the bucket present in the init filesystem." + fi + + minio_log_note "The init filesystem is consistent with the BUCKET_NAME variable." +} + +minio_create_bucket() { # Check if bucket exists, otherwise create it. if mc ls "${MC_ALIAS}/${BUCKET_NAME}" &>/dev/null; then - minio_note "Bucket '${BUCKET_NAME}' already exists." + minio_log_note "Bucket '${BUCKET_NAME}' already exists." else - minio_note "Creating bucket '${BUCKET_NAME}'." - mc mb -p "${MC_ALIAS}/${BUCKET_NAME}" | minio_note - mc anonymous set download "${MC_ALIAS}/${BUCKET_NAME}" | minio_note + mc mb -p "${MC_ALIAS}/${BUCKET_NAME}" | minio_log_note + minio_log_note "Bucket '${BUCKET_NAME}' created." fi + + # Set the bucket policy. + mc anonymous set download "${MC_ALIAS}/${BUCKET_NAME}" | minio_log_note + + # Enable versioning for the bucket if the MINIO_VERSION_ENABLED variable is set to 1. if [ "${MINIO_VERSION_ENABLED}" = "1" ]; then - mc version enable "${MC_ALIAS}/${BUCKET_NAME}" | minio_note + mc version enable "${MC_ALIAS}/${BUCKET_NAME}" | minio_log_note fi } -docker_process_init_files() { - if [ "$(mc ls "${MC_ALIAS}/${BUCKET_NAME}/" | wc -l)" -ne 0 ]; then - minio_note "Bucket '${BUCKET_NAME}' is not empty. Skipping initialization files." - return +minio_process_seed_archives_and_files() { + local SOMETHING_UPLOADED TMP_ARCHIVE_EXTRACTION_DIR LOGERR_FILE + SOMETHING_UPLOADED=0 + TMP_ARCHIVE_EXTRACTION_DIR="/tmp/archives" + LOGERR_FILE="/tmp/error.log" + + # Processing archives. + if [ "$(ls -A "${INITARCHIVES_DIR}" 2>/dev/null | wc -l)" -gt 0 ]; then + minio_log_note "Extracting seed archives and uploading files to bucket '${BUCKET_NAME}'." + + # Extract all archives in the temporary folder. + local archive + for archive in $(ls -A "${INITARCHIVES_DIR}"); do + # Clean up the temporary folder if it exists. + rm -rf "${TMP_ARCHIVE_EXTRACTION_DIR}" + # Create a temporary folder for archive extraction. + mkdir -p "${TMP_ARCHIVE_EXTRACTION_DIR}" + + # Check if the file is a zip archive. + if [ "$(file -b --mime-type "${INITARCHIVES_DIR}/${archive}")" = "application/zip" ]; then + minio_log_debug "Extracting archive '${INITARCHIVES_DIR}/${archive}' using unzip." + unzip -q "${INITARCHIVES_DIR}/${archive}" -d "${TMP_ARCHIVE_EXTRACTION_DIR}" 1>/dev/null + elif is_tar_valid_mime_type "${INITARCHIVES_DIR}/${archive}"; then + # Try to extract the archive using tar. + minio_log_debug "Extracting archive '${INITARCHIVES_DIR}/${archive}' using tar." + tar xf "${INITARCHIVES_DIR}/${archive}" -C "${TMP_ARCHIVE_EXTRACTION_DIR}" 1>/dev/null + else + minio_log_warn "Unsupported archive format '${INITARCHIVES_DIR}/${archive}'. Skipping extraction." + continue + fi + + # We want to upload the contents of each extracted archive to the bucket. + # This is useful when the bucket is configured to use versioning to keep track of the changes. + # Check if the temporary folder is empty. + if [ "$(ls -A "${TMP_ARCHIVE_EXTRACTION_DIR}" 2>/dev/null | wc -l)" -eq 0 ]; then + minio_log_debug "No files found in the extracted archive '${INITARCHIVES_DIR}/${archive}'. Skipping upload." + continue + fi + + # Copy the contents of the temporary folder to the bucket. + minio_log_note "Uploading all extracted files to bucket '${BUCKET_NAME}'." + # Note the trailing slash in the source folder. This is required to copy the CONTENTS of the folder and not the folder itself. + mc cp --recursive "${TMP_ARCHIVE_EXTRACTION_DIR}/" "${MC_ALIAS}/${BUCKET_NAME}" 1>/dev/null 2>"${LOGERR_FILE}" + if [ -s "${LOGERR_FILE}" ]; then + minio_log_error "Error uploading files to bucket '${BUCKET_NAME}'." + minio_log_error "$(cat "${LOGERR_FILE}")" + fi + + SOMETHING_UPLOADED=1 + done + + # Final clean up the temporary folder if it exists. + rm -rf "${TMP_ARCHIVE_EXTRACTION_DIR}" + + if [ "${SOMETHING_UPLOADED}" = "0" ]; then + minio_log_warn "All archives in '${INITARCHIVES_DIR}' have been processed, but no files were found in the extracted archives destination folder." + fi fi - minio_note "Bucket '${BUCKET_NAME}' is empty. Processing initialization files." - if [ "$(ls "${INITFILES_FOLDER}" 2>/dev/null | wc -l)" -gt 0 ]; then - minio_note "Uploading files to bucket '${BUCKET_NAME}'." + # Processing files. + if [ "$(ls -A "${INITFILES_DIR}" 2>/dev/null | wc -l)" -gt 0 ]; then + minio_log_note "Uploading seed files to bucket '${BUCKET_NAME}'." + # Note the trailing slash in the source folder. This is required to copy the CONTENTS of the folder and not the folder itself. - mc cp --recursive "${INITFILES_FOLDER}/" "${MC_ALIAS}/${BUCKET_NAME}" 1>/dev/null 2>/tmp/minio_error.log - if [ -s /tmp/minio_error.log ]; then - minio_error "Error uploading files to bucket '${BUCKET_NAME}'." - minio_error "$(cat /tmp/minio_error.log)" + mc cp --recursive "${INITFILES_DIR}/" "${MC_ALIAS}/${BUCKET_NAME}" 1>/dev/null 2>"${LOGERR_FILE}" + if [ -s "${LOGERR_FILE}" ]; then + minio_log_error "Error uploading files to bucket '${BUCKET_NAME}'." + minio_log_error "$(cat "${LOGERR_FILE}")" fi - return + SOMETHING_UPLOADED=1 fi - minio_note "No files found in '${INITFILES_FOLDER}'. The bucket '${BUCKET_NAME}' will remain empty." + if [ "${SOMETHING_UPLOADED}" = "0" ]; then + minio_log_note "No files found after processing archives in '${INITARCHIVES_DIR}' and files in '${INITFILES_DIR}'. The bucket '${BUCKET_NAME}' will remain empty." + fi +} + +# Utility functions. +is_tar_valid_mime_type() { + if [ "$#" -ne 1 ]; then + minio_log_error "is_tar_valid_mime_type() requires one argument." + fi + + local valid_mime_types + valid_mime_types="application/x-tar,application/gzip,application/x-bzip2,application/x-xz" + local mime_type + mime_type="$(file -b --mime-type "${1}")" + for valid_mime_type in $(echo ${valid_mime_types} | tr "," " "); do + if [ "${mime_type}" = "${valid_mime_type}" ]; then + return 0 + fi + done + return 1 } # Logging functions. @@ -77,15 +200,21 @@ minio_log() { printf '%s [%s] [Entrypoint]: %s\n' "$dt" "$type" "$text" } -minio_note() { +minio_log_debug() { + if [ "${DEBUG}" = "1" ]; then + minio_log Debug "$@" + fi +} + +minio_log_note() { minio_log Note "$@" } -minio_warn() { +minio_log_warn() { minio_log Warn "$@" >&2 } -minio_error() { +minio_log_error() { minio_log ERROR "$@" >&2 exit 1 } diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh index 848a829..7c6e057 100644 --- a/scripts/entrypoint.sh +++ b/scripts/entrypoint.sh @@ -5,15 +5,23 @@ shopt -s nullglob source /scripts/common.sh -# Configure Minio +# Debug mode. +export DEBUG=${DEBUG:-"0"} + +# Configure Minio. export BUCKET_ROOT=${BUCKET_ROOT:-"/data"} -export INITFILES_FOLDER=${INITFILES_FOLDER:-"/docker-entrypoint-initfiles.d"} +export INITFILESYSTEM_DIR=${INITFILESYSTEM_DIR:-"/docker-entrypoint-initfs.d"} +export INITARCHIVES_DIR=${INITARCHIVES_DIR:-"/docker-entrypoint-initarchives.d"} +export INITFILES_DIR=${INITFILES_DIR:-"/docker-entrypoint-initfiles.d"} export DO_NOT_PROCESS_INITFILES=${DO_NOT_PROCESS_INITFILES:-"0"} export MINIO_VERSION_ENABLED=${MINIO_VERSION_ENABLED:-"0"} +export MINIO_OPTS=${MINIO_OPTS:-""} + +# Configure Minio console. export MINIO_BROWSER=${MINIO_BROWSER:-"off"} export MINIO_CONSOLE_PORT=${MINIO_CONSOLE_PORT:-"9001"} -export MINIO_OPTS=${MINIO_OPTS:-""} -# Host to configure the local MinIO client. + +# Configure the local MinIO client. export MC_ALIAS="${MC_ALIAS:-"minio"}" export MINIO_PROTO="${MINIO_PROTO:-"http"}" export MINIO_HOST="${MINIO_HOST:-"localhost"}" @@ -38,29 +46,58 @@ fi # Check required environment variables if [ -z "${BUCKET_NAME}" ]; then - minio_error "BUCKET_NAME environment variable is required." + minio_log_error "BUCKET_NAME environment variable is required." fi if [ -z "${MINIO_ROOT_USER}" ]; then - minio_error "MINIO_ROOT_USER environment variable is required." + minio_log_error "MINIO_ROOT_USER environment variable is required." fi if [ -z "${MINIO_ROOT_PASSWORD}" ]; then - minio_error "MINIO_ROOT_PASSWORD environment variable is required." + minio_log_error "MINIO_ROOT_PASSWORD environment variable is required." fi if [ "${1}" = "minio" ]; then - # Temporary start of minio server. + # Start temporary MinIO server. minio_start_temp_server - # Wait for minio server to be ready. + # Wait for MinIO server to be ready. minio_wait_for_readiness - # Create bucket and upload files. - docker_create_bucket - # Eventually process init files. - if [ "${DO_NOT_PROCESS_INITFILES}" -eq 0 ]; then - docker_process_init_files + + if ! minio_initialization_is_needed; then + minio_log_note "Bucket '${BUCKET_NAME}' exists and it is not empty. Skipping initialization." + minio_log_debug "The 'FileSystem' and 'Seed' initialization modes will be skipped." + else + minio_log_note "Bucket '${BUCKET_NAME}' does not exist or it is empty. Starting initialization process." + + # Check if init filesystem folder exists and it is not empty. + if [ "$(ls "${INITFILESYSTEM_DIR}" 2>/dev/null | wc -l)" -gt 0 ]; then + # The folder is not empty. Start the 'FileSystem' initialization mode. + minio_log_note "Start the 'FileSystem' initialization mode." + + # Process init filesystem. + minio_process_init_filesystem + # Restart of MinIO server. + minio_restart_temp_server + # Wait for MinIO server to be ready. + minio_wait_for_readiness + # Check if the init filesystem is consistent with the BUCKET_NAME variable. + minio_check_initialized_filesystem + fi + + # Start the 'Seed' initialization mode. + minio_log_note "Start the 'Seed' initialization mode." + # Restart of MinIO server. + minio_restart_temp_server + # Wait for MinIO server to be ready. + minio_wait_for_readiness + # Create bucket and upload files. + minio_create_bucket + # Eventually process init files. + if [ "${DO_NOT_PROCESS_INITFILES}" -eq 0 ]; then + minio_process_seed_archives_and_files + fi fi - # Stop temporary minio server. + # Stop temporary MinIO server. minio_stop_temp_server # Run minio.