1
0
mirror of https://github.com/bestnite/quadlet-migrator-skill.git synced 2026-04-26 18:41:52 +00:00

Refactor skill docs into core workflow and references

This commit is contained in:
2026-04-10 02:08:09 +10:00
parent 108e92be4f
commit 349b8ed436
6 changed files with 199 additions and 427 deletions
+37 -52
View File
@@ -2,19 +2,27 @@
Use this file when converting `docker-compose.yml` or `compose.yaml` into Quadlet units.
## General approach
## Contents
- Model each service first, then decide how to group all resulting containers into one or more `.pod` units.
- General defaults
- Field mapping
- Topology guidance
- Risky or lossy areas
## General Defaults
- Model each service first, then decide how to group the result into one or more `.pod` units.
- Prefer maintainable Quadlet output over mechanical one-to-one translation.
- Keep names stable and predictable. Generated filenames should use a shared project prefix.
- Keep filenames stable and predictable. Use a shared project prefix for generated artifacts.
- Do not add explicit runtime naming directives such as `PodName=`, `ServiceName=`, `ContainerName=`, or `NetworkName=` by default. Let Quadlet and Podman derive runtime names unless the user explicitly asks for custom naming or a reviewed requirement depends on it.
- When one deliverable set includes multiple Quadlet files, keep that shared prefix consistent so helper shell scripts can match them by shared-prefix globbing such as `<prefix>*`, instead of hardcoding exact filenames or assuming a fixed file count.
- Do not add `User=`, `Group=`, or `UserNS=keep-id` by default. Preserve or introduce runtime identity mapping only when the source explicitly requires it or when the user is working through permission or ownership behavior.
- For env-specific decisions, use `references/env-strategy.md` instead of expanding the env rules here.
## Field strategy
## Field Mapping
### `name`
- Use as an application prefix when it improves unit naming clarity.
- Use it as an application prefix when it improves naming clarity.
- Do not force a top-level project name into every filename if the user prefers shorter units.
### `services.<name>.image`
@@ -37,7 +45,7 @@ Use this file when converting `docker-compose.yml` or `compose.yaml` into Quadle
### `container_name`
- Drop it.
- Do not generate `ContainerName=`. Let Podman and systemd derive the runtime name.
- Do not generate `ContainerName=`.
### `ports`
@@ -61,33 +69,21 @@ Use this file when converting `docker-compose.yml` or `compose.yaml` into Quadle
- If the source uses a default network only, you often do not need a `.network` unit at all.
- If the source uses bridge networking for containers that can reasonably live in one pod, collapse that topology into one `.pod` so the containers share one network namespace.
- Create a `.network` unit only when services must be split across pods, or when explicit network isolation or custom network management is materially required.
- Do not add `NetworkName=` by default. Let Quadlet derive the network name unless the user explicitly asks for a custom network name or a reviewed requirement depends on it.
- Do not add `NetworkName=` by default.
- Containers in the same `.pod` can communicate over `127.0.0.1` / `localhost` because they share a network namespace.
- When services in the same `.pod` must accept connections from sibling containers, ensure they listen on `127.0.0.1` or `0.0.0.0`; if they listen only on another interface, sibling containers in the pod may not be able to reach them.
- When the upstream service supports configuring the listen address via environment variables or equivalent runtime settings, preserve or generate the necessary configuration instead of assuming the default bind address is correct.
- When `Pod=` is set, never generate `AddHost=` entries whose purpose is sibling-container discovery inside that pod; intra-pod communication should use `127.0.0.1` / `localhost` instead.
- `AddHost=` is a host-to-IP override, not an intra-pod service-discovery mechanism. Upstream Quadlet documents `AddHost=` in both `[Container]` and `[Pod]`, so do not describe `Pod=` as a blanket prohibition on `AddHost=` unless the upstream reference explicitly requires that for the case at hand.
- When `Pod=` is set, never generate `AddHost=` entries whose purpose is sibling-container discovery inside that pod. Intra-pod communication should use `127.0.0.1` / `localhost` instead.
- `AddHost=` is a host-to-IP override, not an intra-pod service-discovery mechanism. Do not describe `Pod=` as a blanket prohibition on `AddHost=` unless the upstream reference explicitly requires that for the case at hand.
- Containers in different pods must not be treated as reachable via `127.0.0.1` / `localhost`.
- When splitting services across multiple pods or preserving a shared bridge network, use container names, pod names, or explicit `NetworkAlias=` values on the shared network, or publish ports to the host boundary when that is the intended access pattern.
- Do not add `ServiceName=` or `PodName=` by default. If they are omitted, use Quadlet's derived names unless the user explicitly asks for custom runtime naming or a reviewed requirement depends on it.
- Do not add `ServiceName=` or `PodName=` by default.
- `ServiceName=` controls the generated systemd unit name only and must not be used as an application-facing network address.
- `PodName=` controls the Podman pod name only; it can participate in the chosen addressing strategy, but it does not determine the systemd service name.
### `environment`
### `environment`, `env_file`, and `.env` interpolation
- Small stable values can become one or more `Environment=` lines.
- Sensitive values should be moved to `EnvironmentFile=` unless the user explicitly wants them inline.
### `env_file`
- Prefer `EnvironmentFile=`.
- If there are multiple env files, preserve order and explain precedence if the user asks.
### `.env` interpolation
- Resolve only when you have the actual source values.
- If variables are missing, surface a missing-variable list.
- Never silently replace unknown values with blanks.
- Use `references/env-strategy.md` for detailed env handling, interpolation, sensitivity defaults, completeness checks, and missing-variable reporting.
### `profiles`
@@ -113,21 +109,32 @@ Use this file when converting `docker-compose.yml` or `compose.yaml` into Quadle
### `user`
- Do not add `User=` or `Group=` by default. Map them in `[Container]` only when the source explicitly requires a container runtime user mapping or when the user is addressing permission or ownership behavior, and not as a systemd service user substitute.
- Map `User=` and `Group=` only when the source explicitly requires a container runtime user mapping or when the user is addressing permission or ownership behavior.
- Do not use systemd `User=` to try to make a rootless Quadlet run as another login user.
- Do not add `UserNS=keep-id` by default. Consider it only when the user is working through rootless permission or ownership behavior and the reviewed topology benefits from preserving host identity semantics.
- Consider `UserNS=keep-id` only when the user is working through rootless permission or ownership behavior and the reviewed topology benefits from preserving host identity semantics.
### unsupported or risky fields
## Topology Guidance
Choose the simplest topology that preserves the source deployment intent.
- Prefer a single `.pod` for multi-container applications when practical.
- If one logical service contains multiple containers, default to putting them in the same `.pod` so they share networking and lifecycle.
- If the project is a simple single-container deployment with no real need for pod semantics, a standalone `.container` is the preferred result.
- If one pod is not practical because of port conflicts or clearly incompatible groupings, split the result into a small number of pods rather than forcing an awkward topology.
- Avoid preserving bridge networks by default when pod grouping already expresses the intended communication pattern well.
- For large application stacks with optional services, ask the user to choose the desired service set before generating a minimized result.
## Risky Or Lossy Areas
Handle these conservatively and usually as migration notes:
- `deploy`
- `profiles`
- `extends`
- advanced Compose merge behavior
- readiness semantics hidden behind `depends_on`
- any mapping that changes the source network or storage behavior in a way that matters
## Minimal examples
## Minimal Examples
### Single service to standalone container
@@ -149,8 +156,6 @@ Image=docker.io/library/nginx:latest
PublishPort=8080:80
```
Use this when the deployment is truly a simple single-service case. A single container should usually stay a standalone `.container` rather than being wrapped in a pod.
### Small multi-service app to one pod
Source intent:
@@ -172,23 +177,3 @@ Reasonable result shape:
- one container unit for `db`
- `api` may reach `db` over `127.0.0.1` / `localhost` because both containers share the pod network namespace
- ordering hints for startup, while explicitly noting that `depends_on` does not guarantee readiness
Use this as the default shape for a small multi-container service unless port conflicts or incompatible grouping force a split into multiple pods.
## Pod decision rule
Choose the simplest topology that preserves the source deployment intent.
Prefer a single `.pod` for multi-container applications when practical.
If one logical service contains multiple containers, default to putting them in the same `.pod` so they share networking and lifecycle.
If the project is a simple single-container deployment with no real need for pod semantics, a standalone `.container` is the preferred result.
If one pod is not practical because of port conflicts or clearly incompatible groupings, split the result into a small number of pods rather than forcing an awkward topology.
When services are split across multiple pods, do not rely on `127.0.0.1` / `localhost` for cross-pod communication. Use container names, pod names, or explicit `NetworkAlias=` values on the shared network instead.
Avoid preserving bridge networks by default when pod grouping already expresses the intended communication pattern well.
For large application stacks with optional services, ask the user to choose the desired service set before generating a minimized result.