一键导入
create-composition
Use when creating a new Docker Compose-based Ansible role (composition-*) in this repo, given a GitHub repo or installation docs link.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when creating a new Docker Compose-based Ansible role (composition-*) in this repo, given a GitHub repo or installation docs link.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Use when deploying Ansible playbooks to hosts or groups, selecting the right playbook file, or targeting specific roles or role types with tags.
Use when checking if infra hosts are reachable, if compositions are running and healthy, or to identify cnames in host_vars that don't correspond to a running composition on that host.
基于 SOC 职业分类
| name | create-composition |
| description | Use when creating a new Docker Compose-based Ansible role (composition-*) in this repo, given a GitHub repo or installation docs link. |
Compositions are Ansible roles (roles/composition-<name>/) that deploy a Docker Compose app. The composition-common dependency handles ZFS datasets, directory creation, and the Docker network — the role only needs its own templates and app-specific tasks.
Fetch the project's GitHub page or install docs. Look for:
docker-compose.yml — use as the starting templateloadbalancer.server.port)Then probe the image to determine the correct healthcheck tool:
scripts/check-image-healthcheck-tools.sh <image>:<tag>
This reports the OS and available tools (bash, wget, curl, nc) and recommends the right healthcheck pattern. Use the recommendation when writing the healthcheck: block in docker-compose.yaml.j2. See .claude/rules/docker-healthcheck.md for the patterns.
roles/composition-<name>/
defaults/main.yaml
meta/main.yaml
tasks/main.yaml
templates/docker-compose.yaml.j2
templates/environment_vars.j2
README.md
Use templates/.env instead of environment_vars.j2 only if the app hard-requires a file named .env (e.g. immich).
defaults/main.yaml# Composition name (used by composition-common dependency)
composition_name: <name>
composition_<name>_subdomains:
- <name>
# Vault-backed secrets reference the vault_ prefix:
# composition_<name>_secret_key: "{{ vault_<name>_secret_key }}"
meta/main.yamldependencies:
- role: composition-common
vars:
composition_name: <name>
tasks/main.yaml# code: language=ansible
# ----------------------------
# Core tasks
# ----------------------------
- name: "Create compose file"
ansible.builtin.template:
src: docker-compose.yaml.j2
dest: "{{ composition_root }}/docker-compose.yaml"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: "0644"
- name: "Create .env file"
ansible.builtin.template:
src: environment_vars.j2
dest: "{{ composition_root }}/.environment_vars"
owner: "{{ ansible_user }}"
group: "{{ ansible_user }}"
mode: "0644"
# ----------------------------
# Specific tasks
# ----------------------------
# Uncomment if the app needs subdirectories under config/:
# - name: Create directories
# ansible.builtin.file:
# path: "{{ composition_config }}/{{ dir_item }}"
# state: directory
# mode: "0755"
# loop_control:
# loop_var: dir_item
# loop:
# - data
- name: Run Configure DNS role
ansible.builtin.include_role:
name: "network-register-subdomain"
vars:
configure_dns_subdomains: "{{ composition_<name>_subdomains }}"
# ----------------------------
# Start composition
# ----------------------------
- name: Start Docker Compose project
community.docker.docker_compose_v2:
project_src: "{{ composition_root }}"
state: present
build: always
remove_orphans: true
notify: Restart Traefik
templates/docker-compose.yaml.j2# code: language=ansible
name: "{{ composition_name }}"
services:
<name>:
container_name: <name>
image: <image>:<tag>
restart: unless-stopped
env_file: .environment_vars
labels:
- "traefik.enable=true"
- "traefik.http.routers.<name>.rule=Host(`<name>.{{ domainname_infra }}`)"
- "traefik.http.routers.<name>.tls=true"
- "traefik.http.routers.<name>.tls.certresolver=letsencrypt"
- "traefik.http.services.<name>.loadbalancer.server.port=<PORT>"
volumes:
- "{{ composition_config }}:/data"
networks:
- "{{ default_docker_network }}"
networks:
"{{ default_docker_network }}":
external: true
Key variables available in templates:
composition_name — Docker Compose project namecomposition_root — /{{ compositions_dataset }}/<name> — where the compose file livescomposition_config — {{ composition_root }}/config — mount point for app datadomainname_infra — internal Tailscale domaindefault_docker_network — always the same, allowing apps to talk to each other.ansible_user — the target host userIf the app doesn't need Traefik (internal-only), omit labels: entirely. If it binds a host port, use "127.0.0.1:<host>:<container>" under ports:.
templates/environment_vars.j2TZ="Europe/Berlin"
# Add app env vars here; reference Ansible vars with {{ var_name }}
Store encrypted secrets in the target host's vault file:
inventory/host_vars/<host>/vault_<name>.yaml
Generate and encrypt:
ansible-vault encrypt_string "$(openssl rand -hex 32)" --name 'vault_<name>_secret_key'
If this a key or password that will never be used by a user in a GUI then you may create and commit them without interaction.
Reference in defaults/main.yaml:
<name>_secret_key: "{{ vault_<name>_secret_key }}"
Reference in templates/environment_vars.j2:
SECRET_KEY="{{ <name>_secret_key }}"
If the user has soecified a host, add to roles: in playbooks/hosts/<host>/core.yaml:
- role: composition-<name>
tags: [composition, composition-<name>]
Multiple services (app + postgres/redis): Keep all in one docker-compose.yaml.j2. Add a Create directories task for the DB data dir. Set DB_DATA_LOCATION="{{ composition_config }}/postgres" in the env template.
Multiple subdomains: Add entries to the subdomains list in defaults. Add extra Traefik router label sets for each subdomain.
No web UI / no Traefik: Ask the user if they would like to create a subdomain. If they decline, omit the labels: block and DNS task entirely.