Skip to main content Skills Marketplace 커뮤니티가 만든 AI 스킬을 발견하고 탐색하세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/diegosouzapw/awesome-omni-skill --skill dotnet-container-deployment명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Zip 다운로드 다운로드 중... 이 저장소의 다른 Skills Token-efficient tracking for AI orchestration. CLI-first for status updates (~50 tokens), agent fallback for complex ops (~1KB). Use when: updating task status, querying blockers, creating progress files, validating phases.
AshAi extension guidelines for integrating AI capabilities with Ash Framework. Use when implementing vectorization/embeddings, exposing Ash actions as LLM tools, creating prompt-backed actions, or setting up MCP servers. Covers semantic search, LangChain integration, and structured outputs.
This skill should be used when solving hard questions, complex architectural problems, or debugging issues that benefit from GPT-5 Pro or GPT-5.1 thinking models with large file context. Use when standard Claude analysis needs deeper reasoning or extended context windows.
name dotnet-container-deployment description Deploys .NET containers. Kubernetes probes, Docker Compose for local dev, CI/CD integration. license MIT targets ["*"] tags ["cicd","dotnet","skill"] version 0.0.1 author dotnet-agent-harness claudecode {"allowed-tools":["Read","Grep","Glob","Bash","Write","Edit"]} codexcli {"short-description":".NET skill guidance for cicd tasks"} opencode {"allowed-tools":["Read","Grep","Glob","Bash","Write","Edit"]}
dotnet-container-deployment
Deploying .NET containers to Kubernetes and local development environments. Covers Kubernetes Deployment + Service +
probe YAML, Docker Compose for local dev workflows, and CI/CD integration for building and pushing container images.
Scope
Kubernetes Deployment, Service, and probe YAML for .NET apps
Docker Compose for local development workflows
CI/CD integration for building and pushing container images
Out of scope
Dockerfile authoring, multi-stage builds, and base image selection -- see [skill:dotnet-containers]
Advanced CI/CD pipeline patterns (matrix builds, deploy pipelines) -- see [skill:dotnet-gha-deploy] and
[skill:dotnet-ado-patterns]
DI and async patterns -- see [skill:dotnet-csharp-dependency-injection] and [skill:dotnet-csharp-async-patterns]
Testing container deployments -- see [skill:dotnet-integration-testing] and [skill:dotnet-playwright]
Cross-references: [skill:dotnet-containers] for Dockerfile and image best practices, [skill:dotnet-observability] for
health check endpoint patterns used by Kubernetes probes.
Kubernetes Deployment
Deployment Manifest
A production-ready Kubernetes Deployment for a .NET API:
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-api
labels:
app: order-api
app.kubernetes.io/name: order-api
app.kubernetes.io/version: '1.0.0'
app.kubernetes.io/component: api
spec:
replicas: 3
selector:
matchLabels:
app: order-api
template:
metadata:
labels:
app: order-api
[ ]
{
,
}
{
}
[ , ]
[ , ]
[ , , ]
[ , , , , ]
[ ]
[ ] [ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
[ ]
spec:
containers:
-
name:
order-api
image:
ghcr.io/myorg/order-api:1.0.0
ports:
-
containerPort:
8080
protocol:
TCP
env:
-
name:
ASPNETCORE_ENVIRONMENT
value:
'Production'
-
name:
OTEL_EXPORTER_OTLP_ENDPOINT
value:
'http://otel-collector.monitoring:4317'
-
name:
OTEL_SERVICE_NAME
value:
'order-api'
-
name:
ConnectionStrings__DefaultConnection
valueFrom:
secretKeyRef:
name:
order-api-secrets
key:
connection-string
resources:
requests:
cpu:
'100m'
memory:
'128Mi'
limits:
cpu:
'500m'
memory:
'512Mi'
livenessProbe:
httpGet:
path:
/health/live
port:
8080
initialDelaySeconds:
10
periodSeconds:
15
timeoutSeconds:
3
failureThreshold:
3
readinessProbe:
httpGet:
path:
/health/ready
port:
8080
initialDelaySeconds:
5
periodSeconds:
10
timeoutSeconds:
3
failureThreshold:
3
startupProbe:
httpGet:
path:
/health/live
port:
8080
initialDelaySeconds:
0
periodSeconds:
5
failureThreshold:
30
securityContext:
runAsNonRoot:
true
runAsUser:
1654
fsGroup:
1654
terminationGracePeriodSeconds:
30
```text
Expose the Deployment within the cluster:
```yaml
apiVersion:
v1
kind:
Service
metadata:
name:
order-api
labels:
app:
order-api
spec:
type:
ClusterIP
selector:
app:
order-api
ports:
-
port:
80
targetPort:
8080
protocol:
TCP
name:
http
```text
```yaml
apiVersion:
v1
kind:
ConfigMap
metadata:
name:
order-api-config
data:
ASPNETCORE_ENVIRONMENT:
'Production'
Logging__LogLevel__Default:
'Information'
Logging__LogLevel__Microsoft.AspNetCore:
'Warning'
```text
Reference in the Deployment:
```yaml
envFrom:
-
configMapRef:
name:
order-api-config
```yaml
```yaml
apiVersion:
v1
kind:
Secret
metadata:
name:
order-api-secrets
type:
Opaque
stringData:
connection-string:
'Host=postgres;Database=orders;Username=app;Password=secret'
```text
In
production,
use
an
external
secrets
operator
(e.g.,
External
Secrets
Operator,
Sealed
Secrets)
rather
than
plain
Kubernetes
Secrets
stored
in
source
control.
---
Probes
tell
Kubernetes
how
to
check
application
health.
They
map
to
the
health
check
endpoints
defined
in
your
.NET
application
(see
skill:dotnet-observability
).
|
Probe
|
Purpose
|
Endpoint
|
Failure
Action
|
|
-------------
|
----------------------------------
|
---------------
|
-------------------------------------------------------
|
|
**Startup**
|
Has
the
app
finished
initializing?
|
`/health/live`
|
Keep
waiting
(up
to
`failureThreshold
*
periodSeconds`)
|
|
**Liveness**
|
Is
the
process
healthy?
|
`/health/live`
|
Restart
the
pod
|
|
**Readiness**
|
Can
the
process
serve
traffic?
|
`/health/ready`
|
Remove
from
Service
endpoints
|
```yaml
startupProbe:
httpGet:
path:
/health/live
port:
8080
initialDelaySeconds:
0
periodSeconds:
5
failureThreshold:
30
livenessProbe:
httpGet:
path:
/health/live
port:
8080
periodSeconds:
15
timeoutSeconds:
3
failureThreshold:
3
readinessProbe:
httpGet:
path:
/health/ready
port:
8080
periodSeconds:
10
timeoutSeconds:
3
failureThreshold:
3
```text
.NET
responds
to
`SIGTERM`
and
begins
graceful
shutdown.
Configure
`terminationGracePeriodSeconds`
to
allow
in-flight
requests to complete:
```yaml
spec:
terminationGracePeriodSeconds:
30
```yaml
In
your
application,
use
`IHostApplicationLifetime`
to handle shutdown:
```csharp
app.Lifetime.ApplicationStopping.Register(()
=>
//
Perform cleanup:
flush
telemetry
close
connections
Log.CloseAndFlush();
);
```text
Ensure
the
`Host.ShutdownTimeout`
allows in-flight requests to complete:
```csharp
builder.Host.ConfigureHostOptions(options
=>
options.ShutdownTimeout
=
TimeSpan.FromSeconds(25);
);
```text
Set
`ShutdownTimeout`
to
a
value
less
than
`terminationGracePeriodSeconds`
to
ensure
the
app
shuts
down
before
Kubernetes
sends
`SIGKILL`.
---
Docker
Compose
provides
a
local
development
environment
that
mirrors
production
dependencies.
```yaml
services:
order-api:
build:
context:
.
dockerfile:
src/OrderApi/Dockerfile
ports:
-
'8080:8080'
environment:
-
ASPNETCORE_ENVIRONMENT=Development
-
ConnectionStrings__DefaultConnection=Host=postgres;Database=orders;Username=app;Password=devpassword
-
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
depends_on:
postgres:
condition:
service_healthy
redis:
condition:
service_healthy
healthcheck:
test:
'CMD-SHELL'
'curl -f http://localhost:8080/health/live || exit 1'
interval:
10s
timeout:
3s
retries:
3
start_period:
10s
postgres:
image:
postgres:17
environment:
POSTGRES_DB:
orders
POSTGRES_USER:
app
POSTGRES_PASSWORD:
devpassword
ports:
-
'5432:5432'
volumes:
-
postgres-data:/var/lib/postgresql/data
healthcheck:
test:
'CMD-SHELL'
'pg_isready -U app -d orders'
interval:
5s
timeout:
3s
retries:
5
redis:
image:
redis:7-alpine
ports:
-
'6379:6379'
healthcheck:
test:
'CMD'
'redis-cli'
'ping'
interval:
5s
timeout:
3s
retries:
5
volumes:
postgres-data:
```text
Use a separate override file for development-specific settings:
```yaml
services:
order-api:
build:
target:
build
volumes:
-
.:/src
environment:
-
ASPNETCORE_ENVIRONMENT=Development
-
DOTNET_USE_POLLING_FILE_WATCHER=true
command:
'dotnet'
'watch'
'run'
'--project'
'src/OrderApi/OrderApi.csproj'
```bash
Add an OpenTelemetry collector and Grafana for local observability:
```yaml
services:
otel-collector:
image:
otel/opentelemetry-collector-contrib:latest
command:
'--config=/etc/otelcol-config.yaml'
volumes:
-
./infra/otelcol-config.yaml:/etc/otelcol-config.yaml
ports:
-
'4317:4317'
-
'4318:4318'
grafana:
image:
grafana/grafana:latest
ports:
-
'3000:3000'
volumes:
-
grafana-data:/var/lib/grafana
volumes:
grafana-data:
```text
Run with the observability stack:
```bash
docker
compose
-f
docker-compose.yml
-f
docker-compose.observability.yml
up
```bash
---
Basic
CI/CD
patterns
for
building
and
pushing
.NET
container
images.
Advanced
CI
patterns
(matrix
builds,
environment
promotion,
deploy
pipelines)
--
see
skill:dotnet-gha-publish
,
skill:dotnet-gha-deploy
,
and
skill:dotnet-ado-publish
.
```yaml
name:
Build
and
Push
Container
on:
push:
branches:
main
tags:
'v*'
env:
REGISTRY:
ghcr.io
IMAGE_NAME:
${{
github.repository
}}
jobs:
build-and-push:
runs-on:
ubuntu-latest
permissions:
contents:
read
packages:
write
steps:
-
uses:
actions/checkout@v4
-
name:
Log
in
to
container
registry
uses:
docker/login-action@v3
with:
registry:
${{
env.REGISTRY
}}
username:
${{
github.actor
}}
password:
${{
secrets.GITHUB_TOKEN
}}
-
name:
Extract
metadata
id:
meta
uses:
docker/metadata-action@v5
with:
images:
${{
env.REGISTRY
}}/${{
env.IMAGE_NAME
}}
tags:
|
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
-
name:
Build
and
push
uses:
docker/build-push-action@v6
with:
context:
.
push:
true
tags:
${{
steps.meta.outputs.tags
}}
labels:
${{
steps.meta.outputs.labels
}}
cache-from:
type=gha
cache-to:
type=gha,mode=max
```text
|
Tag
Pattern
|
Example
|
Use
Case
|
|
-----------
|
-------------------
|
-------------------------------------------
|
|
`latest`
|
`myapi:latest`
|
Development
only
--
never
use
in
production
|
|
Semver
|
`myapi:1.2.3`
|
Release
versions
--
immutable
|
|
Major.Minor
|
`myapi:1.2`
|
Floating
tag
for
patch
updates
|
|
SHA
|
`myapi:sha-abc1234`
|
Unique
per
commit
--
traceability
|
|
Branch
|
`myapi:main`
|
CI
builds
--
latest
from
branch
|
For
projects
using
`dotnet
publish
/t:PublishContainer`
instead of Dockerfiles:
```yaml
steps:
-
uses:
actions/checkout@v4
-
uses:
actions/setup-dotnet@v4
with:
dotnet-version:
'10.0.x'
-
name:
Publish
container
image
run:
|
dotnet publish src/OrderApi/OrderApi.csproj \
--os linux --arch x64 \
/t:PublishContainer \
-p:ContainerRegistry=${{ env.REGISTRY }} \
-p:ContainerRepository=${{ env.IMAGE_NAME }} \
-p:ContainerImageTag=${{ github.sha }}
```text
---
-
**Use
startup
probes**
to
decouple
initialization
time
from
liveness
detection
--
without
a
startup
probe,
slow-starting
apps
get
killed
before
they
are
ready
-
**Separate
liveness
from
readiness**
--
liveness
checks
should
not
include
dependency
health
(see
skill:dotnet-observability
for
endpoint
patterns)
-
**Set
resource
requests
and
limits**
--
without
them,
pods
can
starve
other
workloads
or
get
OOM-killed
unpredictably
-
**Run
as
non-root**
--
set
`runAsNonRoot:
true
`
in
the
pod
security
context
and
use
chiseled
images
(see
skill:dotnet-containers
)
-
**Use
`depends_on`
with
health
checks**
in
Docker
Compose
--
prevents
app
startup
before
dependencies
are
ready
-
**Keep
secrets
out
of
manifests**
--
use
Kubernetes
Secrets
with
external
secrets
operators,
not
plain
values
in
source
control
-
**Match
ShutdownTimeout
to
terminationGracePeriodSeconds**
--
ensure
the
app
finishes
cleanup
before
Kubernetes
sends
SIGKILL
---
1
.
**Do
not
omit
the
startup
probe**
--
without
it,
the
liveness
probe
runs
during
initialization
and
may
restart
slow-starting
apps.
Calculate
startup
budget
as
`failureThreshold
*
periodSeconds`.
2
.
**Do
not
include
dependency
checks
in
liveness
probes**
--
a
database
outage
should
not
restart
your
app.
Liveness
endpoints
must
only
check
the
process
itself.
See
skill:dotnet-observability
for
the
liveness
vs
readiness
pattern.
3
.
**Do
not
use
`latest`
tag
in
Kubernetes
manifests**
--
`latest`
is
mutable
and
`imagePullPolicy:
IfNotPresent`
may
serve
stale
images.
Use
immutable
tags
(semver
or
SHA).
4
.
**Do
not
hardcode
connection
strings
in
Kubernetes
manifests**
--
use
Secrets
or
ConfigMaps
referenced
via
`secretKeyRef`/`configMapRef`.
5
.
**Do
not
set
`terminationGracePeriodSeconds`
lower
than
`Host.ShutdownTimeout`**
--
the
app
needs
time
to
drain
in-flight
requests
before
Kubernetes
sends
SIGKILL.
6
.
**Do
not
forget
`condition:
service_healthy`
in
Docker
Compose
`depends_on`**
--
without
the
condition,
Compose
starts
dependent
services
immediately
without
waiting
for
health
checks.
---
-
Deploy
ASP.NET
Core
to
Kubernetes
(https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx)
-
Kubernetes
Deployments
(https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
-
Kubernetes
probes
(https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)
-
Docker
Compose
overview
(https://docs.docker.com/compose/)
-
ASP.NET
Core
health
checks
(https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks)
-
Graceful
shutdown
in
.NET
(https://learn.microsoft.com/en-us/dotnet/core/extensions/generic-host#host-shutdown)
-
GitHub Actions:
Publishing
Docker
images
(https://docs.github.com/en/actions/use-cases-and-examples/publishing-packages/publishing-docker-images)