diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index eee1961fd6..e2ecaac199 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -216,13 +216,20 @@ jobs: # Re-compute the tag list deterministically from the same metadata-action # config the merge job used, so tag/schedule/SHA runs pull the image # they just published instead of an unrelated `:latest` from a prior run. + # IMPORTANT: keep this `enable=` expression byte-identical to the merge + # job's :latest gate above. The two used to differ + # (merge: ref + unsloth_ref guard; smoke: is_default_branch only), + # which meant workflow_dispatch with unsloth_ref defaulting to "main" + # would skip :latest on merge but still emit :latest as tags[0] on + # smoke -- so docker pull would fetch a previously-published :latest + # from Docker Hub, not the image just merged. - name: Resolve published tag id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | - type=raw,value=latest,enable={{is_default_branch}} + type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && github.event.inputs.unsloth_ref == '' }} type=ref,event=tag type=schedule,pattern=nightly type=sha,prefix=sha-,format=short diff --git a/docker/Dockerfile b/docker/Dockerfile index 29e0b5cd89..6d14d3400a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -230,8 +230,20 @@ RUN ${VENV}/bin/pip freeze --exclude-editable > ${VENV}/requirements.lock.txt \ && head -50 ${VENV}/requirements.lock.txt # 6) Strip pip cache & __pycache__ to shrink the layer copied to runtime. +# +# Note on the `-name tests` strip: numpy 2.4 ships `numpy/_core/tests/` +# back into the wheel (numpy 2.2.6 had stripped it, which is what the +# explicit upgrade earlier in this Dockerfile was meant to fix). Blowing +# away every `tests/` directory under the venv would re-introduce the +# same `from numpy._core.tests._natype import pd_NA` ImportError on the +# deployed image. Exclude numpy's tests directories explicitly so the +# upgrade fix stays in effect; keep stripping the rest. RUN find ${VENV} -depth -type d -name __pycache__ -exec rm -rf {} + \ - && find ${VENV} -depth -type d -name tests -exec rm -rf {} + \ + && find ${VENV} -depth -type d -name tests \ + ! -path "*numpy/_core/tests*" \ + ! -path "*numpy/tests*" \ + ! -path "*numpy/ma/tests*" \ + -exec rm -rf {} + \ && rm -rf /root/.cache/pip /root/.cache/uv # Build-time verification. diff --git a/docker/run.sh b/docker/run.sh index a240269b79..cb6b909279 100755 --- a/docker/run.sh +++ b/docker/run.sh @@ -51,10 +51,15 @@ fi # Forward common secrets only if they're set in the host environment. # Empty strings would shadow whatever is already inside the image. +# IMPORTANT: use the dash-only form `-e VAR` (no `=VALUE`). Docker reads +# the value from the parent shell, so the literal secret never lands in +# argv where it would be visible to any user on the host via +# `ps auxe` / `/proc//cmdline` for the lifetime of the docker CLI +# process. declare -a ENV_FORWARD=(-e HF_HUB_ENABLE_HF_TRANSFER=1) -[[ -n "${HF_TOKEN:-}" ]] && ENV_FORWARD+=(-e "HF_TOKEN=${HF_TOKEN}") -[[ -n "${WANDB_API_KEY:-}" ]] && ENV_FORWARD+=(-e "WANDB_API_KEY=${WANDB_API_KEY}") -[[ -n "${UNSLOTH_LICENSE:-}" ]] && ENV_FORWARD+=(-e "UNSLOTH_LICENSE=${UNSLOTH_LICENSE}") +[[ -n "${HF_TOKEN:-}" ]] && ENV_FORWARD+=(-e HF_TOKEN) +[[ -n "${WANDB_API_KEY:-}" ]] && ENV_FORWARD+=(-e WANDB_API_KEY) +[[ -n "${UNSLOTH_LICENSE:-}" ]] && ENV_FORWARD+=(-e UNSLOTH_LICENSE) # Only attach -t when our own stdin/stdout are a TTY; CI / piped invocations # otherwise hit `the input device is not a TTY` and never reach the entrypoint. diff --git a/docker/test_locally.sh b/docker/test_locally.sh index e6dbbe9a11..f93485d02e 100755 --- a/docker/test_locally.sh +++ b/docker/test_locally.sh @@ -362,8 +362,11 @@ INNER # Only forward HF_TOKEN if the host has one set, so an empty # `-e HF_TOKEN=` does not shadow whatever is already inside the image. + # Use the dash-only form `-e HF_TOKEN` so the secret value never + # lands in argv (visible via /proc//cmdline to any user on + # the host for the lifetime of the docker CLI process). HF_ARGS=() - [[ -n "${HF_TOKEN:-}" ]] && HF_ARGS+=(-e "HF_TOKEN=${HF_TOKEN}") + [[ -n "${HF_TOKEN:-}" ]] && HF_ARGS+=(-e HF_TOKEN) docker run --rm \ --gpus all \ --ipc=host \