From 98a721e1da390bf71ab92849b51a99197ea557d6 Mon Sep 17 00:00:00 2001 From: FAQ Bot Date: Mon, 17 Aug 2026 15:52:45 +0000 Subject: [PATCH 1/2] NEW: Why did Render deploy the wrong service from my multi-stage Dockerfile? --- ...der-wrong-service-multistage-dockerfile.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 _questions/llm-zoomcamp/workshops-dlthub/016_5b343ea5b3_render-wrong-service-multistage-dockerfile.md diff --git a/_questions/llm-zoomcamp/workshops-dlthub/016_5b343ea5b3_render-wrong-service-multistage-dockerfile.md b/_questions/llm-zoomcamp/workshops-dlthub/016_5b343ea5b3_render-wrong-service-multistage-dockerfile.md new file mode 100644 index 00000000..9ccec07a --- /dev/null +++ b/_questions/llm-zoomcamp/workshops-dlthub/016_5b343ea5b3_render-wrong-service-multistage-dockerfile.md @@ -0,0 +1,24 @@ +--- +id: 5b343ea5b3 +question: Why did Render deploy the wrong service from my multi-stage Dockerfile? +sort_order: 16 +--- + +When you build a multi-stage `Dockerfile`, Render effectively performs a target-less build (no `--target`), so the image it runs is whatever stage is declared last in the file. + +If your `Dockerfile` has multiple stages (e.g., a `ui` stage and an `api` stage that share a base), ensure the service you actually want deployed is the last stage. + +Key points: +- Keep the desired runtime stage (the one that should be deployed) as the last `FROM ... AS ` in the `Dockerfile`. +- If you later append a new stage below it, Render may silently switch which stage gets built and shipped (build can still succeed, just with the wrong service). +- This discrepancy often only shows up on Render because `docker-compose` can set `target: ...` per service. +- Verify which service Render actually deployed by hitting a route that is unique to that service, not a shared endpoint like `/health` that both services might implement. + +Quick local check before pushing: +```bash +docker build -t check . # same as Render: no --target +docker run --rm -p 8010:8000 -e POSTGRES_URL=... check +curl -s localhost:8010/health +``` + +To prevent future edits from reintroducing the problem, you can add a comment above the intended last stage reminding not to append anything below it. \ No newline at end of file From eaa96bf9d7c84485a6a272ef130ef4ea23ccfb51 Mon Sep 17 00:00:00 2001 From: Alexey Grigorev Date: Wed, 9 Sep 2026 14:52:38 +0200 Subject: [PATCH 2/2] Move Render multistage FAQ to project section, restore examples (#364) --- ...der-wrong-service-multistage-dockerfile.md | 47 +++++++++++++++++++ ...der-wrong-service-multistage-dockerfile.md | 24 ---------- 2 files changed, 47 insertions(+), 24 deletions(-) create mode 100644 _questions/llm-zoomcamp/project/031_5b343ea5b3_render-wrong-service-multistage-dockerfile.md delete mode 100644 _questions/llm-zoomcamp/workshops-dlthub/016_5b343ea5b3_render-wrong-service-multistage-dockerfile.md diff --git a/_questions/llm-zoomcamp/project/031_5b343ea5b3_render-wrong-service-multistage-dockerfile.md b/_questions/llm-zoomcamp/project/031_5b343ea5b3_render-wrong-service-multistage-dockerfile.md new file mode 100644 index 00000000..26f9085c --- /dev/null +++ b/_questions/llm-zoomcamp/project/031_5b343ea5b3_render-wrong-service-multistage-dockerfile.md @@ -0,0 +1,47 @@ +--- +id: 5b343ea5b3 +question: Why did Render deploy the wrong service from my multi-stage Dockerfile? +sort_order: 31 +--- + +Render builds your Dockerfile with no `--target` flag (its Blueprint spec has no field to select a build stage), and a target-less `docker build` always produces the stage declared last. If your `Dockerfile` has multiple stages — e.g. an `api` stage and a `ui` stage sharing a base — whichever comes last is what Render runs. Reordering stages or appending a new one silently changes what gets deployed: the build still succeeds, it just ships the wrong image. + +This is easy to miss locally because `docker-compose` sets `target:` per service, so the same Dockerfile behaves correctly under compose while deploying the wrong thing on Render: + +```dockerfile +FROM python:3.11-slim AS deps +WORKDIR /app +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt +COPY . . + +# UI stage — deliberately NOT last +FROM deps AS ui +EXPOSE 8501 +CMD ["streamlit", "run", "app.py", "--server.address=0.0.0.0", "--server.port=8501"] + +# `api` is deliberately the LAST stage: Render builds with no --target, +# and a target-less build resolves to whichever stage comes last. +# DO NOT append new stages below this one. +FROM deps AS api +EXPOSE 8000 +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] +``` + +```yaml +services: + api: + build: { context: ., target: api } + ui: + build: { context: ., target: ui } +``` + +To keep it fixed: keep the deployed service as the last stage and verify by hitting a route unique to that service (not a shared `/health` endpoint both services might answer identically). Before pushing, reproduce Render's target-less build locally: + +```bash +docker build -t check . # no --target, same as Render +docker run --rm -p 8010:8000 check +curl -s localhost:8010/health +``` + +See [Render's Docker docs](https://docs.render.com/docker) — multi-stage builds are supported, but there is no target-stage selection. diff --git a/_questions/llm-zoomcamp/workshops-dlthub/016_5b343ea5b3_render-wrong-service-multistage-dockerfile.md b/_questions/llm-zoomcamp/workshops-dlthub/016_5b343ea5b3_render-wrong-service-multistage-dockerfile.md deleted file mode 100644 index 9ccec07a..00000000 --- a/_questions/llm-zoomcamp/workshops-dlthub/016_5b343ea5b3_render-wrong-service-multistage-dockerfile.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -id: 5b343ea5b3 -question: Why did Render deploy the wrong service from my multi-stage Dockerfile? -sort_order: 16 ---- - -When you build a multi-stage `Dockerfile`, Render effectively performs a target-less build (no `--target`), so the image it runs is whatever stage is declared last in the file. - -If your `Dockerfile` has multiple stages (e.g., a `ui` stage and an `api` stage that share a base), ensure the service you actually want deployed is the last stage. - -Key points: -- Keep the desired runtime stage (the one that should be deployed) as the last `FROM ... AS ` in the `Dockerfile`. -- If you later append a new stage below it, Render may silently switch which stage gets built and shipped (build can still succeed, just with the wrong service). -- This discrepancy often only shows up on Render because `docker-compose` can set `target: ...` per service. -- Verify which service Render actually deployed by hitting a route that is unique to that service, not a shared endpoint like `/health` that both services might implement. - -Quick local check before pushing: -```bash -docker build -t check . # same as Render: no --target -docker run --rm -p 8010:8000 -e POSTGRES_URL=... check -curl -s localhost:8010/health -``` - -To prevent future edits from reintroducing the problem, you can add a comment above the intended last stage reminding not to append anything below it. \ No newline at end of file