Menulis Dockerfile dan Titik Masuk Shell yang Ringkas
Tulis skrip binaan berbilang peringkat dan shim titik masuk yang teguh dengan pengendalian isyarat serta templat konfigurasi
Menulis Dockerfile dan Titik Masuk Shell yang Ringkas ialah pelajaran Kem Intensif DevOps percuma di CoddyKit. Ini ialah pelajaran 1 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Kem Intensif DevOps, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Kem Intensif DevOps merangkumi sejumlah 4 pelajaran.
Mengapa Dockerfile Ringkas Penting untuk DevOps
Dalam persekitaran produksi, setiap megabait dalam imej Docker mempunyai kos: penarikan yang lebih perlahan, permukaan serangan yang lebih besar dan storan pendaftaran yang terbuang. Dockerfile ringkas yang digabungkan dengan titik masuk skrip shell yang kukuh merupakan ciri amalan DevOps yang matang.
- Binaan berbilang peringkat mengasingkan alat masa binaan daripada imej masa jalan akhir, lalu mengurangkan saiz dengan ketara.
- Shim titik masuk ialah skrip shell kecil yang menyediakan bekas: shim ini menghasilkan templat fail config, mengesahkan pemboleh ubah persekitaran, mengendalikan isyarat dan akhirnya melaksanakan proses utama.
- Bersama-sama, kedua-duanya membentuk tunjang beban kerja bekas yang boleh dipercayai dan mudah alih dalam Kubernetes, ECS dan persekitaran pelayan fizikal.
Pelajaran ini merangkumi kedua-dua disiplin dari hujung ke hujung, dengan corak bertaraf produksi yang boleh anda masukkan terus ke dalam saluran paip anda.
Anatomi Dockerfile Berbilang Peringkat
Dockerfile berbilang peringkat menggunakan berbilang arahan FROM. Setiap peringkat ialah set lapisan yang terasing; anda hanya menyalin artifak yang diperlukan ke dalam peringkat seterusnya.
- Peringkat 0 (builder): memasang pengkompil, pelaksana ujian dan kebergantungan binaan.
- Peringkat 1 (runtime): bermula daripada asas minimum (contohnya
alpine,distroless) dan hanya menyalin perduaan yang telah dikompil atau himpunan aplikasi. - Imej akhir tidak mengandungi
gcc,makeatau kod sumber melainkan anda menyalinnya secara jelas.
Gunakan --from=<stage> dalam COPY untuk mengambil fail merentasi sempadan peringkat. Namakan peringkat dengan AS <name> supaya lebih mudah dibaca dan disasarkan secara terpilih menggunakan docker build --target.
# ---- 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"]Meminimumkan Lapisan dan Membatalkan Cache
Setiap arahan RUN, COPY dan ADD menghasilkan lapisan baharu. Susunan arahan yang kurang baik membatalkan cache binaan tanpa keperluan, lalu melambatkan saluran paip CI.
- Salin manifes kebergantungan (
package.json,go.mod,requirements.txt) sebelum menyalin kod sumber supaya pemasangan kebergantungan dicache secara berasingan. - Rantaikan arahan yang berkaitan dengan
&&dan lakukan pembersihan dalam lapisanRUNyang sama supaya cache pakej tidak tertinggal dalam lapisan perantaraan. - Gunakan
--no-cachedalam pengurus pakej dan buang fail senarai selepas pemasangan.
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"]Rahsia BuildKit dan Pemajuan SSH
Pendaftaran peribadi, kunci SSH dan token API tidak boleh sekali-kali muncul dalam lapisan imej. Docker BuildKit menyediakan dua mekanisme selamat:
--secret: memasang fail rahsia dalam satu langkahRUNtanpa memasukkannya ke dalam lapisan. Akses melalui/run/secrets/<id>.--ssh: memajukan soket ejen SSH hos ke dalam binaan supayagit cloneboleh mengesahkan identiti tanpa membenamkan kunci peribadi.
Dayakan BuildKit dengan DOCKER_BUILDKIT=1 atau melalui docker buildx build. Arahan # syntax=docker/dockerfile:1 membuka ciri-ciri ini.
# 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 .Menulis Shim Titik Masuk yang Kukuh
Shim titik masuk ialah skrip shell yang ditetapkan sebagai ENTRYPOINT dalam Dockerfile. Tugasnya adalah menyediakan persekitaran masa jalan sebelum menyerahkan kawalan kepada proses utama.
Shim yang distrukturkan dengan baik mengikut susunan ini:
- Langkah 1: Tetapkan
set -euo pipefailsupaya sebarang kegagalan menghentikan pelaksanaan lebih awal. - Langkah 2: Sahkan pemboleh ubah persekitaran yang diperlukan dan gagal dengan segera bersama mesej yang membantu.
- Langkah 3: Hasilkan templat fail config daripada pemboleh ubah persekitaran.
- Langkah 4: Daftarkan pengendali isyarat untuk penutupan yang lancar.
- Langkah 5:
exec "$@"— gantikan shell dengan proses utama supaya PID 1 ialah aplikasi, bukannya shim.
exec terakhir amat penting: tanpanya, isyarat yang dihantar oleh Kubernetes atau masa jalan Docker tidak dimajukan kepada proses anak.
#!/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 "$@"Penghasilan Templat Config dengan envsubst
envsubst (daripada pakej GNU gettext, yang tersedia dalam Alpine sebagai gettext) menggantikan ruang letak ${VAR} dalam fail templat dengan nilai semasa pemboleh ubah persekitarannya.
- Sertakan templat config
*.tmpldalam imej; titik masuk menghasilkan fail tersebut semasa permulaan. - Hantar senarai pemboleh ubah secara jelas kepada
envsubstsupaya ia tidak mengembangkan tanda dolar yang tidak berkaitan secara tidak sengaja (contohnya dalam ungkapan biasa NGINX). - Tulis fail yang telah dihasilkan ke laluan yang boleh ditulis seperti
/tmpatau volum config khusus.
#!/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 "$@"Pengendalian Isyarat dan Penutupan yang Lancar
Bekas menerima SIGTERM apabila dihentikan oleh Kubernetes, ECS atau docker stop. Jika shim titik masuk anda ialah PID 1 dan tidak memajukan isyarat, proses utama akan dimatikan dengan SIGKILL selepas tempoh ihsan — lalu menyebabkan permintaan tercicir atau kerosakan data.
- Gunakan
trapuntuk menangkapSIGTERMdanSIGINTdalam shim. - Majukan isyarat kepada PID anak menggunakan
kill -TERM "$child". - Gunakan
wait "$child"untuk menunggu sehingga proses anak keluar, kemudian teruskan kod keluarnya. - Sebagai pilihan, gunakan
execuntuk menggantikan shell sepenuhnya — kemudian OS menghantar isyarat terus kepada proses anak dan trap tidak diperlukan. Inilah corak pilihan untuk kes mudah.
#!/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 $?Menggunakan tini sebagai Proses Init Minimum
Apabila bekas anda menghasilkan proses anak (contohnya shell yang menggandakan proses pekerja), anda memerlukan init sebenar untuk mengutip semula proses zombi. tini ialah perduaan init kecil yang direka khusus untuk bekas.
- Tambahkan
tinike dalam imej anda dan tetapkannya sebagai pembungkus titik masuk. - Ia mengutip semula proses anak zombi, memajukan isyarat dengan betul dan keluar dengan kod status proses anak.
- Docker disertakan dengan tini terbina dalam yang diaktifkan menggunakan
docker run --init, tetapi membenamkannya dalam imej memastikan tingkah laku konsisten merentasi masa jalan (Kubernetes, ECS dan sebagainya).
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"]Menjalankan sebagai Pengguna Bukan Root
Bekas yang berjalan sebagai root (UID 0) merupakan risiko keselamatan yang besar: pelarian bekas memberikan akses penuh kepada hos. Sentiasa tukar kepada pengguna tanpa keistimewaan sebelum melaksanakan proses utama.
- Cipta pengguna dan kumpulan sistem khusus dalam Dockerfile dengan
addgroup/adduser(Alpine) ataugroupadd/useradd(Debian). - Tukar pemilikan fail aplikasi dengan
COPY --chown=appuser:appgroup— lebih cekap berbanding lapisanRUN chownyang berasingan. - Tukar kepada pengguna tersebut dengan arahan
USER. Titik masuk dan CMD mewarisi pengguna ini. - Kubernetes
securityContext.runAsNonRoot: trueakan enggan memulakan imej yang masih berjalan sebagai root.
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"]Pemeriksaan Kesihatan dan Probe Kesediaan dalam Imej
Probe keaktifan dan kesediaan Kubernetes ditakrifkan dalam manifes, tetapi anda juga boleh membenamkan HEALTHCHECK dalam Dockerfile untuk persekitaran docker run kendiri dan Docker Compose.
HEALTHCHECK --interval=10s --timeout=3s --start-period=15s --retries=3 CMD ...- Gunakan
curl --failatauwget -qO-untuk perkhidmatan HTTP; bagi daemon bukan HTTP, uji soket dengan/dev/tcp/localhost/PORT. - Pasang hanya perkara yang diperlukan: dalam imej distroless, elakkan menambah
curlhanya untuk pemeriksaan kesihatan — gunakan perduaan probe yang direka khusus atau perduaan kesihatan aplikasi sendiri.
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 80Menggabungkan Semuanya: Titik Masuk Produksi
Berikut ialah shim titik masuk lengkap bertaraf produksi yang menggabungkan semua corak daripada pelajaran ini: pengesahan pemboleh ubah persekitaran, penghasilan templat config, pemajuan isyarat dan penyerahan kawalan melalui exec. Corak ini digunakan dalam perkhidmatan mikro Node.js, Python dan Go dunia sebenar yang digunakan pada Kubernetes.
- Setiap bahagian diberikan komen untuk berfungsi sebagai templat yang mendokumenkan dirinya sendiri.
- Shim ini dikekalkan di bawah 50 baris — titik masuk hendaklah ringkas dan mudah diaudit.
- Perhatikan
exec "$@"terakhir: selepas semua persediaan selesai, shell digantikan dengan proses aplikasi supaya proses itu menjadi PID 1 dan menerima semua isyarat OS secara langsung.
#!/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 "$@"Semakan Pengetahuan: Pengendalian Isyarat dalam Titik Masuk
Uji pemahaman anda tentang pengendalian isyarat dalam skrip titik masuk bekas.
Imbas Kembali: Dockerfile Ringkas dan Titik Masuk Shell
Anda telah merangkumi keseluruhan susunan penghasilan bekas produksi:
- Binaan berbilang peringkat menggunakan berbilang arahan
FROMuntuk mengeluarkan pengkompil dan alat binaan daripada imej akhir, lalu menghasilkan lapisan masa jalan yang ringkas dan minimum. - Susunan lapisan — salin manifes kebergantungan sebelum kod sumber — memaksimumkan cache yang sepadan dan mempercepatkan saluran paip CI.
- Rahsia dan pelekap SSH BuildKit menghalang kelayakan daripada masuk ke dalam sejarah imej tanpa menjejaskan binaan yang disahkan.
- Shim titik masuk mengesahkan pemboleh ubah persekitaran, menghasilkan templat fail config dengan
envsubstdan menyerahkan kawalan kepada aplikasi melaluiexec "$@". - Pengendalian isyarat memerlukan sama ada
exec(supaya aplikasi menjadi PID 1) atau coraktrap+kill+waityang jelas apabila kerja latar digunakan. - tini menambah pengutipan semula proses zombi dan pemajuan isyarat yang betul apabila bekas menghasilkan berbilang proses.
- Pengguna bukan root dan arahan
HEALTHCHECKmelengkapkan imej yang selamat serta boleh dipantau, dan bersedia untuk beban kerja produksi Kubernetes.
Gabungkan corak ini secara konsisten supaya imej anda lebih kecil, lebih pantas digunakan dan jauh lebih kukuh dalam keadaan produksi.
Pelajari Kem Intensif DevOps dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 142
- Pelajaran
- 568
Soalan Lazim
Adakah pelajaran “Menulis Dockerfile dan Titik Masuk Shell yang Ringkas” percuma?
Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Kem Intensif DevOps, termasuk “Menulis Dockerfile dan Titik Masuk Shell yang Ringkas”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Kem Intensif DevOps merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Menulis Dockerfile dan Titik Masuk Shell yang Ringkas”?
Tulis skrip binaan berbilang peringkat dan shim titik masuk yang teguh dengan pengendalian isyarat serta templat konfigurasi Anda berlatih Kem Intensif DevOps menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan Kem Intensif DevOps?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Kem Intensif DevOps di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 1 daripada 4.
Berapa lamakah pelajaran “Menulis Dockerfile dan Titik Masuk Shell yang Ringkas” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran Kem Intensif DevOps ini?
Ya. Setiap pelajaran Kem Intensif DevOps menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Menulis Dockerfile dan Titik Masuk Shell yang Ringkas
- Menyediakan Templat Konfigurasi dengan envsubst dan heredoc
- Menskripkan Sumber Awan melalui CLI dan jq
- Probe Kesihatan, Gerbang Kesediaan dan Gelung Menunggu