Skip to content

docs(dockerfile): warn about the npm omit=dev + tsc build trap in TypeScript Actors#2716

Open
DaveHanns wants to merge 5 commits into
masterfrom
docs-typescript-dockerfile-omit-dev-warning
Open

docs(dockerfile): warn about the npm omit=dev + tsc build trap in TypeScript Actors#2716
DaveHanns wants to merge 5 commits into
masterfrom
docs-typescript-dockerfile-omit-dev-warning

Conversation

@DaveHanns

@DaveHanns DaveHanns commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a :::warning on source_code.md about the npm install --omit=dev + tsc build trap: --omit=dev drops typescript, so any TS Actor whose build invokes tsc fails at image-build time with sh: tsc: not found. Callout links to the ts-empty template's Dockerfile as the canonical multi-stage reference.

Related — coordinated remediation stack

Four defense layers, each covering a different failure mode:

  • apify/actor-templates — ts-* Dockerfiles ship a multi-stage build (already in master via #592, Dec 2025). Users of apify create -t ts-* cannot hit the trap.
  • apify/apify-cli#1252apify push preflight warning when a Dockerfile has --omit=dev before npm run build that invokes tsc.
  • apify/apify-cli#1261apify create forces --include=dev + NODE_ENV=development on the post-scaffold install, so apify run works locally.
  • This PR — docs callout on the Source-code page for the direct-docker build / search-fallback case.

Surfaced during an evaluation of Apify surfaces for agent-driven Actor development.

…eScript Actors

The canonical Node.js Dockerfile on this page uses `npm install --omit=dev`, which drops `devDependencies` and thus removes `typescript` from the image. Any TypeScript Actor whose `build` script invokes `tsc` will fail inside the Docker build with `tsc: not found`. This is a recurring pitfall — agents and users both hit it once per new TS Actor, and each retry burns a remote build cycle.

Add a `:::warning` callout under the sample Dockerfile with two concrete fixes (multi-stage build, or single-stage with devDeps kept in) and the failure signature so it can be recognized from logs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@apify-service-account

apify-service-account commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

❌ Preview build for this PR (commit 0a89687c) failed. See action run for details.

Cut the multi-stage code sample and the redundant symptoms
paragraph; link to the ts-empty template's Dockerfile as the
canonical multi-stage reference. Failure signature is still in
the callout so log searches land here.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
DaveHanns and others added 3 commits July 13, 2026 14:18
Drop the template reference; simplify the error signature to
`tsc: not found`; add the "move typescript to dependencies"
fix alongside multi-stage and drop-omit-dev.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Each of the three fixes (multi-stage, drop --omit=dev, move to
dependencies) now has a one-line trade-off summary and a
<details>-collapsed code example.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Remove specific runtime-image size numbers from the "move
typescript to dependencies" fix; unspace em-dashes per
Microsoft.Dashes vale rule.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@DaveHanns DaveHanns self-assigned this Jul 13, 2026
@DaveHanns DaveHanns marked this pull request as ready for review July 13, 2026 13:28
@DaveHanns DaveHanns requested review from TC-MO and l2ysho July 13, 2026 13:28

@TC-MO TC-MO left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should fix the build, I'll tackle the admonition itself separately

Comment on lines +86 to +103
- **Multi-stage build** (smallest runtime image)—installs devDeps in a builder stage, copies the compiled output into a slim runtime stage. Most complex Dockerfile.
<details><summary>Example</summary>

```dockerfile
FROM apify/actor-node:24 AS builder
COPY --chown=myuser:myuser package*.json ./
RUN npm install --include=dev
COPY --chown=myuser:myuser . ./
RUN npm run build

FROM apify/actor-node:24
COPY --chown=myuser:myuser package*.json ./
RUN npm install --omit=dev --omit=optional
COPY --from=builder --chown=myuser:myuser /usr/src/app/dist ./dist
CMD ["node", "dist/main.js"]
```

</details>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- **Multi-stage build** (smallest runtime image)—installs devDeps in a builder stage, copies the compiled output into a slim runtime stage. Most complex Dockerfile.
<details><summary>Example</summary>
```dockerfile
FROM apify/actor-node:24 AS builder
COPY --chown=myuser:myuser package*.json ./
RUN npm install --include=dev
COPY --chown=myuser:myuser . ./
RUN npm run build
FROM apify/actor-node:24
COPY --chown=myuser:myuser package*.json ./
RUN npm install --omit=dev --omit=optional
COPY --from=builder --chown=myuser:myuser /usr/src/app/dist ./dist
CMD ["node", "dist/main.js"]
```
</details>
- **Multi-stage build** (smallest runtime image)—installs devDeps in a builder stage, copies the compiled output into a slim runtime stage. Most complex Dockerfile.
<details>
<summary>Example</summary>
```dockerfile
FROM apify/actor-node:24 AS builder
COPY --chown=myuser:myuser package*.json ./
RUN npm install --include=dev
COPY --chown=myuser:myuser . ./
RUN npm run build
FROM apify/actor-node:24
COPY --chown=myuser:myuser package*.json ./
RUN npm install --omit=dev --omit=optional
COPY --from=builder --chown=myuser:myuser /usr/src/app/dist ./dist
CMD ["node", "dist/main.js"]
```

Comment on lines +105 to +117
- **Drop `--omit=dev`** (simplest Dockerfile, largest runtime image)—installs everything, including linters and type declarations, into the single-stage image.
<details><summary>Example</summary>

```dockerfile
FROM apify/actor-node:24
COPY --chown=myuser:myuser package*.json ./
RUN npm install
COPY --chown=myuser:myuser . ./
RUN npm run build
CMD ["node", "dist/main.js"]
```

</details>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- **Drop `--omit=dev`** (simplest Dockerfile, largest runtime image)—installs everything, including linters and type declarations, into the single-stage image.
<details><summary>Example</summary>
```dockerfile
FROM apify/actor-node:24
COPY --chown=myuser:myuser package*.json ./
RUN npm install
COPY --chown=myuser:myuser . ./
RUN npm run build
CMD ["node", "dist/main.js"]
```
</details>
- **Drop `--omit=dev`** (simplest Dockerfile, largest runtime image)—installs everything, including linters and type declarations, into the single-stage image.
<details>
<summary>Example</summary>
```dockerfile
FROM apify/actor-node:24
COPY --chown=myuser:myuser package*.json ./
RUN npm install
COPY --chown=myuser:myuser . ./
RUN npm run build
CMD ["node", "dist/main.js"]
```

Comment on lines +119 to +131
- **Move `typescript` to `dependencies`**—keeps the single-stage Dockerfile but bloats the runtime image with the TypeScript compiler and its tooling. Runtime never uses these, so the extra size is wasted.
<details><summary>Example</summary>

```json
{
"dependencies": {
"apify": "^3.4.0",
"typescript": "^5.5.0"
}
}
```

</details>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- **Move `typescript` to `dependencies`**—keeps the single-stage Dockerfile but bloats the runtime image with the TypeScript compiler and its tooling. Runtime never uses these, so the extra size is wasted.
<details><summary>Example</summary>
```json
{
"dependencies": {
"apify": "^3.4.0",
"typescript": "^5.5.0"
}
}
```
</details>
- **Move `typescript` to `dependencies`**—keeps the single-stage Dockerfile but bloats the runtime image with the TypeScript compiler and its tooling. Runtime never uses these, so the extra size is wasted.
<details>
<summary>Example</summary>
```json
{
"dependencies": {
"apify": "^3.4.0",
"typescript": "^5.5.0"
}
}
```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants