This skill reviews and rewrites Okteto Manifests (okteto.yaml) so they follow Okteto's documented performance best practices, together with the .dockerignore, .oktetoignore, and .stignore files that go with them. Slow environments almost always trace to one of three causes: unpinned images that defeat node cache reuse, a bloated build or sync context, or dependencies that are re-downloaded on every start. This skill removes those.
Full field reference, copy-paste ignore-file templates, and a worked manifest live in reference/okteto-manifest-fields.md, next to this file. Read it when you need the exact syntax; the rules here are enough to act.
Operating rules
These rules prevent the mistakes that make environments slow. Apply every one to every manifest you produce.
- Verify against the repo — never invent. Read the Dockerfile(s), the dependency manifest (
package.json,go.mod,pom.xml,requirements.txt), and the existingokteto.yamlfirst. Every service name, image, sync path, volume, and cache dir must trace to something in the repo. - Pin every image. Never
:latest— use a version tag or an@sha256digest. When a service has abuild:entry, wire its dev container to it with${OKTETO_BUILD_<NAME>_IMAGE}(uppercase the build name,-becomes_: buildapi→${OKTETO_BUILD_API_IMAGE}, buildweb-dev→${OKTETO_BUILD_WEB_DEV_IMAGE}). A dev container on a plain toolchain image (nobuild:) just pins that image. - Context and sync are the highest-impact levers — and the two ignore files read in opposite order.
.dockerignore:*first, then!-include only build inputs (Docker applies the last matching rule)..stignore:!-include the active source first, then*(Syncthing applies the first matching rule;*first syncs nothing). Never sync artifacts, dependency directories, or.git. Add a.oktetoignorewhen the deploy or test context is large. - Persist dependencies and caches — don't re-fetch them. Put dependency and build-cache directories in
dev.<svc>.volumes, mirror them intest.<name>.cachesfor test containers, and use BuildKit cache mounts in the Dockerfile. See the per-language cache map. - Always set
resources.requestsandresources.limitson dev containers. Both are unset by default, which starves the scheduler and causes slow orPendingstarts. - Get
forwardvsreversedirection right.forwardislocalPort:remotePort(reach a container port fromlocalhost).reverseisremotePort:localPort(send from the container back to your machine, e.g. a debugger callback). Swapping them silently breaks the connection. - Order the Dockerfile by change frequency and never
COPY . .. Base image and system packages first, dependency install next, source copy last. Copy only what each stage needs. This is what makes Okteto Smart Builds and layer caching effective. - Validate and rebuild what you changed — without being asked.
okteto.yaml, the Dockerfile, and.dockerignoreare build inputs: nothing syncs them, so the environment is stale until it is rebuilt. As soon as the manifest is written, runokteto validate(it works offline). Then rebuild and redeploy the way theoktetoskill requires —okteto build <service>andokteto deploy --wait— and report the outcome: endpoints on success, the error and your fix on failure. Never runokteto up; it is interactive and would hang.
Workflow
- Discover the stack. Identify each service, its language/build tool, its Dockerfile, and its source layout from the repo (rule 1). If there is no manifest at all, stop and hand off to
okteto-onboarding; come back to optimize its draft. - Rewrite
build→deploy→dev→test. See Manifest shape. Apply the best-practice levers as you write each section. - Write the ignore files (
.dockerignore,.stignore, and.oktetoignoreif needed) in the order rule 3 gives. The reference has copy-paste templates. - Run the pre-return review checklist, then
okteto validate, then rebuild and redeploy (rule 8).
Manifest shape
| Section | Purpose | Optimization focus |
|---|---|---|
build |
Images Okteto builds for each service | Pin bases, order layers, cache mounts, a target per stage for a -dev image |
deploy |
How the stack is provisioned (Helm/manifests/commands) | Wire images with ${OKTETO_BUILD_<NAME>_IMAGE} |
dev.<svc> |
Live-edit config: image, command, sync, forward/reverse, volumes, resources |
Sync source only; persist deps in volumes; set resources; correct port direction |
test.<name> |
Test containers run via Remote Execution | caches for dependency/build dirs; pin image |
Best-practice levers
Fourteen practices from the source doc, grouped. One-line reminders here; full examples in the reference file.
Images & build
| # | Practice | Do this |
|---|---|---|
| 1 | Pin images | Version tag or @sha256; never :latest |
| 2 | Okteto Smart Builds | Let identical builds be skipped from cache; don't defeat it with churny layers |
| 3 | Order layers by change frequency | Base + system packages first, deps next, source last |
| 4 | Avoid COPY . . |
Copy only build inputs (COPY package.json ., then COPY src/ src/) |
| 5 | Avoid recursive ops | RUN chown -R → COPY --chown=user:group |
| 6 | BuildKit cache mounts | RUN --mount=type=cache,target=<dep-or-build-cache> |
Context & sync (highest impact)
| # | Practice | Do this |
|---|---|---|
| 7 | .dockerignore |
* first, then !-include only build inputs (last match wins) |
| 8 | .oktetoignore |
.dockerignore syntax with [deploy] / [test] sections |
| 9 | .stignore |
!-include active source first, then * (first match wins); never artifacts, deps, or .git |
| 10 | Precopy source into dev image | Multi-stage: a -dev build target that already contains the source |
Data & environment
| # | Practice | Do this |
|---|---|---|
| 11 | Volume Snapshots over seed scripts | Preload databases from a snapshot instead of slow seed scripts |
| 12 | Okteto Divert | When full isolation isn't required, route into a shared environment |
Dev container & tests
| # | Practice | Do this |
|---|---|---|
| 13 | dev.<svc>.volumes |
Persist dep/cache dirs across okteto up sessions |
| 14 | test.<name>.caches |
Cache dep/build dirs across test runs |
Also enforce, from the Okteto Manifest reference: resources.requests and resources.limits on every dev container, and correct forward/reverse direction (Operating rules 5–6).
Per-language dependency & cache directories
Persist these in dev.<svc>.volumes and test.<name>.caches, and mount them as BuildKit caches (more stacks in the reference):
| Stack | Dependency / cache directories |
|---|---|
| Node.js | node_modules, ~/.npm (or .yarn/cache) |
| Go | /go/pkg/mod, /root/.cache/go-build |
| Java / Maven | /root/.m2 |
| Python | ~/.cache/pip, the virtualenv / .venv |
Pre-return review checklist
Do not hand back a manifest until all ten pass. Report each result.
- No
:latestanywhere inbuildordevimages — every image is a version tag or@sha256digest. dev.<svc>.imageis wired via${OKTETO_BUILD_<NAME>_IMAGE}(not a hardcoded tag) for every service that has abuild:entry.syncis scoped to source, and the.stignoreexcludes artifacts, dependency directories, and.git— with any!includes before a catch-all*.- Dependency/build directories are in
dev.<svc>.volumes(see the cache map) so they survive restarts. resources.requestsandresources.limitsare both present on each dev container.forward(local:remote) andreverse(remote:local) point the right way.- A
.dockerignorescopes the build context —*first, then!-includes for the build inputs only. test.<name>.cachesis set for every test container (where tests exist).- Dockerfiles are layer-ordered and free of
COPY . .and recursiveRUN chown -R. okteto validatepasses on the result, and the rebuild/redeploy from rule 8 is done or under way.
Related skills
okteto-onboarding— discovers services and drafts a firstokteto.yamlon a repo that has none. It runs first; this skill optimizes its output once the draft deploys.okteto— deploying, developing, and iterating in a live environment (okteto build,okteto deploy,okteto up,okteto exec). Rule 8's rebuild step follows its "when a change needs a rebuild" guidance.okteto-debugging— triaging a broken or unhealthy environment (CrashLoopBackOff,OOMKilled, stuck sync). Use it when the problem is runtime failure, not manifest performance.