Keveiden Dockerfile-tiedostojen ja shell-entripointien kirjoittaminen
Kirjoita monivaiheisia koontiskriptejä ja vankkoja entrypoint-sovittimia, joissa on signaalien käsittely ja määritysten mallipohjat.
Keveiden Dockerfile-tiedostojen ja shell-entripointien kirjoittaminen on ilmainen Linux-komentorivin ja Bash-komentosarjojen hallinta-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Linux-komentorivin ja Bash-komentosarjojen hallinta-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Linux-komentorivin ja Bash-komentosarjojen hallinta-kurssilla on yhteensä 4 oppituntia.
Miksi kevyet Dockerfile-tiedostot ovat tärkeitä DevOpsissa
Tuotantoympäristöissä jokaisella Docker-imagen megatavulla on hintansa: lataukset ovat hitaampia, hyökkäyspinta suurempi ja rekisterin tallennustilaa kuluu hukkaan. Kevyet Dockerfile-tiedostot yhdessä vankkojen shell-entrypoint-skriptien kanssa ovat kypsän DevOps-käytännön tunnusmerkkejä.
- Monivaiheiset koonnit erottavat koonnin aikana tarvittavat työkalut lopullisesta ajonaikaisesta imagesta ja pienentävät sen kokoa huomattavasti.
- Entrypoint-skriptit ovat pieniä shell-skriptejä, jotka valmistelevat kontit: ne muodostavat asetustiedostot mallipohjista, tarkistavat ympäristömuuttujat, käsittelevät signaalit ja suorittavat lopuksi pääprosessin
exec-komennolla. - Yhdessä ne muodostavat luotettavien ja siirrettävien konttityökuormien perustan Kubernetes-, ECS- ja bare metal -ympäristöissä.
Tässä oppitunnissa käsitellään molemmat osa-alueet alusta loppuun käyttäen tuotantokelpoisia malleja, jotka voitte ottaa suoraan käyttöön putkissanne.
Monivaiheisen Dockerfile-tiedoston rakenne
Monivaiheinen Dockerfile-tiedosto käyttää useita FROM-ohjeita. Jokainen vaihe on erillinen kerrosjoukko, ja seuraavaan vaiheeseen kopioidaan vain tarvittavat artefaktit.
- Vaihe 0 (builder): asentaa kääntäjät, testien suorittajat ja koonnin riippuvuudet.
- Vaihe 1 (runtime): alkaa minimaalisesta perustasta (esimerkiksi
alpinetaidistroless) ja kopioi vain käännetyt binäärit tai sovelluspaketit. - Lopullinen image ei sisällä
gcc- taimake-ohjelmaa eikä lähdekoodia, ellette kopioi niitä sinne erikseen.
Käyttäkää COPY-ohjeessa määritettä --from=<stage> tiedostojen siirtämiseen vaiheiden välillä. Nimetkää vaiheet määritteellä AS <name>, jotta Dockerfile on helpompi lukea ja voitte kohdistaa koonnin valittuun vaiheeseen komennolla 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"]Kerrosten minimointi ja välimuistin mitätöinti
Jokainen RUN-, COPY- ja ADD-ohje luo uuden kerroksen. Huonosti järjestetyt ohjeet mitätöivät koontivälimuistin tarpeettomasti, mikä hidastaa CI-putkia.
- Kopioikaa riippuvuusmanifestit (
package.json,go.mod,requirements.txt) ennen lähdekoodin kopioimista, jotta riippuvuuksien asennus voidaan välimuistittaa erikseen. - Ketjuttakaa toisiinsa liittyvät komennot komennolla
&&ja siivotkaa samassaRUN-kerroksessa, jotta paketinhallinnan välimuisti ei jää välivaiheiden kerroksiin. - Käyttäkää paketinhallintaohjelmissa asetusta
--no-cacheja poistakaa listatiedostot asennuksen jälkeen.
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-salaisuudet ja SSH-välitys
Yksityiset rekisterit, SSH-avaimet ja API-tunnukset eivät saa koskaan päätyä image-kerroksiin. Docker BuildKit tarjoaa kaksi turvallista mekanismia:
--secret: liittää salaisuustiedoston yhdenRUN-vaiheen ajaksi ilman, että se tallentuu kerrokseen. Tiedostoon pääsee polun/run/secrets/<id>kautta.--ssh: välittää isäntäkoneen SSH-agentin socketin koontiin, jolloingit clonevoi todentaa käyttäjän ilman yksityisten avainten upottamista imageen.
Ottakaa BuildKit käyttöön asetuksella DOCKER_BUILDKIT=1 tai komennolla docker buildx build. Direktiivi # syntax=docker/dockerfile:1 ottaa nämä ominaisuudet käyttöön.
# 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 .Vankan entrypoint-skriptin kirjoittaminen
Entrypoint-skripti on shell-skripti, joka asetetaan Dockerfile-tiedostossa ENTRYPOINT-ohjeen arvoksi. Sen tehtävänä on valmistella ajonaikainen ympäristö ennen hallinnan luovuttamista pääprosessille.
Hyvin jäsennelty skripti noudattaa tätä järjestystä:
- Vaihe 1: Asettakaa
set -euo pipefail, jotta mikä tahansa virhe keskeyttää suorituksen heti. - Vaihe 2: Tarkistakaa pakolliset ympäristömuuttujat ja keskeyttäkää suoritus nopeasti informatiivisen viestin kera.
- Vaihe 3: Muodostakaa asetustiedostot ympäristömuuttujien pohjalta.
- Vaihe 4: Rekisteröikää signaalinkäsittelijät hallittua sammutusta varten.
- Vaihe 5:
exec "$@"— korvatkaa shell pääprosessilla, jotta PID 1 on sovellus eikä entrypoint-skripti.
Lopullinen exec on ratkaisevan tärkeä: ilman sitä Kubernetesin tai Docker-ajonaikaisen ympäristön lähettämät signaalit eivät välity lapsiprosessille.
#!/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 "$@"Asetusten mallintaminen envsubst-komennolla
envsubst (GNU:n gettext-paketista, joka on Alpinella saatavilla nimellä gettext) korvaa mallipohjatiedoston ${VAR}-paikkamerkit niidenhetkisillä ympäristömuuttujien arvoilla.
- Toimittakaa imageen
*.tmpl-muotoinen asetusten mallipohja; entrypoint-skripti muodostaa siitä lopullisen tiedoston käynnistyksen yhteydessä. - Välittäkää muuttujaluettelo
envsubst-komennolle eksplisiittisesti, jotta se ei vahingossa laajenna toisiinsa liittymättömiä dollarimerkkejä (esimerkiksi nginxin säännöllisissä lausekkeissa). - Kirjoittakaa muodostettu tiedosto kirjoitettavissa olevaan polkuun, kuten
/tmp-hakemistoon tai erilliseen asetustaltioon.
#!/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 "$@"Signaalien käsittely ja hallittu sammutus
Kontit vastaanottavat SIGTERM-signaalin, kun Kubernetes, ECS tai docker stop pysäyttää ne. Jos entrypoint-skripti on PID 1 eikä välitä signaaleja eteenpäin, pääprosessi lopetetaan SIGKILL-signaalilla odotusajan päätyttyä, mikä voi aiheuttaa pyyntöjen katoamista tai tietojen vioittumista.
- Käyttäkää
trap-komentoaSIGTERM- jaSIGINT-signaalien vastaanottamiseen skriptissä. - Välittäkää signaali lapsiprosessin PID:lle komennolla
kill -TERM "$child". - Käyttäkää komentoa
wait "$child"odottamaan lapsiprosessin päättymistä ja välittäkää sen paluuarvo eteenpäin. - Vaihtoehtoisesti voitte korvata shellin kokonaan komennolla
exec. Tällöin käyttöjärjestelmä toimittaa signaalit suoraan lapsiprosessille, eikätrap-komentoa tarvita. Tämä on suositeltu malli yksinkertaisissa tapauksissa.
#!/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 $?tinin käyttäminen minimaalisena init-prosessina
Kun kontti käynnistää lapsiprosesseja (esimerkiksi työntekijöitä haarauttavan shellin), tarvitsette varsinaisen init-prosessin zombie-prosessien keräämiseen. tini on kontteja varten suunniteltu erittäin pieni init-binääri.
- Lisätkää
tiniimageen ja asettakaa se entrypoint-skriptin kääreeksi. - Se kerää zombie-lapsiprosessit, välittää signaalit oikein ja päättyy lapsiprosessin paluuarvolla.
- Docker sisältää valmiin tinin, jonka voi ottaa käyttöön komennolla
docker run --init, mutta sen upottaminen imageen varmistaa toiminnan yhdenmukaisuuden eri ajonaikaisissa ympäristöissä (Kubernetes, ECS ja muut).
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"]Suorittaminen ilman pääkäyttäjän oikeuksia
root-käyttäjänä (UID 0) toimivat kontit ovat merkittävä tietoturvariski: kontista pakeneminen antaa täydet oikeudet isäntäkoneeseen. Vaihtakaa aina etuoikeudettomaan käyttäjään ennen pääprosessin suorittamista.
- Luokaa Dockerfile-tiedostossa erillinen järjestelmäkäyttäjä ja -ryhmä komennoilla
addgroup/adduser(Alpine) taigroupadd/useradd(Debian). - Vaihtakaa sovellustiedostojen omistajuus komennolla
COPY --chown=appuser:appgroup. Tämä on tehokkaampaa kuin erillinenRUN chown-kerros. - Vaihtakaa käyttäjää
USER-ohjeella. Tämä käyttäjä periytyy entrypoint-skriptille ja CMD:lle. - Kubernetesin
securityContext.runAsNonRoot: truekieltäytyy käynnistämästä imagea, joka toimii edelleen pääkäyttäjänä.
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"]Imagen kuntotarkistukset ja valmiuskyselyt
Kubernetesin elossaolo- ja valmiuskyselyt määritetään manifesteissa, mutta voitte lisätä Dockerfile-tiedostoon myös HEALTHCHECK-ohjeen erillisiä docker run- ja Docker Compose -ympäristöjä varten.
HEALTHCHECK --interval=10s --timeout=3s --start-period=15s --retries=3 CMD ...- Käyttäkää HTTP-palveluissa komentoja
curl --failtaiwget -qO-. Muiden kuin HTTP-taustapalvelujen tapauksessa tarkistakaa socket yhteydellä/dev/tcp/localhost/PORT. - Asentakaa vain tarvittavat työkalut: distroless-imageihin ei kannata lisätä
curl-ohjelmaa pelkästään kuntotarkistuksia varten. Käyttäkää tarkoitukseen suunniteltua kyselybinääriä tai sovelluksen omaa kuntotarkistusbinääriä.
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 80Kaikki yhteen: tuotantokäyttöön sopiva entrypoint-skripti
Seuraava on täydellinen tuotantokäyttöön sopiva entrypoint-skripti, joka yhdistää kaikki tämän oppitunnin mallit: ympäristömuuttujien tarkistuksen, asetusten mallintamisen, signaalien välityksen ja hallinnan luovuttamisen exec-komennolla. Tätä mallia käytetään tosielämän Node.js-, Python- ja Go-mikropalveluissa, jotka on otettu käyttöön Kubernetesissa.
- Jokainen osio on kommentoitu itseään dokumentoivaksi mallipohjaksi.
- Skripti on alle 50 riviä pitkä — entrypoint-skriptien tulee olla yksinkertaisia ja helposti tarkastettavia.
- Huomatkaa lopullinen
exec "$@": kun kaikki valmistelut on tehty, shell korvataan sovellusprosessilla, jolloin siitä tulee PID 1 ja se vastaanottaa kaikki käyttöjärjestelmän signaalit suoraan.
#!/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 "$@"Tietotesti: signaalien käsittely entrypoint-skripteissä
Testatkaa, miten hyvin ymmärrätte signaalien käsittelyn konttien entrypoint-skripteissä.
Kertaus: kevyet Dockerfile-tiedostot ja shell-entrypoint-skriptit
Olette käsitelleet tuotantokonttien kirjoittamisen koko kokonaisuuden:
- Monivaiheiset koonnit käyttävät useita
FROM-ohjeita pitääkseen kääntäjät ja koontityökalut poissa lopullisesta imagesta. Näin syntyvät kevyet ja minimaaliset ajonaikaiset kerrokset. - Kerrosten järjestys — riippuvuusmanifestit kopioidaan ennen lähdekoodia — maksimoi välimuistiosumat ja nopeuttaa CI-putkia.
- BuildKit-salaisuudet ja SSH-liitännät pitävät tunnistetiedot poissa imagen historiasta rikkomatta todennusta vaativia koonteja.
- Entrypoint-skriptit tarkistavat ympäristömuuttujat, muodostavat asetustiedostot
envsubst-komennolla ja luovuttavat hallinnan sovellukselle komennollaexec "$@". - Signaalien käsittely edellyttää joko
exec-komentoa, jolloin sovellus on PID 1, tai nimenomaistatrap+kill+wait-mallia, kun käytössä on taustatöitä. - tini lisää zombie-prosessien keräämisen ja varmistaa signaalien oikean välityksen, kun kontti käynnistää useita prosesseja.
- Pääkäyttäjättömät käyttäjät ja
HEALTHCHECK-ohjeet täydentävät turvallisen ja havainnoitavan imagen, joka soveltuu Kubernetesin tuotantotyökuormiin.
Kun yhdistätte nämä mallit johdonmukaisesti, imaget ovat pienempiä, ne otetaan käyttöön nopeammin ja ne toimivat huomattavasti luotettavammin tuotanto-olosuhteissa.
Opi Bash tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 22
- Oppitunnit
- 88
Usein kysytyt kysymykset
Onko oppitunti ”Keveiden Dockerfile-tiedostojen ja shell-entripointien kirjoittaminen” ilmainen?
Kyllä – oppitunnin ”Keveiden Dockerfile-tiedostojen ja shell-entripointien kirjoittaminen” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Linux-komentorivin ja Bash-komentosarjojen hallinta-kurssin, päivitä CoddyKit PROhon. Linux-komentorivin ja Bash-komentosarjojen hallinta-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Keveiden Dockerfile-tiedostojen ja shell-entripointien kirjoittaminen”?
Kirjoita monivaiheisia koontiskriptejä ja vankkoja entrypoint-sovittimia, joissa on signaalien käsittely ja määritysten mallipohjat. Harjoittelet Linux-komentorivin ja Bash-komentosarjojen hallinta-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Linux-komentorivin ja Bash-komentosarjojen hallinta-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Linux-komentorivin ja Bash-komentosarjojen hallinta-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.
Kuinka kauan ”Keveiden Dockerfile-tiedostojen ja shell-entripointien kirjoittaminen”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Linux-komentorivin ja Bash-komentosarjojen hallinta-oppitunnilla?
Kyllä. Jokainen Linux-komentorivin ja Bash-komentosarjojen hallinta-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Keveiden Dockerfile-tiedostojen ja shell-entripointien kirjoittaminen
- Määritysten mallintaminen envsubstilla ja heredoc-rakenteilla
- Pilviresurssien skriptaus CLI-työkaluilla ja jq:lla
- Kuntotarkistukset, valmiusportit ja odotussilmukat