{"id":"cf921f9e-7686-4583-aaa1-2e83eaabc319","shortId":"SBcbyH","kind":"skill","title":"docker","tagline":"Auto-activate for Dockerfile, docker-compose.yml, docker-compose.yaml, .dockerignore. Docker expertise: multi-stage builds, distroless images, Compose, BuildKit, and container optimization. Use when: writing Dockerfiles, optimizing image size, configuring docker-compose, using Bu","description":"# Docker\n\n## Overview\n\nDocker provides OS-level virtualization via containers. This skill covers Dockerfile best practices, multi-stage builds, distroless images, Compose orchestration, and BuildKit optimizations.\n\n---\n\n## Multi-Stage Build Quick Reference\n\nMulti-stage builds separate build-time dependencies from the runtime image, producing minimal production images.\n\n```dockerfile\n# ---- Stage 1: dependency builder ----\nFROM python:3.12-slim-bookworm AS builder\nWORKDIR /app\nRUN pip install --no-cache-dir uv\nCOPY pyproject.toml uv.lock ./\n# Cache uv's package download cache across builds\nRUN --mount=type=cache,target=/root/.cache/uv \\\n    uv sync --frozen --no-dev --no-editable\n\n# ---- Stage 2: runtime (distroless, non-root) ----\nFROM gcr.io/distroless/python3-debian12:nonroot\nWORKDIR /app\nCOPY --from=builder /app/.venv/lib/python3.12/site-packages /usr/lib/python3.12/site-packages\nCOPY src/ ./src/\nENTRYPOINT [\"python\", \"-m\", \"myapp\"]\n```\n\nKey rules:\n\n- Name every stage (`AS builder`, `AS runner`, etc.).\n- Only the final stage ends up in the shipped image.\n- Copy only what is needed from earlier stages with `COPY --from=`.\n\n---\n\n## Compose Quick Reference\n\n```yaml\n# compose.yml\nservices:\n  app:\n    build: .\n    image: myapp:dev\n    ports:\n      - \"8000:8000\"\n    environment:\n      DATABASE_URL: postgresql://app:secret@db:5432/mydb\n    depends_on:\n      db:\n        condition: service_healthy\n    restart: unless-stopped\n\n  db:\n    image: postgres:16-alpine\n    environment:\n      POSTGRES_USER: app\n      POSTGRES_PASSWORD: secret\n      POSTGRES_DB: mydb\n    volumes:\n      - pg_data:/var/lib/postgresql/data\n    healthcheck:\n      test: [\"CMD-SHELL\", \"pg_isready -U app -d mydb\"]\n      interval: 10s\n      timeout: 5s\n      retries: 5\n\nvolumes:\n  pg_data:\n```\n\n```bash\n# Common Compose commands\ndocker compose up -d          # start detached\ndocker compose logs -f app    # follow service logs\ndocker compose exec app bash  # shell into running container\ndocker compose down -v        # stop and remove volumes\ndocker compose build --no-cache  # full rebuild\n```\n\n---\n\n## BuildKit Cache Mounts\n\n`--mount=type=cache` persists a directory between builds so package managers do not re-download.\n\n```dockerfile\n# uv (Python)\nRUN --mount=type=cache,target=/root/.cache/uv \\\n    uv sync --frozen --no-dev\n\n# pip\nRUN --mount=type=cache,target=/root/.cache/pip \\\n    pip install -r requirements.txt\n\n# apt\nRUN --mount=type=cache,target=/var/cache/apt,sharing=locked \\\n    --mount=type=cache,target=/var/lib/apt,sharing=locked \\\n    apt-get update && apt-get install -y --no-install-recommends curl\n\n# npm\nRUN --mount=type=cache,target=/root/.npm \\\n    npm ci --omit=dev\n\n# Go modules\nRUN --mount=type=cache,target=/go/pkg/mod \\\n    go mod download\n```\n\nEnable BuildKit (default in Docker 23+):\n\n```bash\nexport DOCKER_BUILDKIT=1\ndocker build .\n# or\ndocker buildx build .\n```\n\n---\n\n## Production Patterns\n\n### uv Package Manager\n\n`uv` is a fast Python package/project manager. Use it as the build-stage installer, then copy the resulting `.venv` into the runtime stage.\n\n```dockerfile\nFROM python:3.12-slim-bookworm AS builder\nWORKDIR /app\nRUN pip install --no-cache-dir uv\nCOPY pyproject.toml uv.lock ./\nRUN --mount=type=cache,target=/root/.cache/uv \\\n    uv sync --frozen --no-dev --no-editable\n```\n\n### Distroless Base Images\n\n| Image | Use case |\n|-------|----------|\n| `gcr.io/distroless/static-debian12:nonroot` | Statically compiled binaries (Go, Rust) |\n| `gcr.io/distroless/base-debian12:nonroot` | Dynamically linked, needs glibc |\n| `gcr.io/distroless/python3-debian12:nonroot` | Python applications |\n| `gcr.io/distroless/nodejs22-debian12:nonroot` | Node.js applications |\n\nAlways use the `:nonroot` tag — the image user is UID 65532.\n\n### tini Init\n\n`tini` properly forwards signals and reaps zombie processes. Use it when the base image does not include an init system (e.g., non-distroless slim images).\n\n```dockerfile\nFROM python:3.12-slim-bookworm\nRUN apt-get update \\\n && apt-get install -y --no-install-recommends tini \\\n && rm -rf /var/lib/apt/lists/*\nENTRYPOINT [\"tini\", \"--\"]\nCMD [\"python\", \"-m\", \"myapp\"]\n```\n\nDistroless images already run as non-root; for non-distroless images add tini + explicit non-root user.\n\n### Non-Root User (UID 65532)\n\nUID 65532 is the `nonroot` user in distroless images. Align custom user IDs with this value for consistency.\n\n```dockerfile\n# For non-distroless images\nRUN groupadd --gid 65532 nonroot \\\n && useradd --uid 65532 --gid 65532 --no-create-home --shell /bin/false nonroot\nUSER nonroot\n```\n\n### .dockerignore\n\n```text\n.git\n.github\n.venv\n__pycache__\n*.pyc\n*.pyo\nnode_modules\n.env\n.env.*\nDockerfile\ndocker-compose*.yml\ncompose*.yml\n.dockerignore\ncoverage\n.pytest_cache\n.mypy_cache\n.ruff_cache\ndist\nbuild\n*.md\n!README.md\n```\n\n<workflow>\n\n## Workflow\n\n1. **Write Dockerfile** — multi-stage, pin base tags, use cache mounts.\n2. **Write .dockerignore** — exclude `.git`, `.env`, `node_modules`, `__pycache__`.\n3. **Build locally** — `docker buildx build -t myimage:dev .`\n4. **Inspect** — `docker image inspect myimage:dev` for size; `dive myimage:dev` for layer breakdown.\n5. **Run as non-root check** — `docker run --rm myimage:dev id` should print `uid=65532`.\n6. **Compose integration** — use `compose.yml` with health checks and `depends_on` conditions.\n\n</workflow>\n\n<guardrails>\n\n## Guardrails\n\n- **Always multi-stage** — never ship build tools, compilers, or dev dependencies in the final image.\n- **Always non-root** — use `:nonroot` distroless tags or add an explicit non-root user (UID 65532). Never run as root in production.\n- **Always .dockerignore** — prevents leaking `.env`, secrets, `.git`, and large directories into the build context.\n- **Pin base image tags** — use full tags (`python:3.12-slim-bookworm`, not `python:latest`) to ensure reproducible builds.\n- **Use BuildKit cache mounts** for all package managers to keep CI builds fast.\n- **No secrets in layers** — never `COPY .env` or `RUN echo SECRET=...`. Use `--secret` mount or runtime injection.\n\n</guardrails>\n\n<validation>\n\n## Validation Checkpoint\n\nBefore delivering Dockerfile or Compose config, verify:\n\n- [ ] Multi-stage build separates builder from runtime stage\n- [ ] Base image tags are pinned (no `:latest`)\n- [ ] `.dockerignore` is present and excludes secrets/caches\n- [ ] Final image runs as non-root (UID 65532 or equivalent)\n- [ ] No secrets baked into layers\n- [ ] Cache mounts used for package manager steps\n- [ ] Health check defined in Compose or Dockerfile for long-running services\n\n</validation>\n\n---\n\n## References Index\n\nFor detailed guides and code examples, refer to the following documents in `references/`:\n\n- **[Dockerfile Patterns](references/dockerfile.md)**\n  - Multi-stage builds, distroless images, TARGETARCH for multi-arch, non-root users, tini init, .dockerignore, uv cache mounts.\n- **[Compose](references/compose.md)**\n  - docker-compose.yml patterns, service dependencies, volumes, networks, health checks.\n- **[Optimization](references/optimization.md)**\n  - Layer caching, BuildKit cache mounts, minimal base images, bytecode compilation, reducing image size.\n\n---\n\n<example>\n\n## Example: Multi-Stage Python Dockerfile\n\n```dockerfile\n# Build stage\nFROM python:3.12-slim-bookworm AS builder\nWORKDIR /app\nRUN pip install --no-cache-dir uv\nCOPY pyproject.toml uv.lock ./\nRUN --mount=type=cache,target=/root/.cache/uv \\\n    uv sync --frozen --no-dev --no-editable\n\n# Runtime stage\nFROM gcr.io/distroless/python3-debian12:nonroot\nWORKDIR /app\nCOPY --from=builder /app/.venv/lib/python3.12/site-packages /usr/lib/python3.12/site-packages\nCOPY src/ ./src/\nENTRYPOINT [\"python\", \"-m\", \"myapp\"]\n```\n\n</example>\n\n---\n\n## Official References\n\n- <https://docs.docker.com/>\n- <https://github.com/GoogleContainerTools/distroless>\n\n## Shared Styleguide Baseline\n\n- Use shared styleguides for generic language/framework rules to reduce duplication in this skill.\n- [General Principles](https://github.com/cofin/flow/blob/main/templates/styleguides/general.md)\n- [Docker](https://github.com/cofin/flow/blob/main/templates/styleguides/tools/docker.md)\n- Keep this skill focused on tool-specific workflows, edge cases, and integration details.","tags":["docker","flow","cofin","agent-skills","ai-agents","beads","claude-code","codex","cursor","developer-tools","gemini-cli","opencode"],"capabilities":["skill","source-cofin","skill-docker","topic-agent-skills","topic-ai-agents","topic-beads","topic-claude-code","topic-codex","topic-cursor","topic-developer-tools","topic-gemini-cli","topic-opencode","topic-plugin","topic-slash-commands","topic-spec-driven-development"],"categories":["flow"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/cofin/flow/docker","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add cofin/flow","source_repo":"https://github.com/cofin/flow","install_from":"skills.sh"}},"qualityScore":"0.455","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 11 github stars · SKILL.md body (8,218 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-24T01:03:26.264Z","embedding":null,"createdAt":"2026-04-23T13:03:59.027Z","updatedAt":"2026-04-24T01:03:26.264Z","lastSeenAt":"2026-04-24T01:03:26.264Z","tsv":"'/app':100,147,457,1012,1046 '/app/.venv/lib/python3.12/site-packages':151,1050 '/bin/false':650 '/cofin/flow/blob/main/templates/styleguides/general.md)':1085 '/cofin/flow/blob/main/templates/styleguides/tools/docker.md)':1089 '/distroless/base-debian12:nonroot':500 '/distroless/nodejs22-debian12:nonroot':512 '/distroless/python3-debian12:nonroot':145,507,1044 '/distroless/static-debian12:nonroot':492 '/go/pkg/mod':397 '/googlecontainertools/distroless':1064 '/root/.cache/pip':344 '/root/.cache/uv':125,331,474,1029 '/root/.npm':385 '/src':155,1054 '/usr/lib/python3.12/site-packages':152,1051 '/var/cache/apt':355 '/var/lib/apt':362 '/var/lib/apt/lists':578 '/var/lib/postgresql/data':240 '1':88,411,686 '10s':253 '16':225 '2':136,698 '23':406 '3':707 '3.12':93,450,557,823,1005 '4':716 '5':257,731 '5432/mydb':211 '5s':255 '6':748 '65532':525,610,612,638,642,644,747,794,903 '8000':203,204 'across':118 'activ':4 'add':598,786 'align':620 'alpin':226 'alreadi':587 'alway':515,761,777,801 'app':197,208,230,249,275,282 'applic':509,514 'apt':349,366,370,563,567 'apt-get':365,369,562,566 'arch':958 'auto':3 'auto-activ':2 'bake':908 'base':485,540,693,816,882,987 'baselin':1067 'bash':261,283,407 'best':50 'binari':495 'bookworm':96,453,560,826,1008 'breakdown':730 'bu':35 'build':15,55,66,72,75,119,198,298,314,413,417,435,682,708,712,767,813,833,845,876,951,1001 'build-stag':434 'build-tim':74 'builder':90,98,150,166,455,878,1010,1049 'buildkit':19,61,304,402,410,835,983 'buildx':416,711 'bytecod':989 'cach':106,112,117,123,301,305,309,329,342,353,360,383,395,463,472,676,678,680,696,836,911,967,982,984,1018,1027 'case':489,1100 'check':737,755,919,978 'checkpoint':865 'ci':387,844 'cmd':244,581 'cmd-shell':243 'code':936 'command':264 'common':262 'compil':494,769,990 'compos':18,33,58,191,263,266,272,280,289,297,669,671,749,870,922,969 'compose.yml':195,752 'condit':215,759 'config':871 'configur':30 'consist':628 'contain':21,45,287 'context':814 'copi':109,148,153,180,189,439,466,852,1021,1047,1052 'cover':48 'coverag':674 'creat':647 'curl':378 'custom':621 'd':250,268 'data':239,260 'databas':206 'db':210,214,222,235 'default':403 'defin':920 'deliv':867 'depend':77,89,212,757,772,974 'detach':270 'detail':933,1103 'dev':131,201,337,389,480,715,722,727,742,771,1035 'dir':107,464,1019 'directori':312,810 'dist':681 'distroless':16,56,138,484,551,585,596,618,633,783,952 'dive':725 'docker':1,10,32,36,38,265,271,279,288,296,405,409,412,415,668,710,718,738,1086 'docker-compos':31,667 'docker-compose.yaml':8 'docker-compose.yml':7,971 'dockerfil':6,26,49,86,323,447,554,629,666,688,868,924,945,999,1000 'dockerignor':9,654,673,700,802,889,965 'docs.docker.com':1061 'document':942 'download':116,322,400 'duplic':1077 'dynam':501 'e.g':548 'earlier':186 'echo':856 'edg':1099 'edit':134,483,1038 'enabl':401 'end':174 'ensur':831 'entrypoint':156,579,1055 'env':664,665,703,805,853 'environ':205,227 'equival':905 'etc':169 'everi':163 'exampl':937,994 'exclud':701,893 'exec':281 'expertis':11 'explicit':600,788 'export':408 'f':274 'fast':426,846 'final':172,775,895 'focus':1093 'follow':276,941 'forward':530 'frozen':128,334,477,1032 'full':302,820 'gcr.io':144,491,499,506,511,1043 'gcr.io/distroless/base-debian12:nonroot':498 'gcr.io/distroless/nodejs22-debian12:nonroot':510 'gcr.io/distroless/python3-debian12:nonroot':143,505,1042 'gcr.io/distroless/static-debian12:nonroot':490 'general':1081 'generic':1072 'get':367,371,564,568 'gid':637,643 'git':656,702,807 'github':657 'github.com':1063,1084,1088 'github.com/cofin/flow/blob/main/templates/styleguides/general.md)':1083 'github.com/cofin/flow/blob/main/templates/styleguides/tools/docker.md)':1087 'github.com/googlecontainertools/distroless':1062 'glibc':504 'go':390,398,496 'groupadd':636 'guardrail':760 'guid':934 'health':754,918,977 'healthcheck':241 'healthi':217 'home':648 'id':623,743 'imag':17,28,57,81,85,179,199,223,486,487,521,541,553,586,597,619,634,719,776,817,883,896,953,988,992 'includ':544 'index':931 'init':527,546,964 'inject':863 'inspect':717,720 'instal':103,346,372,376,437,460,569,573,1015 'integr':750,1102 'interv':252 'isreadi':247 'keep':843,1090 'key':160 'language/framework':1073 'larg':809 'latest':829,888 'layer':729,850,910,981 'leak':804 'level':42 'link':502 'local':709 'lock':357,364 'log':273,278 'long':927 'long-run':926 'm':158,583,1057 'manag':317,422,429,841,916 'md':683 'minim':83,986 'mod':399 'modul':391,663,705 'mount':121,306,307,327,340,351,358,381,393,470,697,837,860,912,968,985,1025 'multi':13,53,64,70,690,763,874,949,957,996 'multi-arch':956 'multi-stag':12,52,63,69,689,762,873,948,995 'myapp':159,200,584,1058 'mydb':236,251 'myimag':714,721,726,741 'mypi':677 'name':162 'need':184,503 'network':976 'never':765,795,851 'no-cach':299 'no-cache-dir':104,461,1016 'no-create-hom':645 'no-dev':129,335,478,1033 'no-edit':132,481,1036 'no-install-recommend':374,571 'node':662,704 'node.js':513 'non':140,550,591,595,602,606,632,735,779,790,900,960 'non-distroless':549,594,631 'non-root':139,590,601,605,734,778,789,899,959 'nonroot':518,615,639,651,653,782 'npm':379,386 'offici':1059 'omit':388 'optim':22,27,62,979 'orchestr':59 'os':41 'os-level':40 'overview':37 'packag':115,316,421,840,915 'package/project':428 'password':232 'pattern':419,946,972 'persist':310 'pg':238,246,259 'pin':692,815,886 'pip':102,338,345,459,1014 'port':202 'postgr':224,228,231,234 'practic':51 'present':891 'prevent':803 'principl':1082 'print':745 'process':535 'produc':82 'product':84,418,800 'proper':529 'provid':39 'pyc':660 'pycach':659,706 'pyo':661 'pyproject.toml':110,467,1022 'pytest':675 'python':92,157,325,427,449,508,556,582,822,828,998,1004,1056 'quick':67,192 'r':347 're':321 're-download':320 'readme.md':684 'reap':533 'rebuild':303 'recommend':377,574 'reduc':991,1076 'refer':68,193,930,938,944,1060 'references/compose.md':970 'references/dockerfile.md':947 'references/optimization.md':980 'remov':294 'reproduc':832 'requirements.txt':348 'restart':218 'result':441 'retri':256 'rf':577 'rm':576,740 'root':141,592,603,607,736,780,791,798,901,961 'ruff':679 'rule':161,1074 'run':101,120,286,326,339,350,380,392,458,469,561,588,635,732,739,796,855,897,928,1013,1024 'runner':168 'runtim':80,137,445,862,880,1039 'rust':497 'secret':209,233,806,848,857,859,907 'secrets/caches':894 'separ':73,877 'servic':196,216,277,929,973 'share':356,363,1065,1069 'shell':245,284,649 'ship':178,766 'signal':531 'size':29,724,993 'skill':47,1080,1092 'skill-docker' 'slim':95,452,552,559,825,1007 'slim-bookworm':94,451,558,824,1006 'source-cofin' 'specif':1097 'src':154,1053 'stage':14,54,65,71,87,135,164,173,187,436,446,691,764,875,881,950,997,1002,1040 'start':269 'static':493 'step':917 'stop':221,292 'styleguid':1066,1070 'sync':127,333,476,1031 'system':547 'tag':519,694,784,818,821,884 'target':124,330,343,354,361,384,396,473,1028 'targetarch':954 'test':242 'text':655 'time':76 'timeout':254 'tini':526,528,575,580,599,963 'tool':768,1096 'tool-specif':1095 'topic-agent-skills' 'topic-ai-agents' 'topic-beads' 'topic-claude-code' 'topic-codex' 'topic-cursor' 'topic-developer-tools' 'topic-gemini-cli' 'topic-opencode' 'topic-plugin' 'topic-slash-commands' 'topic-spec-driven-development' 'type':122,308,328,341,352,359,382,394,471,1026 'u':248 'uid':524,609,611,641,746,793,902 'unless':220 'unless-stop':219 'updat':368,565 'url':207 'use':23,34,430,488,516,536,695,751,781,819,834,858,913,1068 'user':229,522,604,608,616,622,652,792,962 'useradd':640 'uv':108,113,126,324,332,420,423,465,475,966,1020,1030 'uv.lock':111,468,1023 'v':291 'valid':864 'valu':626 'venv':442,658 'verifi':872 'via':44 'virtual':43 'volum':237,258,295,975 'workdir':99,146,456,1011,1045 'workflow':685,1098 'write':25,687,699 'y':373,570 'yaml':194 'yml':670,672 'zombi':534","prices":[{"id":"5d346688-3834-4f90-97e9-743f3f29f632","listingId":"cf921f9e-7686-4583-aaa1-2e83eaabc319","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"cofin","category":"flow","install_from":"skills.sh"},"createdAt":"2026-04-23T13:03:59.027Z"}],"sources":[{"listingId":"cf921f9e-7686-4583-aaa1-2e83eaabc319","source":"github","sourceId":"cofin/flow/docker","sourceUrl":"https://github.com/cofin/flow/tree/main/skills/docker","isPrimary":false,"firstSeenAt":"2026-04-23T13:03:59.027Z","lastSeenAt":"2026-04-24T01:03:26.264Z"}],"details":{"listingId":"cf921f9e-7686-4583-aaa1-2e83eaabc319","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cofin","slug":"docker","github":{"repo":"cofin/flow","stars":11,"topics":["agent-skills","ai-agents","beads","claude-code","codex","context-driven-development","cursor","developer-tools","gemini-cli","opencode","plugin","slash-commands","spec-driven-development","subagents","tdd","workflow"],"license":"apache-2.0","html_url":"https://github.com/cofin/flow","pushed_at":"2026-04-19T23:22:27Z","description":"Context-Driven Development toolkit for AI agents — spec-first planning, TDD workflow, and Beads integration.","skill_md_sha":"ec71c640418cb9cee662267c89d61be68858e6ac","skill_md_path":"skills/docker/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cofin/flow/tree/main/skills/docker"},"layout":"multi","source":"github","category":"flow","frontmatter":{"name":"docker","description":"Auto-activate for Dockerfile, docker-compose.yml, docker-compose.yaml, .dockerignore. Docker expertise: multi-stage builds, distroless images, Compose, BuildKit, and container optimization. Use when: writing Dockerfiles, optimizing image size, configuring docker-compose, using BuildKit features, or deploying containerized applications. Produces optimized Dockerfiles with multi-stage builds, Compose configurations, and BuildKit patterns. Not for Podman (see podman) or container orchestration (see gke/cloud-run)."},"skills_sh_url":"https://skills.sh/cofin/flow/docker"},"updatedAt":"2026-04-24T01:03:26.264Z"}}