Yalın Dockerfile'lar ve Kabuk Giriş Noktaları Yazma
Sinyal işleme ve yapılandırma şablonlaması içeren çok aşamalı derleme betikleri ile sağlam giriş noktası uyarlayıcıları yazın.
Yalın Dockerfile'lar ve Kabuk Giriş Noktaları Yazma, CoddyKit'te ücretsiz bir DevOps Bootcamp dersidir. Bu, 4 dersinin 1. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, DevOps Bootcamp öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. DevOps Bootcamp kursu toplamda 4 dersten oluşur.
Yalın Dockerfile'lar DevOps için neden önemlidir
Üretim ortamlarında bir Docker imajındaki her megabaytın bir maliyeti vardır: daha yavaş indirme, daha geniş saldırı yüzeyi ve israf edilen kayıt deposu alanı. Sağlam kabuk başlatma noktalarıyla birleştirilmiş yalın Dockerfile'lar, olgun DevOps uygulamalarının ayırt edici özelliklerindendir.
- Çok aşamalı derlemeler, derleme zamanındaki araçları son çalışma zamanı imajından ayırarak boyutu büyük ölçüde azaltır.
- Başlatma noktası aracı komut dosyaları, kapsayıcıları başlatan küçük kabuk komut dosyalarıdır: yapılandırma dosyalarına şablon uygular, ortam değişkenlerini doğrular, sinyalleri işler ve son olarak ana süreci exec ile çalıştırır.
- Birlikte, Kubernetes, ECS ve çıplak metal ortamlarındaki güvenilir ve taşınabilir kapsayıcı iş yüklerinin temelini oluştururlar.
Bu derste her iki uygulama alanı da uçtan uca ele alınır; doğrudan işlem hatlarınıza ekleyebileceğiniz üretim kalitesinde kalıplar sunulur.
Çok Aşamalı Bir Dockerfile'ın Anatomisi
Çok aşamalı bir Dockerfile, birden fazla FROM yönergesi kullanır. Her aşama yalıtılmış bir katman kümesidir; yalnızca ihtiyaç duyduğunuz yapıtları bir sonraki aşamaya kopyalarsınız.
- Aşama 0 (builder): derleyicileri, test çalıştırıcılarını ve derleme bağımlılıklarını kurar.
- Aşama 1 (runtime): en küçük temel imajdan (ör.
alpine,distroless) başlar ve yalnızca derlenmiş ikili dosyaları veya uygulama paketlerini kopyalar. - Son imajda, açıkça kopyalamadığınız sürece
gcc,makeveya kaynak kodu bulunmaz.
Aşamaların sınırları arasında dosya almak için COPY içinde --from=<stage> kullanın. Okunabilirlik ve docker build --target ile belirli bir aşamayı seçebilmek için aşamaları AS <name> ile adlandırın.
# ---- Stage 0: builder ----
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags='-s -w' -o /app/server ./cmd/server
# ---- Stage 1: runtime ----
FROM gcr.io/distroless/static-debian12
COPY --from=builder /app/server /server
ENTRYPOINT ["/server"]Katmanları Küçültme ve Önbelleği Geçersiz Kılma
Her RUN, COPY ve ADD yönergesi yeni bir katman oluşturur. Yönergelerin kötü sıralanması, derleme önbelleğini gereksiz yere geçersiz kılar ve CI işlem hatlarını yavaşlatır.
- Bağımlılık bildirimlerini (
package.json,go.mod,requirements.txt) kaynak kodunu kopyalamadan önce kopyalayın; böylece bağımlılık kurulumu bağımsız olarak önbelleğe alınır. - İlişkili komutları
&&ile zincirleyin ve ara katmanlarda paket önbelleği bırakmamak için temizleme işlemini aynıRUNkatmanında yapın. - Paket yöneticilerinde
--no-cachekullanın ve kurulumdan sonra liste dosyalarını kaldırın.
FROM python:3.12-slim AS builder
WORKDIR /app
# 1. Install deps first (cached until requirements change)
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
# 2. Copy source (cache busted only when code changes)
COPY src/ ./src/
FROM python:3.12-slim
COPY --from=builder /install /usr/local
COPY --from=builder /app/src /app/src
WORKDIR /app
CMD ["python", "-m", "src.main"]BuildKit Gizli Bilgileri ve SSH Yönlendirmesi
Özel kayıt depoları, SSH anahtarları ve API belirteçleri imaj katmanlarında asla görünmemelidir. Docker BuildKit iki güvenli mekanizma sağlar:
--secret: gizli bir dosyayı tek birRUNadımı içinde bağlar, ancak katmana kalıcı olarak eklemez./run/secrets/<id>üzerinden erişin.--ssh: özel anahtarları imaja gömmeden kimlik doğrulaması yapabilmesi için ana makinenin SSH aracısı yuvasını derleme ortamına yönlendirir.
BuildKit'i DOCKER_BUILDKIT=1 ile veya docker buildx build aracılığıyla etkinleştirin. # syntax=docker/dockerfile:1 yönergesi bu özelliklerin kullanılmasını sağlar.
# syntax=docker/dockerfile:1
FROM node:20-alpine AS deps
WORKDIR /app
COPY package*.json ./
# Mount NPM token as a secret — never stored in the image
RUN --mount=type=secret,id=npm_token \
NPM_TOKEN=$(cat /run/secrets/npm_token) \
npm ci --prefer-offline
# Usage at build time:
# DOCKER_BUILDKIT=1 docker build \
# --secret id=npm_token,src=~/.npmrc-token \
# -t myapp:latest .Sağlam Bir Başlatma Noktası Aracı Komut Dosyası Yazma
Başlatma noktası aracı komut dosyası, Dockerfile içinde ENTRYPOINT olarak ayarlanan bir kabuk komut dosyasıdır. Görevi, denetimi ana sürece devretmeden önce çalışma zamanı ortamını hazırlamaktır.
İyi yapılandırılmış bir aracı komut dosyası şu sırayı izler:
- 1. adım: Herhangi bir hatanın işlemi erkenden durdurması için
set -euo pipefailayarlanır. - 2. adım: Gerekli ortam değişkenleri doğrulanır ve yararlı bir iletiyle hızlıca hata verilir.
- 3. adım: Ortam değişkenlerinden yapılandırma dosyalarına şablon uygulanır.
- 4. adım: Düzgün kapatma için sinyal işleyicileri kaydedilir.
- 5. adım:
exec "$@"— kabuk ana süreçle değiştirilir; böylece PID 1 aracı komut dosyası değil, uygulama olur.
Son exec kritik öneme sahiptir: bu komut olmadan Kubernetes veya Docker çalışma zamanı tarafından gönderilen sinyaller alt sürece iletilmez.
#!/usr/bin/env bash
set -euo pipefail
# Step 2: validate required env vars
REQUIRED_VARS=(DATABASE_URL APP_SECRET PORT)
for var in "${REQUIRED_VARS[@]}"; do
if [[ -z "${!var:-}" ]]; then
echo "[entrypoint] ERROR: required env var '$var' is not set" >&2
exit 1
fi
done
# Step 3: template config (see next scene)
# Step 4: signal handling (see scene after that)
# Step 5: hand off to CMD
exec "$@"envsubst ile Yapılandırmaya Şablon Uygulama
envsubst (GNU gettext paketinden gelir ve Alpine'de gettext olarak bulunur), bir şablon dosyasındaki ${VAR} yer tutucularını mevcut ortam değişkeni değerleriyle değiştirir.
- İmajla birlikte bir
*.tmplyapılandırma şablonu gönderin; başlatma noktası bunu başlangıçta oluşturur. - İlişkisiz dolar işaretlerinin (ör. nginx düzenli ifadesindeki işaretlerin) yanlışlıkla genişletilmemesi için değişken listesini açıkça
envsubst'a geçirin. - Oluşturulan dosyayı
/tmpgibi yazılabilir bir yola veya özel bir yapılandırma birimine yazın.
#!/usr/bin/env bash
# Template: /etc/nginx/conf.d/app.conf.tmpl contains:
# server { listen ${NGINX_PORT}; server_name ${SERVER_NAME}; ... }
export NGINX_PORT=${NGINX_PORT:-8080}
export SERVER_NAME=${SERVER_NAME:-localhost}
envsubst '${NGINX_PORT} ${SERVER_NAME}' \
< /etc/nginx/conf.d/app.conf.tmpl \
> /etc/nginx/conf.d/app.conf
echo "[entrypoint] nginx config rendered:"
grep -E 'listen|server_name' /etc/nginx/conf.d/app.conf
exec "$@"Sinyal İşleme ve Düzgün Kapatma
Kapsayıcılar Kubernetes, ECS veya docker stop tarafından durdurulduğunda SIGTERM alır. Başlatma noktası aracı komut dosyanız PID 1 konumundaysa ve sinyalleri iletmiyorsa, ana süreç bekleme süresinden sonra SIGKILL ile sonlandırılır; bu da isteklerin kaybolmasına veya verilerin bozulmasına yol açabilir.
- Aracı komut dosyasında
SIGTERMveSIGINTsinyallerini yakalamak içintrapkullanın. - Sinyali
kill -TERM "$child"ile alt sürecin PID'sine iletin. - Alt süreç çıkana kadar beklemek ve ardından çıkış kodunu aktarmak için
wait "$child"kullanın. - Alternatif olarak, kabuğu tamamen değiştirmek için
execkullanabilirsiniz; bu durumda işletim sistemi sinyalleri doğrudan alt sürece iletir vetrapgerekmez. Basit durumlarda tercih edilen kalıp budur.
#!/usr/bin/env bash
set -euo pipefail
# Start main process in background
"$@" &
child=$!
# Forward SIGTERM and SIGINT to the child
trap 'echo "[entrypoint] caught SIGTERM, forwarding..."; kill -TERM "$child"' TERM
trap 'echo "[entrypoint] caught SIGINT, forwarding..."; kill -INT "$child"' INT
# Wait for child to exit and capture its exit code
wait "$child"
exit $?En Küçük Başlatma Süreci Olarak tini Kullanma
Kapsayıcınız alt süreçler oluşturduğunda (ör. çalışanları çatallayan bir kabuk), zombi süreçleri toplamak için gerçek bir başlatma sürecine ihtiyaç duyarsınız. tini, özellikle kapsayıcılar için tasarlanmış küçük bir başlatma ikilisidir.
- İmajınıza
tiniekleyin ve bunu başlatma noktası sarmalayıcısı olarak ayarlayın. - Zombi alt süreçleri toplar, sinyalleri doğru şekilde iletir ve alt sürecin durum koduyla çıkar.
- Docker,
docker run --initile etkinleştirilen yerleşik bir tini sunar; ancak bunu imaja gömmek, davranışın farklı çalışma zamanlarında (Kubernetes, ECS vb.) tutarlı olmasını sağlar.
FROM node:20-alpine
# Install tini for proper signal handling and zombie reaping
RUN apk add --no-cache tini
WORKDIR /app
COPY --chown=node:node . .
RUN npm ci --omit=dev
USER node
# tini wraps CMD; forwards SIGTERM and reaps zombies
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "server.js"]Kök Kullanıcı Olmadan Çalıştırma
root olarak (UID 0) çalışan kapsayıcılar büyük bir güvenlik riskidir: kapsayıcıdan kaçış, ana makineye tam erişim sağlar. Ana süreci çalıştırmadan önce her zaman ayrıcalıksız bir kullanıcıya geçin.
- Dockerfile içinde
addgroup/adduser(Alpine) veyagroupadd/useradd(Debian) ile özel bir sistem kullanıcısı ve grubu oluşturun. - Uygulama dosyalarının sahipliğini
COPY --chown=appuser:appgroupile değiştirin; bu, ayrı birRUN chownkatmanı kullanmaktan daha verimlidir. USERyönergesiyle bu kullanıcıya geçin. Başlatma noktası ve CMD bu kullanıcıyı devralır.- Kubernetes
securityContext.runAsNonRoot: true, hâlâ root olarak çalışan bir imajı başlatmayı reddeder.
FROM python:3.12-slim
# Create non-root user
RUN groupadd --gid 1001 appgroup && \
useradd --uid 1001 --gid appgroup --shell /bin/bash --create-home appuser
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy app files with correct ownership in a single layer
COPY --chown=appuser:appgroup src/ ./src/
COPY --chown=appuser:appgroup entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
USER appuser
ENTRYPOINT ["/entrypoint.sh"]
CMD ["python", "-m", "src.main"]İmajda Sağlık Denetimleri ve Hazır Olma Yoklamaları
Kubernetes canlılık ve hazır olma yoklamaları bildirimlerde tanımlanır; ancak bağımsız docker run ve Docker Compose ortamları için Dockerfile'a bir HEALTHCHECK de ekleyebilirsiniz.
HEALTHCHECK --interval=10s --timeout=3s --start-period=15s --retries=3 CMD ...- HTTP hizmetleri için
curl --failveyawget -qO-kullanın; HTTP kullanmayan arka plan hizmetlerinde/dev/tcp/localhost/PORTile bir yuvayı yoklayın. - Yalnızca ihtiyacınız olanları kurun: distroless imajlarda yalnızca sağlık denetimleri için
curleklemekten kaçının; bunun yerine amaca özel bir yoklama ikilisi veya uygulamanın kendi sağlık ikilisini kullanın.
FROM nginx:1.27-alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY dist/ /usr/share/nginx/html/
# Lightweight health check using bash TCP pseudo-device
# (no curl needed — works on any image with bash)
HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=3 \
CMD bash -c 'exec 3<>/dev/tcp/localhost/80 && echo -e "GET /health HTTP/1.0\r\n" >&3 && cat <&3 | grep -q "200 OK"' || exit 1
EXPOSE 80Her Şeyi Birleştirme: Üretim Ortamına Uygun Bir Başlatma Noktası
Aşağıdaki örnek, bu dersteki tüm kalıpları birleştiren eksiksiz ve üretim kalitesinde bir başlatma noktası aracı komut dosyasıdır: ortam doğrulama, yapılandırmaya şablon uygulama, sinyal iletme ve exec ile devretme. Bu kalıp, Kubernetes üzerinde dağıtılan gerçek dünya Node.js, Python ve Go mikro hizmetlerinde kullanılır.
- Her bölüm, kendini açıklayan bir şablon görevi görmesi için açıklama satırları içerir.
- Aracı komut dosyası 50 satırın altında tutulur; başlatma noktaları basit ve denetlenebilir olmalıdır.
- Son
exec "$@"komutuna dikkat edin: tüm hazırlıklar tamamlandıktan sonra kabuk uygulama süreciyle değiştirilir; böylece uygulama PID 1 olur ve tüm işletim sistemi sinyallerini doğrudan alır.
#!/usr/bin/env bash
# entrypoint.sh — production-grade container entrypoint shim
set -euo pipefail
# ── 1. Validate required environment variables ──────────────────
REQUIRED=(DATABASE_URL APP_SECRET PORT LOG_LEVEL)
for var in "${REQUIRED[@]}"; do
[[ -n "${!var:-}" ]] || { echo "[entrypoint] FATAL: $var is not set" >&2; exit 1; }
done
# ── 2. Set safe defaults for optional variables ─────────────────
export HOST=${HOST:-0.0.0.0}
export WORKERS=${WORKERS:-2}
# ── 3. Render config template ───────────────────────────────────
if [[ -f /etc/app/app.conf.tmpl ]]; then
envsubst '${DATABASE_URL} ${PORT} ${LOG_LEVEL} ${HOST}' \
< /etc/app/app.conf.tmpl \
> /etc/app/app.conf
echo "[entrypoint] config rendered at /etc/app/app.conf"
fi
# ── 4. Wait for dependent services (optional, fast) ─────────────
if [[ -n "${WAIT_FOR_HOST:-}" ]]; then
echo "[entrypoint] waiting for ${WAIT_FOR_HOST}:${WAIT_FOR_PORT:-5432}..."
until bash -c "exec 3<>/dev/tcp/${WAIT_FOR_HOST}/${WAIT_FOR_PORT:-5432}" 2>/dev/null; do
sleep 1
done
echo "[entrypoint] dependency ready"
fi
# ── 5. Hand off to CMD (PID 1 becomes the application) ──────────
echo "[entrypoint] starting: $*"
exec "$@"Bilgi Kontrolü: Başlatma Noktalarında Sinyal İşleme
Kapsayıcı başlatma noktası komut dosyalarında sinyal işleme konusundaki anlayışınızı sınayın.
Özet: Yalın Dockerfile'lar ve Kabuk Başlatma Noktaları
Üretim ortamına yönelik kapsayıcı yazımının tüm katmanlarını ele aldınız:
- Çok aşamalı derlemeler, derleyicileri ve derleme araçlarını son imajdan uzak tutmak için birden fazla
FROMyönergesi kullanır; böylece yalın ve en küçük çalışma zamanı katmanları üretilir. - Katman sıralaması — bağımlılık bildirimlerini kaynak kodundan önce kopyalamak — önbellek isabetlerini en üst düzeye çıkarır ve CI işlem hatlarını hızlandırır.
- BuildKit gizli bilgileri ve SSH bağlamaları, kimlik doğrulamalı derlemeleri bozmadan kimlik bilgilerini imaj geçmişinden uzak tutar.
- Başlatma noktası aracı komut dosyaları, ortam değişkenlerini doğrular,
envsubstile yapılandırma dosyalarına şablon uygular veexec "$@"aracılığıyla uygulamaya devreder. - Sinyal işleme, ya
execkullanılmasını (böylece uygulamanın PID 1 olmasını) ya da arka plan işleri kullanıldığında açık birtrap+kill+waitkalıbını gerektirir. - tini, kapsayıcı birden fazla süreç oluşturduğunda zombi süreçlerin toplanmasını ve sinyallerin doğru şekilde iletilmesini sağlar.
- Kök kullanıcı olmayan kullanıcılar ve
HEALTHCHECKyönergeleri, Kubernetes üretim iş yüklerine hazır, güvenli ve gözlemlenebilir bir imajı tamamlar.
Bu kalıpları tutarlı biçimde birleştirdiğinizde imajlarınız daha küçük, dağıtımları daha hızlı ve üretim koşullarındaki davranışları çok daha sağlam olur.
Sıkça Sorulan Sorular
“Yalın Dockerfile'lar ve Kabuk Giriş Noktaları Yazma” dersi ücretsiz mi?
Evet — “Yalın Dockerfile'lar ve Kabuk Giriş Noktaları Yazma” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve DevOps Bootcamp kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. DevOps Bootcamp kursu toplamda 4 dersten oluşur.
“Yalın Dockerfile'lar ve Kabuk Giriş Noktaları Yazma” dersinde ne öğreneceğim?
Sinyal işleme ve yapılandırma şablonlaması içeren çok aşamalı derleme betikleri ile sağlam giriş noktası uyarlayıcıları yazın. DevOps Bootcamp ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
DevOps Bootcamp öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te DevOps Bootcamp, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 1. dersidir.
“Yalın Dockerfile'lar ve Kabuk Giriş Noktaları Yazma” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu DevOps Bootcamp dersinde kod yazıp çalıştırabilir miyim?
Evet. Her DevOps Bootcamp dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Yalın Dockerfile'lar ve Kabuk Giriş Noktaları Yazma
- envsubst ve heredoc'larla Yapılandırma Şablonlama
- CLI ve jq ile Bulut Kaynaklarını Betikleme
- Sağlık Yoklamaları, Hazırlık Kapıları ve Bekleme Döngüleri