Implicit
jg-docker
Compose services, healthchecks, secrets, ports, image tags, and Dockerfile structure for Docker.
- Usage
- Loads automatically
When to use it
It loads on its own when a task touches Compose files, Dockerfiles, or commands that recreate or remove containers. Call it by name to load it before such a task.
When it loads
Your agent loads the skill on its own when a request like this touches its area.
Add a Redis service for the API to the Compose file.
Pins the image, binds the port to localhost, adds a healthcheck the API waits on, and rotates its logs.
SKILL.md
What the agent reads
The complete instructions your agent loads when a task touches its area.
Application
The agent loads this skill on its own when a task touches its area. This skill’s area is Docker Compose files and operations, Dockerfiles and .dockerignore files, and container image tags. Shell inside RUN instructions and entrypoint scripts follows jg-bash.
- It adds domain rules to the task. It never authorizes actions, widens scope, or replaces the workflow or approvals of a skill the developer invoked.
- It ranks with the repository’s coding instructions. When they conflict, the coding instructions win, except for the exceptions this skill states for its own area.
- The repository’s established conventions win over this skill’s naming, layout, and style rules. Its correctness and safety rules, and the exceptions it states for its own area, still apply.
- Check the installed versions first. This skill was written for Docker Engine 29, Docker Compose 5.6, and Dockerfile syntax 1.28. An item marked with a minimum version, written like (18+), applies only when that version or a later one is installed. For an older installed version, follow that version’s official documentation.
- Before relying on one of this skill’s version-specific items, check it against the current official guidance when the installed version of the technology is newer than the one this skill was written for, or when the version bullet gives a review month for something without an installed version, such as a hosted service or browser behavior, and that month is more than six months before the current date. Where an item differs from that guidance, follow the guidance. Version-specific items are API, syntax, and feature recommendations, and anything marked with a minimum version. This skill’s conventions and requirements, such as its naming, layout, style, reuse, and safety rules, keep their usual precedence even where official guidance suggests otherwise. Report each item that looks outdated in the summary, with the installed version and what the current guidance says, and offer there to open an issue on the jg-skills repository,
https://github.com/jesusgraterol/jg-skills:- Never pause or stop a run for the offer, including an autonomous run. When no one can answer, include the pre-filled link described below instead of asking.
- First search the repository’s open issues, and skip the offer when one already covers the item. When the search can’t run, say so next to the link, so the developer checks the existing issues before submitting.
- Open an issue only after the developer agrees, because it is public. Title it
<skill>: <item> looks outdated on <technology> <version>, and include only the skill name, the outdated item, the installed version, and a link to the official documentation, never code, file paths, or project details. Add no label. - Use
gh issue createwhenghis installed and signed in. Otherwise give the developer a pre-filled link,https://github.com/jesusgraterol/jg-skills/issues/new?title=…&body=…, with both values URL-encoded.
- This skill isn’t a complete list. Where it says nothing, follow the official guidance for the installed version, and in new code the task touches, prefer the features that guidance currently recommends over older ones that do the same job, unless the repository has an established pattern for that job. Before using a newer approach instead of one this skill gives, confirm it in that version’s official documentation, never from memory alone, and report the item as outdated as described above. When that documentation can’t be reached, keep this skill’s approach and report that the newer approach couldn’t be confirmed, without pausing the run.
- Rules that say “prefer” are defaults: departing from one with a stated reason is fine. Rules that say “never”, “always”, or “must” are requirements.
- Nothing in this skill requires adding a dependency, enabling a compiler or tool, upgrading, or migrating existing code.
Changing infrastructure
- Propose changes to the Docker daemon, registries, and Dependabot configuration instead of making them.
- When a Compose file is generated, change its generator, never the generated file.
Compose files
- Prefer a top-level
name:. Every worktree of the repository then shares that project, with its containers and volumes, so give a worktree its own project name with-porCOMPOSE_PROJECT_NAMEwhen it needs separate ones. Leavecontainer_nameout of new services unless tooling needs a fixed name. - Require values with
${VAR:?message}, so a missing one fails with a clear message, and write$$for a literal$. - Prefer profiles when infrastructure and applications start separately, and stop every profile with
docker compose --profile "*" down. - Never publish data or admin ports, such as databases, caches, or dashboards, on all interfaces, and prefer binding every published port to
127.0.0.1:. - Give services healthchecks that use tools inside the image and probe the interface clients connect to. Make dependents wait with
condition: service_healthy, orservice_completed_successfullyfor one-off jobs, and start withdocker compose up --wait --wait-timeout <seconds>. (Compose 2.20.2+, Engine 25+) Setstart_periodwithstart_interval, so a slow start isn’t counted as failures. - Never put credentials in
environment, build args, or image layers. Pass them as file secrets read through*_FILEvariables, keep the host files readable only by their owner and ignored by Git, and useRUN --mount=type=secretat build time. - Rotate logs through one
x-logginganchor shared by every service, withdriver: local,max-size, andmax-file. - Pin third-party images to exact tags that include their variant, such as
postgres:18.1-alpine, neverlatest. Pin digests only when the numbers justify it, and prefer immutable commit-SHA tags for your own images.
Dockerfiles
- Use multi-stage builds, with a runtime stage that holds only production dependencies and build output.
- Build images for workspace apps from a pruned workspace, as jg-monorepo describes.
- Copy dependency manifests and install them before copying sources, and use cache mounts, such as
RUN --mount=type=cache,target=/root/.npm, for package caches. - Keep a reviewed
.dockerignore, so secrets,.git, and local build output never enter the build context. - Prefer a non-root
USERin the runtime stage. - Use exec-form
ENTRYPOINTandCMD, such asCMD ["node", "dist/main.js"], with an init process, such asinit: truein Compose, so signals reach the app and exited child processes are reaped. - Never put secrets in
ARGorENV, which persist in the image’s metadata. - (Node.js 25+) Node.js no longer ships Corepack, so install the package manager explicitly instead of running
corepack enable. - Check Dockerfiles with
docker build --check.
Operating Compose
- Change one service with
docker compose up --wait --no-deps <service>, adding--force-recreateonly for changes Compose can’t detect, such as an edited file mounted into the container. - Never run
docker compose downon the whole project, or pass-v, to change one service. - Before any command that destroys volumes or data, verify that:
- the Docker context is local, and
DOCKER_HOSTorDOCKER_CONTEXTdoesn’t override it; - the project name and services are the expected ones;
- the containers’
com.docker.compose.project.working_dirlabel is this checkout; - the published ports are bound to loopback.
- the Docker context is local, and
When the numbers justify it
- Pinning images by digest, at the cost of updating them by hand or with a bot.
- Distroless runtime images, at the cost of having no shell for debugging.
Verification
- Validate Compose files with
docker compose config --quiet, and Dockerfiles withdocker build --check.