From 2b95ad327c22abfa774a913e2855b873f7d96c38 Mon Sep 17 00:00:00 2001 From: shevi-kukis Date: Tue, 26 Aug 2025 19:17:24 +0300 Subject: [PATCH 1/9] Lifecycle rules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit configure MinIO so objects >7 days move to a “cold” tier --- .../xl.meta | Bin 0 -> 425 bytes .../xl.meta | Bin 0 -> 463 bytes .../xl.meta | Bin 0 -> 463 bytes .../xl.meta | Bin 0 -> 463 bytes storage/data/config/init.sh | 35 +++++ storage/data/config/lifecycle.json | 1 + storage/data/hot/imagery/dev/obj.txt/xl.meta | Bin 0 -> 2205 bytes storage/docker-compose.yml | 63 ++++++++ storage/lifecycle.md | 138 ++++++++++++++++++ storage/minio-bootstrap/Dockerfile | 114 +++++++++++++++ 10 files changed, 351 insertions(+) create mode 100644 storage/data/cold/cold-tier/37fcaa6724dd1518/2d/43/2d436d17-48d7-462f-bea5-0336cef4b00a/xl.meta create mode 100644 storage/data/cold/cold-tier/37fcaa6724dd1518/3c/76/3c763823-b1cd-4c81-a976-edf61769a8fb/xl.meta create mode 100644 storage/data/cold/cold-tier/37fcaa6724dd1518/ad/fb/adfbf567-3f25-4984-93de-c6191b007ce4/xl.meta create mode 100644 storage/data/cold/cold-tier/37fcaa6724dd1518/c8/4a/c84a68f7-3d1d-42bd-ba45-8ac22eb99b3b/xl.meta create mode 100644 storage/data/config/init.sh create mode 100644 storage/data/config/lifecycle.json create mode 100644 storage/data/hot/imagery/dev/obj.txt/xl.meta create mode 100644 storage/docker-compose.yml create mode 100644 storage/lifecycle.md create mode 100644 storage/minio-bootstrap/Dockerfile diff --git a/storage/data/cold/cold-tier/37fcaa6724dd1518/2d/43/2d436d17-48d7-462f-bea5-0336cef4b00a/xl.meta b/storage/data/cold/cold-tier/37fcaa6724dd1518/2d/43/2d436d17-48d7-462f-bea5-0336cef4b00a/xl.meta new file mode 100644 index 0000000000000000000000000000000000000000..e9a0b670aaf0cb91d8736ef19f5cbe9a284cfb2c GIT binary patch literal 425 zcma#>F;ZY;U}iYRz`)qY%*=R1ZTb-b1~hP4BJQ)2)xP3yM_5kja{OUrV_-bWn9#f= zq_QBDacP*5e^S;x2Ej$1E|^-ExVU5%9TAXqYFT=HrR(;k8|3*USL>cw=9=u7lb+AG z*frS~MEEf*cTIK*&a6tk!~nD&$nnfeNv&W6s&mOKE}6)up^YS1Vl3|^$p3)O@;eoxo>JoVsK?~E|bxq?YIwmlUNY=B|&>bRg@J*krA2CTnuUpxdFsNla~X}Sv(8D{u}@@dT#{FslXHXt E0C**p#{d8T literal 0 HcmV?d00001 diff --git a/storage/data/cold/cold-tier/37fcaa6724dd1518/3c/76/3c763823-b1cd-4c81-a976-edf61769a8fb/xl.meta b/storage/data/cold/cold-tier/37fcaa6724dd1518/3c/76/3c763823-b1cd-4c81-a976-edf61769a8fb/xl.meta new file mode 100644 index 0000000000000000000000000000000000000000..dd6972e6f29ae17c68f86ff2e127f1354cc667af GIT binary patch literal 463 zcma#>F;ZY;U}iYRz`)qY%*=R1ZTb-b1~hP4B5uclC|CZ9BP{Hj5?(U0F)$uwOlV#b zQdyA7xHQbjKPl@TgWw`h7fh{7TwF4XjtIC*=&n?Ea*J=+#(YqguYcn**JQ_>^nAv} zuF1Y2!jECOYqC>tW>xAX2B7soj%QvG5{pXwN^^@R zGOh$MT|*Mniw}UAApOM?*;avs9if~hAewEdZ%AftD%>B-eN#&kgDZ<0_f+WSX69w) z>t^Paq!#5R<^UNvnR%(YDTyVCM_5XVN>jmVLyL==*GK3&=2q!~wCegL=BBPrNiEaQ zPs-9OsVG?j6imOVkYs3SVwRX}X=Gw)lwxFTVxDYfWNeybl44|LXlQ6*vL-nnXir{= zZV52tb|e-QE|bxq?YIwmlUNY<}NHdm(j>N>)g!1Mk~g~C3&SeIY-pA smQKiza-MqY$-_HV$C6K+el^!@LsvF;ZY;U}iYRz`)qY%*=R1ZTb-b1~hP4B5v3F7vd6^kFZ=^VIIcF#=v-#F`;=$ zNM%7P#Y41$Y1T`;vSadF8kIwIh+A^qDo9>?v|#AX%o#d}yRb4_;4NzZ3o z?3(NgBK#PZyCypYXI7#uQa!K zBI8OB(={Y9z4!o_3DRFYk!=-7*b&NE0;1WL`i5lYro#QP+&8r(F}Sk0aZiPAZf0I) zzHVk-NorAEVh)gzlbM&Qo03?Pc!Z^-s5BL+Giq`5_spIXU@U05L+URR910 literal 0 HcmV?d00001 diff --git a/storage/data/cold/cold-tier/37fcaa6724dd1518/c8/4a/c84a68f7-3d1d-42bd-ba45-8ac22eb99b3b/xl.meta b/storage/data/cold/cold-tier/37fcaa6724dd1518/c8/4a/c84a68f7-3d1d-42bd-ba45-8ac22eb99b3b/xl.meta new file mode 100644 index 0000000000000000000000000000000000000000..2ce66af3015eee994c691df554b5af3281e4c2ad GIT binary patch literal 463 zcma#>F;ZY;U}iYRz`)qY%*=R1ZTb-b1~hP4B5wQ2^*sl2Bc6VMhLw2fc=Jc)0T$3Gh((@S? zyC(aB2tS79uE|cpnN_Km7=YFTIi7hbsTGVsbuO93B@-D}I0u*Jg0-v&NGvMxE6pvQ z$hZ>3bPY*NFFpWfg7gR9rL)34^5ZRjc~@vnI4b@tPQ{E&>)oSb|v05cb-vH$=8 literal 0 HcmV?d00001 diff --git a/storage/data/config/init.sh b/storage/data/config/init.sh new file mode 100644 index 000000000..8f7aeb574 --- /dev/null +++ b/storage/data/config/init.sh @@ -0,0 +1,35 @@ +#!/bin/sh +set -euo pipefail + +echo "[bootstrap] setting mc aliases..." +mc alias set hot http://minio-hot:9000 minio minio123 +mc alias set cold http://minio-cold:9000 minio minio123 + +echo "[bootstrap] waiting for hot..." +until mc ls hot >/dev/null 2>&1; do sleep 2; done +echo "[bootstrap] waiting for cold..." +until mc ls cold >/dev/null 2>&1; do sleep 2; done + +echo "[bootstrap] creating buckets (idempotent)..." +mc mb --ignore-existing hot/imagery || true +mc mb --ignore-existing cold/cold-tier || true + +echo "[bootstrap] enabling versioning..." +mc version enable hot/imagery || true + +echo "[bootstrap] ensuring remote tier COLD exists..." +if ! mc ilm tier ls hot | grep -q ' COLD '; then + mc ilm tier add s3 hot COLD \ + --endpoint http://minio-cold:9000 \ + --access-key minio \ + --secret-key minio123 \ + --bucket cold-tier \ + --region us-east-1 +fi + +echo "[bootstrap] importing lifecycle policy..." +mc ilm import hot/imagery < /config/lifecycle.json + +echo "[bootstrap] current rules:" +mc ilm rule ls hot/imagery || true +echo "[bootstrap] DONE." diff --git a/storage/data/config/lifecycle.json b/storage/data/config/lifecycle.json new file mode 100644 index 000000000..9e41ad618 --- /dev/null +++ b/storage/data/config/lifecycle.json @@ -0,0 +1 @@ +{"Rules":[{"ID":"d2lhca81cpp9ns2hgsr0","Status":"Enabled","Transition":{"StorageClass":"COLD","Days":7}}]} diff --git a/storage/data/hot/imagery/dev/obj.txt/xl.meta b/storage/data/hot/imagery/dev/obj.txt/xl.meta new file mode 100644 index 0000000000000000000000000000000000000000..ce949dd6e98ebf363aa30ac73b38b93fc4522578 GIT binary patch literal 2205 zcmdVaTSyd97y#gz+$1W>UMlDzkxCLyGjrzb%o%!!%{9{UQrhJ~qBG~5u?crqc1E!v zqq|lw8X=U>%`RF{5M>BP#AH25s6k6m4?Xl$K?R~+XV*oA=e6>k())<;q$H!4WnEvt_>tzuVl zSyV-8oJXl;vfgPGx|6R%=}l+yDO@eBvLk$=kL#t}C6)V}qlvsm5V50n4A@bZ$D^bc zxN#D7Y}bxOf#VXl-tp$pSfs9&yF9TXLpEn1X71(G_13DoMG4V#h!|6X3YH*~km^UI zYE01q!psjEw1CM;5Xh>kQEnkqmPsN%^AQa^?)abPk6K9NW=I9D&EsC6uzYhk)$BGW ze)txR`AtS$;QII0?ea!fs;eb-w9_9(O(K^eg<;AJY{{|-WyB3E%Z7nDwJ?G@ztk|W z=g{nPDIx3HPJEgBvV7_7JHw|pH4oqOC)@k+?NG-`FL2?cs%H{1wKOf{@z$}M_vaRm zUhI9?`ZLg7J)J_bCkx3=3CW%iGTz5b3n5IhOo=edw1S!rR0{?HGB5&$$~d5!VkkZj zopLmtLedgU#XuUN21EvAP(?b`pc*t0gPNi!82t&-WFh!jQ{SHDp{A}av3ZHS_OLJH z!K2EumhWERYi}LSBxGu7TF9}E>fZDDp=E9NLWzp@mi~VxWW0}=7NSx~*Cdtdnu?(c zOocLlC{_S5bPaH3X^O5H1Y72G3i;F3|D~MCLT2qKD3QNye0Hp0$??36&BeZup04gs zWBp#B(P&tiNyyaFw2*5ZuW~ Alternative (CLI only): +> ```bash +> mc ilm rule add hot/imagery --transition-days 7 --transition-tier COLD --prefix "" +> ``` + +--- + +## Dev Validation (fast, safe) +Use a **temporary** rule that applies only to a `dev/` prefix and transitions **immediately**. This validates the tiering without waiting 7 days. + +1) **Add the temporary rule (inside `mc`):** +```bash +mc ilm rule add hot/imagery --transition-days 0 --transition-tier COLD --prefix "dev/" +mc ilm rule ls hot/imagery +``` + +2) **Upload a test object and verify:** +```bash +echo "hello" > /tmp/obj.txt +mc cp /tmp/obj.txt hot/imagery/dev/obj.txt + +# Check on hot: +mc stat hot/imagery/dev/obj.txt +# Expect a line: X-Amz-Storage-Class: COLD +``` + +3) **(Optional) Additional checks:** +- Stop cold and try to read (should fail), then start and try again: + ```bash + # on host + docker stop minio-cold + # in mc + mc cat hot/imagery/dev/obj.txt # expect failure + # on host + docker start minio-cold + # in mc + mc cat hot/imagery/dev/obj.txt # should work again + ``` +- Watch logs while reading: + ```bash + # on host + docker logs -f minio-hot + docker logs -f minio-cold + ``` + +4) **Cleanup the temporary rule:** +```bash +# Find the ID of the dev rule (PREFIX=dev/) and remove it +mc ilm rule ls hot/imagery +mc ilm rule rm hot/imagery --id +``` + +5) **Export the final prod policy and copy it out (optional):** +```bash +# in mc +mc ilm export hot/imagery > /tmp/lifecycle.json + +# on host (Windows PowerShell) +docker cp mc:/tmp/lifecycle.json .\lifecycle.json +type .\lifecycle.json +``` + +--- + +## Troubleshooting +- **No transition happens:** ensure `mc version info hot/imagery` shows `Enabled`. +- **Wrong tier name:** `--transition-tier` must match exactly the tier shown in `mc ilm tier ls hot` (e.g., `COLD`). +- **Cannot see the object under the same key in cold:** expected. Cold stores objects under internal keys; rely on `mc stat` (`X-Amz-Storage-Class: COLD`) and logs/trace. +- **Latency on first read after transition:** expected; hot fetches from cold. +- **Permission errors:** verify access/secret keys used in `mc ilm tier add`. + +--- + +## Notes for production +- Keep the prod rule (7 days) only; remove any temporary dev rules. +- Consider bucket-level IAM: ingestion services get `s3:PutObject` only to the appropriate bucket/prefix. +- Consider monitoring: expose MinIO metrics to Prometheus; chart PUT latency and bucket size in Grafana. + +--- + +**Done.** This document + `lifecycle.json` are the required deliverables. diff --git a/storage/minio-bootstrap/Dockerfile b/storage/minio-bootstrap/Dockerfile new file mode 100644 index 000000000..1f4c28c4c --- /dev/null +++ b/storage/minio-bootstrap/Dockerfile @@ -0,0 +1,114 @@ +FROM alpine:3.19 + +# ===== Deps & Binaries ===== +RUN apk add --no-cache bash curl ca-certificates supervisor && \ + update-ca-certificates && \ + curl -fsSL https://dl.min.io/server/minio/release/linux-amd64/minio -o /usr/local/bin/minio && \ + curl -fsSL https://dl.min.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc && \ + chmod +x /usr/local/bin/minio /usr/local/bin/mc + +# ===== Dirs ===== +RUN mkdir -p /data/hot /data/cold /entrypoint /config /var/log/supervisor + +# ===== init.sh (Bootstrap) ===== +RUN cat > /entrypoint/init.sh <<'SH' && chmod +x /entrypoint/init.sh +#!/usr/bin/env bash +set -euo pipefail + +# Aliases via env allow mc to work even when ENTRYPOINT is bypassed +mc alias set "${MC_ALIAS_HOT}" "${HOT_ENDPOINT}" "${MINIO_ROOT_USER}" "${MINIO_ROOT_PASSWORD}" || true +mc alias set "${MC_ALIAS_COLD}" "${COLD_ENDPOINT}" "${MINIO_ROOT_USER}" "${MINIO_ROOT_PASSWORD}" || true + +echo "[bootstrap] waiting for hot (${HOT_ENDPOINT})..." +until mc ls "${MC_ALIAS_HOT}" >/dev/null 2>&1; do sleep 2; done +echo "[bootstrap] waiting for cold (${COLD_ENDPOINT})..." +until mc ls "${MC_ALIAS_COLD}" >/dev/null 2>&1; do sleep 2; done + +echo "[bootstrap] creating buckets (idempotent)..." +mc mb --ignore-existing "${MC_ALIAS_HOT}/imagery" || true +mc mb --ignore-existing "${MC_ALIAS_COLD}/cold-tier" || true + +echo "[bootstrap] enabling versioning on hot/imagery..." +mc version enable "${MC_ALIAS_HOT}/imagery" || true + +echo "[bootstrap] ensuring remote tier COLD exists on HOT..." +# Robust check using JSON; add only if missing. || true keeps script idempotent +if ! mc ilm tier ls "${MC_ALIAS_HOT}" --json | grep -q '"Name":"COLD"'; then + mc ilm tier add s3 "${MC_ALIAS_HOT}" COLD \ + --endpoint "${COLD_ENDPOINT}" \ + --access-key "${MINIO_ROOT_USER}" \ + --secret-key "${MINIO_ROOT_PASSWORD}" \ + --bucket cold-tier \ + --region us-east-1 || true +fi + +echo "[bootstrap] importing lifecycle policy..." +mc ilm import "${MC_ALIAS_HOT}/imagery" < "${LIFECYCLE_PATH}" + +echo "[bootstrap] current rules:" +mc ilm rule ls "${MC_ALIAS_HOT}/imagery" || true +echo "[bootstrap] DONE." +SH + +# ===== lifecycle.json ===== +RUN cat > /config/lifecycle.json <<'JSON' +{ + "Rules": [ + { + "ID": "d2lhca81cpp9ns2hgsr0", + "Status": "Enabled", + "Transition": { "StorageClass": "COLD", "Days": 7 } + } + ] +} +JSON + +# ===== supervisord.conf ===== +RUN cat > /etc/supervisord.conf <<'CONF' +[supervisord] +nodaemon=true +logfile=/var/log/supervisor/supervisord.log + +[program:minio_hot] +command=/usr/local/bin/minio server --address %(ENV_HOT_ADDRESS)s --console-address %(ENV_HOT_CONSOLE)s /data/hot +stdout_logfile=/var/log/supervisor/minio_hot.log +stderr_logfile=/var/log/supervisor/minio_hot.err +autorestart=true +priority=10 + +[program:minio_cold] +command=/usr/local/bin/minio server --address %(ENV_COLD_ADDRESS)s --console-address %(ENV_COLD_CONSOLE)s /data/cold +stdout_logfile=/var/log/supervisor/minio_cold.log +stderr_logfile=/var/log/supervisor/minio_cold.err +autorestart=true +priority=10 + +# Bootstrap waits for servers (init.sh itself waits for readiness) +[program:bootstrap] +command=/bin/bash -lc "/entrypoint/init.sh" +stdout_logfile=/var/log/supervisor/bootstrap.log +stderr_logfile=/var/log/supervisor/bootstrap.err +autorestart=false +startsecs=0 +priority=20 +CONF + +# ===== Sensible defaults & mc ENV aliases ===== +ENV MINIO_ROOT_USER=minio \ + MINIO_ROOT_PASSWORD=minio123 \ + HOT_ADDRESS=:9000 \ + HOT_CONSOLE=:9001 \ + COLD_ADDRESS=:9100 \ + COLD_CONSOLE=:9101 \ + HOT_ENDPOINT=http://127.0.0.1:9000 \ + COLD_ENDPOINT=http://127.0.0.1:9100 \ + MC_ALIAS_HOT=hot \ + MC_ALIAS_COLD=cold \ + LIFECYCLE_PATH=/config/lifecycle.json \ + MC_HOST_hot="http://minio:minio123@127.0.0.1:9000" \ + MC_HOST_cold="http://minio:minio123@127.0.0.1:9100" + +EXPOSE 9000 9001 9100 9101 + +# Run both MinIO servers + bootstrap in one container +CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"] From 4123071391db693730673e6c87aa7bf989d78182 Mon Sep 17 00:00:00 2001 From: shevi-kukis Date: Wed, 27 Aug 2025 15:01:26 +0300 Subject: [PATCH 2/9] Update README.md --- README.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f7e205ef9..c70788138 100644 --- a/README.md +++ b/README.md @@ -1 +1,19 @@ -# AgCloud \ No newline at end of file +# MinIO Tiering Demo (All-in-One Docker) + +Runs HOT + COLD MinIO servers in one container, with bootstrap script that: +- Creates buckets: imagery (HOT), cold-tier (COLD) +- Enables versioning on HOT +- Defines lifecycle: move objects >7 days → COLD + +## Quickstart +```bash +docker build -t minio-allinone . +docker run -d --name minio-aio -p 9000:9000 -p 9001:9001 -p 9100:9100 -p 9101:9101 minio-allinone +``` + +Consoles: HOT → http://localhost:9001 | COLD → http://localhost:9101 + +Upload test: +```bash +docker exec -it minio-aio mc cp /etc/hosts hot/imagery/test.txt +``` From c5680a175ffbd16901cf5ac47617c8ed9d9b1d9f Mon Sep 17 00:00:00 2001 From: shevi-kukis Date: Mon, 1 Sep 2025 11:35:02 +0300 Subject: [PATCH 3/9] Add files via upload --- monitoring/dashbaord.png | Bin 0 -> 52524 bytes monitoring/docker-compose.yml | 46 ++++++ monitoring/grafana-dashboard.json | 244 ++++++++++++++++++++++++++++++ monitoring/prometheus.yml | 13 ++ monitoring/somefile.txt | 1 + 5 files changed, 304 insertions(+) create mode 100644 monitoring/dashbaord.png create mode 100644 monitoring/docker-compose.yml create mode 100644 monitoring/grafana-dashboard.json create mode 100644 monitoring/prometheus.yml create mode 100644 monitoring/somefile.txt diff --git a/monitoring/dashbaord.png b/monitoring/dashbaord.png new file mode 100644 index 0000000000000000000000000000000000000000..22d4f54dee2f2d71904be6eeea768860ce7d565a GIT binary patch literal 52524 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 s Date: Mon, 1 Sep 2025 13:40:04 +0300 Subject: [PATCH 4/9] Update README.md From 87622d178020f9a7b7e85a91261cc8d4724ef146 Mon Sep 17 00:00:00 2001 From: shevi-kukis Date: Mon, 1 Sep 2025 13:45:00 +0300 Subject: [PATCH 5/9] Update README.md add monitoring readme --- README.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/README.md b/README.md index c70788138..168c3db4a 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,39 @@ Upload test: ```bash docker exec -it minio-aio mc cp /etc/hosts hot/imagery/test.txt ``` +# MinIO Monitoring Demo (Docker Compose) + +Runs MinIO with HOT + COLD endpoints, Prometheus scraping enabled, and Grafana dashboard for monitoring. + +- MinIO exposes metrics on ports 9000 (HOT) and 9100 (COLD) +- Prometheus scrapes MinIO metrics from both endpoints +- Grafana shows dashboards with: + - **PUT latency (p95)** + - **Bucket size** + +## Quickstart +```bash +docker compose up -d --build +``` + +## Consoles & UIs +- HOT MinIO Console → http://localhost:9001 +- COLD MinIO Console → http://localhost:9101 +- Prometheus → http://localhost:9090 +- Grafana → http://localhost:3000 (admin / admin) + +## Example PromQL +### PUT latency (p95) +```promql +histogram_quantile( + 0.95, + sum by (le, job, instance) ( + rate(minio_s3_requests_ttfb_seconds_distribution_bucket{api="putobject"}[5m]) + ) +) +``` + +### Bucket size per bucket +```promql +sum by (bucket) (minio_bucket_usage_size_bytes) +``` From 2aa5d93c3cb4df5e09413cc9d8c16608e84f609e Mon Sep 17 00:00:00 2001 From: shevi-kukis Date: Mon, 1 Sep 2025 14:22:05 +0300 Subject: [PATCH 6/9] Create ci.yml --- .github/workflows/ci.yml | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..061254d09 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,49 @@ +name: CI + +on: + push: + branches: ["**"] + pull_request: + +jobs: + build_and_validate: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + env: + IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/minio-bootstrap + IMAGE_TAG: ${{ github.sha }} + + steps: + # שלב 1 - הורדת הקוד + - name: Checkout repository + uses: actions/checkout@v4 + + # שלב 2 - הכנה לבנייה בדוקר + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # שלב 3 - התחברות ל־GHCR (רג’יסטרי של GitHub) + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # שלב 4 - בנייה ודחיפת האימג' + - name: Build and push minio-bootstrap image + uses: docker/build-push-action@v6 + with: + context: ./storage/minio-bootstrap + file: ./storage/minio-bootstrap/Dockerfile + push: true + tags: | + ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} + ${{ env.IMAGE_NAME }}:latest + + # שלב 5 - בדיקת תקינות של docker-compose.yml + - name: Validate docker compose + run: docker compose -f storage/docker-compose.yml config -q From d532376b6fa534366004fdf5ca1a63c178ffcf52 Mon Sep 17 00:00:00 2001 From: shevi-kukis Date: Mon, 1 Sep 2025 14:36:34 +0300 Subject: [PATCH 7/9] Update ci.yml --- .github/workflows/ci.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 061254d09..134c37abf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,22 +10,27 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - packages: write + packages: write # נדרש כדי לדחוף ל-GHCR env: - IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/minio-bootstrap + # בסיס שם האימג' (עלול לכלול אותיות גדולות, נטפל בזה בשלב הבא) + IMAGE_NAME_BASE: ghcr.io/${{ github.repository_owner }}/minio-bootstrap IMAGE_TAG: ${{ github.sha }} steps: - # שלב 1 - הורדת הקוד - name: Checkout repository uses: actions/checkout@v4 - # שלב 2 - הכנה לבנייה בדוקר - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - # שלב 3 - התחברות ל־GHCR (רג’יסטרי של GitHub) + # הפיכה ל-lowercase כדי למנוע "repository name must be lowercase" + - name: Normalize image name to lowercase + id: name_lc + run: | + echo "IMAGE_NAME=$(echo '${IMAGE_NAME_BASE}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV + echo "Final image: $(echo '${IMAGE_NAME_BASE}' | tr '[:upper:]' '[:lower:]')" + - name: Log in to GHCR uses: docker/login-action@v3 with: @@ -33,8 +38,7 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - # שלב 4 - בנייה ודחיפת האימג' - - name: Build and push minio-bootstrap image + - name: Build & push minio-bootstrap image uses: docker/build-push-action@v6 with: context: ./storage/minio-bootstrap @@ -44,6 +48,5 @@ jobs: ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} ${{ env.IMAGE_NAME }}:latest - # שלב 5 - בדיקת תקינות של docker-compose.yml - name: Validate docker compose run: docker compose -f storage/docker-compose.yml config -q From 7dd1d15ab1e85c2031b2355a2105e86b03fb7883 Mon Sep 17 00:00:00 2001 From: shevi-kukis Date: Mon, 1 Sep 2025 14:39:14 +0300 Subject: [PATCH 8/9] Update ci.yml --- .github/workflows/ci.yml | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 134c37abf..34df1cd85 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,12 +10,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read - packages: write # נדרש כדי לדחוף ל-GHCR - - env: - # בסיס שם האימג' (עלול לכלול אותיות גדולות, נטפל בזה בשלב הבא) - IMAGE_NAME_BASE: ghcr.io/${{ github.repository_owner }}/minio-bootstrap - IMAGE_TAG: ${{ github.sha }} + packages: write steps: - name: Checkout repository @@ -24,12 +19,12 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - # הפיכה ל-lowercase כדי למנוע "repository name must be lowercase" - - name: Normalize image name to lowercase - id: name_lc - run: | - echo "IMAGE_NAME=$(echo '${IMAGE_NAME_BASE}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV - echo "Final image: $(echo '${IMAGE_NAME_BASE}' | tr '[:upper:]' '[:lower:]')" + # שלב: נורמליזציה לשם אימג' באותיות קטנות + - name: Set image name (lowercase) + run: echo "IMAGE_NAME=ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/minio-bootstrap" >> $GITHUB_ENV + + - name: Set image tag + run: echo "IMAGE_TAG=${GITHUB_SHA}" >> $GITHUB_ENV - name: Log in to GHCR uses: docker/login-action@v3 From e2cc9457a6402982b245abcb51ffe5c872a7432c Mon Sep 17 00:00:00 2001 From: shevi-kukis Date: Mon, 1 Sep 2025 16:13:57 +0300 Subject: [PATCH 9/9] Update ci.yml --- .github/workflows/ci.yml | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34df1cd85..7851d6a17 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,42 +6,41 @@ on: pull_request: jobs: - build_and_validate: + build_and_push: runs-on: ubuntu-latest permissions: contents: read - packages: write + packages: write # חשוב ל-GHCR + + env: + IMAGE_TAG: ${{ github.sha }} steps: - - name: Checkout repository + - name: Checkout uses: actions/checkout@v4 + - name: Set image name (org) + run: echo "IMAGE_NAME=ghcr.io/kamatechorg/minio-bootstrap" >> $GITHUB_ENV + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - # שלב: נורמליזציה לשם אימג' באותיות קטנות - - name: Set image name (lowercase) - run: echo "IMAGE_NAME=ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/minio-bootstrap" >> $GITHUB_ENV - - - name: Set image tag - run: echo "IMAGE_TAG=${GITHUB_SHA}" >> $GITHUB_ENV - - - name: Log in to GHCR + - name: Login to GHCR (using GITHUB_TOKEN) uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Build & push minio-bootstrap image + - name: Build & Push uses: docker/build-push-action@v6 with: context: ./storage/minio-bootstrap file: ./storage/minio-bootstrap/Dockerfile push: true tags: | - ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} ${{ env.IMAGE_NAME }}:latest + ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} - - name: Validate docker compose + - name: Validate compose run: docker compose -f storage/docker-compose.yml config -q