VPSలో Docker Compose: build vs image తేడా
image key ప్రచురించిన tagను pull చేస్తుంది, build key స్థానికంగా imageను తయారు చేస్తుంది. VPSలో compose up Dockerfile మార్పును ఎందుకు పట్టించుకోదో, పరిష్కారం ఏమిటో తెలుసుకోండి.
Docker Compose build మరియు image: సంక్షిప్త సమాధానం
Docker Compose ఫైల్లో, image: registry నుంచి pull చేయాల్సిన image పేరును సూచిస్తుంది. build: ఈ machineలో Dockerfile ఆధారంగా imageను build చేయాలని Composeకు చెబుతుంది. image: మాత్రమే సెట్ చేస్తే, Compose ఆ tagను pull చేసి దాన్ని run చేస్తుంది. build: మాత్రమే సెట్ చేస్తే, Compose ఇక్కడ imageను build చేస్తుంది. దానికి project name మరియు service name ఆధారంగా పేరు ఇస్తుంది. రెండింటినీ సెట్ చేస్తే, Compose స్థానికంగా imageను build చేసి, ఫలితానికి image: లోని పేరుతో tag ఇస్తుంది. మీరు ఎంచుకున్న పేరుతో imageను build చేసి push చేయడానికి ఇదే విధానం.
ఇదే మొత్తం తేడా. కింది విషయాలు serverలో ఇది ఎలా పనిచేస్తుందో వివరిస్తాయి. Docker Engine మరియు Compose plugin ఇప్పటికే install అయి ఉన్నాయని ఇది భావిస్తుంది; VPSపై Docker నడపడం ఆ భాగాన్ని వివరిస్తుంది.
పూర్తి మూడు రూపాలు
ప్రచురించిన tag ను pull చేసి, దాన్ని run చేయండి. ఏ దశలోనూ Dockerfile ఉపయోగించబడదు.
services:
web:
image: nginx:1.27
restart: unless-stopped
ports:
- "80:80"ప్రస్తుత directory లోని Dockerfile నుంచి build చేయండి. FROM లో పేర్కొన్న base image తప్ప మరేదీ pull చేయబడదు.
services:
web:
build: .
restart: unless-stopped
ports:
- "80:80"స్థానికంగా build చేసి, ఫలితానికి tag ఇవ్వండి. ఆ ఖచ్చితమైన tag ను registry కి పంపడానికి docker compose push ను ఉపయోగించవచ్చు.
services:
web:
build:
context: .
dockerfile: Dockerfile
image: registry.example.com/acme/web:1.4.2
restart: unless-stopped
ports:
- "80:80"context అనేది builder కు పంపే directory. dockerfile ఆ context కు సంబంధించి resolve అవుతుంది. అందువల్ల dockerfile: docker/prod.Dockerfile తో context: . ఉపయోగించడం సాధారణం మరియు సరైనదే. ప్రతి service container వెనుక ఉన్న image name మరియు image ID చూడటానికి docker compose images ను run చేయండి. మీరు వాస్తవంగా ఈ మూడు రూపాల్లో ఏదిని రాశారో నిర్ధారించడానికి ఇదే వేగవంతమైన మార్గం.
docker compose up ఎందుకు నేను Dockerfile మార్చిన తర్వాత మళ్లీ build చేయదు?
ఎందుకంటే up image ఉందో లేదో మాత్రమే తనిఖీ చేస్తుంది. అది image తాజాగా ఉందో లేదో తనిఖీ చేయదు.
Compose, build: section ఉన్న service ను ప్రారంభించేటప్పుడు, local image store లో image కోసం చూస్తుంది. అదే పేరుతో image ఇప్పటికే ఉంటే, Compose దానినే ఉపయోగిస్తుంది. అది మీ Dockerfile ను చదవదు, source files ను పోల్చదు, timestamp ను కూడా పరిశీలించదు. Compose specification ఈ నియమాన్ని pull_policy attribute గా పేర్కొంటుంది. Default behaviour ప్రకారం image లేనప్పుడు మాత్రమే build జరుగుతుంది. Image ఉండటం సరిపోతుందని పరిగణించబడుతుంది.
అందువల్ల మీరు app.py ను మార్చి, docker compose up -d ను run చేస్తారు. Compose container running అని చూపిస్తుంది. కానీ పాత codeనే serve అవుతుంది. ఏదీ విఫలం కాలేదు కాబట్టి, ఎలాంటి హెచ్చరిక కూడా కనిపించదు. Composeలో “నా మార్పు అమలుకాలేదు” అనే సమస్యకు ఇది అత్యంత సాధారణ కారణం. దీన్ని గుర్తించడానికి Compose container name పక్కన చూపించే status word ను చూడండి: Compose భర్తీ చేసిన container కు recreated లేదా started అని చూపిస్తుంది. Compose అలాగే ఉంచిన container కు running అని చూపిస్తుంది.
రెండు తనిఖీలు దీనిని నిర్ధారిస్తాయి. docker compose images ప్రతి container ఉపయోగిస్తున్న image ID ను చూపిస్తుంది. కాబట్టి deploy కు ముందు దాన్ని నమోదు చేసి, తరువాతి IDతో పోల్చండి. docker image ls లో CREATED column ఉంటుంది. మీ చివరి commit కు ముందు సృష్టించబడిన image, deploy script ఏదని చూపించినా stale imageగానే ఉంటుంది.
ఏ flags rebuild ను బలవంతం చేస్తాయి
docker compose up -d --buildముందుగా build చేసి, image మారిన ప్రతి container ను మళ్లీ సృష్టిస్తుంది. చాలామంది వెతుకుతున్న flag ఇదే.docker compose build webఒక service ను build చేస్తుంది, కానీ ఏదీ start చేయదు. దీని తరువాతdocker compose up --no-deps -d webఉపయోగిస్తే ఆ container మాత్రమే replace అవుతుంది; మిగిలిన stack నడుస్తూనే ఉంటుంది.docker compose build --no-cache webcached layerలను అన్నింటినీ తొలగించి, మొదటి instruction నుంచి rebuild చేస్తుంది.docker compose build --pullFROMలోని base image యొక్క కొత్త version ను pull చేయడానికి ప్రయత్నిస్తుంది. అందువల్లnode:22వంటి moving tag, మార్చిలో download చేసిన copyకి బదులుగా ప్రస్తుతం ఉన్న contents ను పొందుతుంది.docker compose up -d --force-recreatecontainerలు ఇప్పటికే ఉపయోగిస్తున్న image నుంచే వాటిని మళ్లీ సృష్టిస్తుంది. ఇది ఎప్పుడూ build చేయదు. మీరు ఉద్దేశించింది--buildఅయినప్పుడు దీనిని ఉపయోగించడం సాధారణంగా సమస్యకు దారితీస్తుంది.
ఈ నిర్ణయాన్ని file లో కూడా ఉంచవచ్చు. Compose specification ప్రకారం, pull_policy: build అంటే Compose image ను build చేస్తుంది; image ఇప్పటికే ఉంటే దాన్ని rebuild కూడా చేస్తుంది. ప్రతి up సమయంలో build చేయాల్సి వస్తుంది. Laptopలో ఇది మీకు కావాల్సిందే, కానీ serverలో సాధారణంగా ఇది అవసరం ఉండదు.
services:
web:
build: .
image: registry.example.com/acme/web:dev
pull_policy: buildమరొక ముఖ్యమైన పరస్పర ప్రభావం ఉంది. docker compose pull లో build section ఉన్న services కోసం కూడా images ను pull చేయడానికి ప్రయత్నిస్తుంది. ఆ pull విఫలమైతే image ను బదులుగా build చేయాలని తెలియజేస్తుంది. ఆ services ను ఎటువంటి సందేశం లేకుండా దాటవేయడానికి --ignore-buildable pass చేయండి.
బిల్డ్ cache మీ deploy సమయాన్ని ఎలా నిర్ణయిస్తుంది
Dockerfile లోని ప్రతి instruction ఒక layer ను సృష్టిస్తుంది. ఆ instruction మరియు దాని inputs మారకపోతే builder cached layer ను మళ్లీ ఉపయోగిస్తుంది. COPY కోసం inputs అంటే copy చేస్తున్న files లోని contents. ఒక layer cache ను ఉపయోగించలేకపోతే, దాని తరువాతి ప్రతి layer మళ్లీ build అవుతుంది. ఎందుకంటే ప్రతి layer, దానికి ముందు ఉన్న layer సృష్టించిన filesystem పై build అవుతుంది.
ఈ ఒక్క నియమమే మీ deploy సెకన్లలో పూర్తవుతుందా లేదా నిమిషాలు పడుతుందా అన్నది నిర్ణయిస్తుంది. Dockerfile లో అరుదుగా మారే అంశాల నుంచి ప్రతి commitలో మారే అంశాల వరకు క్రమబద్ధీకరించండి.
FROM node:22-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
CMD ["node", "server.js"]npm ci, COPY . . పైన ఉంటుంది. అందువల్ల source file ను సవరించినప్పుడు install layer cacheలోనే ఉంటుంది. Build copy step వద్ద తిరిగి ప్రారంభమవుతుంది. ఆ రెండు lines ను మార్చి ఉంచితే, ఒక్క character మార్పుకే ప్రతి dependency మళ్లీ install అవుతుంది. ఎందుకంటే COPY . ., npm ci ఆధారపడే layer ను invalidate చేస్తుంది. ఇదే నిర్మాణం pip install -r requirements.txt కు మరియు go mod download కు కూడా వర్తిస్తుంది.
పాత layer మీ fix ను దాచిపెడుతోందని అనుమానించినప్పుడు --no-cache సరైన tool. అయితే దీన్ని defaultగా ఉపయోగించడం మంచిది కాదు. ఎందుకంటే Dockerfile ordering ద్వారా పొందాల్సిన layer reuse మొత్తం దాంతో తొలగిపోతుంది.
Image sets మరియు Compose ఒక అంశాన్ని override చేయగలవు. Dockerfile లోని CMD, image defaultగా ఏది run చేయాలో నిర్ణయిస్తుంది. Serviceలోని command: key దాన్ని భర్తీ చేస్తుంది. command మరియు entrypoint ఎలా పరస్పరం పనిచేస్తాయి అనే విషయం ఇక్కడ ముఖ్యమైనది. ఎందుకంటే Compose override వల్ల తాజాగా build చేసిన image కూడా పాత imageలాగే పనిచేయవచ్చు.
Build context మరియు .dockerignore
context: . మొదటి instruction అమలుకాకముందే ఆ directory మొత్తాన్ని ప్యాకేజ్ చేసి builder కు పంపుతుంది. అందులోని ప్రతిదీ వెళ్తుంది. ఇందులో .git మరియు source పక్కన మీరు ఉంచిన ఏ data directory అయినా ఉంటాయి. మార్పులేని project లో build, transferring-context దశ వద్ద నిలిచిపోతే, context పరిమాణం చాలా పెద్దదని అర్థం.
Context root వద్ద ఉన్న .dockerignore file, ఆ transfer నుంచి paths ను మినహాయిస్తుంది. దీని syntax .gitignore కు దగ్గరగా ఉంటుంది.
.git
node_modules
*.log
data/
.envదీంతో రెండు ప్రయోజనాలు ఉన్నాయి. Transfer పరిమాణం తగ్గుతుంది కాబట్టి ప్రతి build వేగంగా ప్రారంభమవుతుంది. అలాగే COPY . . ఇకపై .env ను image లోకి copy చేయలేరు. ఆ image ను pull చేసే ఎవరైనా దానిలోని సమాచారాన్ని తిరిగి చదవగలరు.
కాలక్రమేణా పెరిగే bind mount వల్ల build నెమ్మదించే పరిస్థితి సాధారణం. Named volume మీ project directory వెలుపల ఉంటుంది. అయితే ./data:/var/lib/postgresql/data వంటి bind mount build context లోనే ఉంటుంది. అందువల్ల database పెరుగుతున్న కొద్దీ ప్రతి వారం builds మరింత నెమ్మదిస్తాయి. .dockerignore లో ఒక line దీనిని పరిష్కరిస్తుంది. విస్తృత trade-off గురించి Named volumes కు బదులుగా bind mounts లో వివరించారు.
Build arguments కూడా ఇదే ప్రమాదానికి చిన్న రూపాన్ని కలిగి ఉంటాయి. args: ద్వారా పంపిన values image history లో కనిపిస్తాయి. Image ఉన్న ఎవరైనా వాటిని చూడగలరు. కాబట్టి అక్కడ version number మాత్రమే ఉంచండి. Token ను ఎప్పుడూ ఉంచవద్దు. Credentials ఎక్కడ ఉండాలో Compose లో Env files మరియు secrets లో వివరించారు.
VPSపై build చేయాలా, లేక వేరే చోట build చేసి pull చేయాలా?
మీ traffic ను అందించే box పైనే build చేయడం సాధారణ default. కారణం, ఇది అత్యంత చిన్న మార్గం: git pull, తరువాత docker compose up -d --build. ఇంకా ఎవరూ ఆధారపడని చిన్న server పై ఇది సరైనదే. కానీ కొలవగల రెండు కారణాల వల్ల, అలాగే చెడు రోజున మాత్రమే కనిపించే మరో కారణం వల్ల ఇది సరైన విధానం కాకుండా మారుతుంది.
Memory. Build సమయంలో live application పక్కనే compilers మరియు bundlers నడుస్తాయి. చాలా stacks లో ఇవే ఎక్కువ memory ఉపయోగించే భాగాలు. 1 GB VPSలో JavaScript bundler లేదా Rust compile సాధారణంగా ఆ boxలో అతిపెద్ద process అవుతుంది. Kernel వద్ద memory అయిపోతే అది అతిపెద్ద process ను kill చేస్తుంది: build Killed మరియు exit status 137 తో ఆగిపోవచ్చు, లేదా బదులుగా database kill అయి deploy మధ్యలోనే site down కావచ్చు. ఏది జరిగిందో ఊహించకుండా తెలుసుకోవడానికి dmesg -T | grep -i oom process name తో kill line ను చూపిస్తుంది.
Disk. ప్రతి build కొన్ని layers ను మిగులుస్తుంది. Builder మీ images కు వేరుగా తన cache ను కూడా ఉంచుతుంది. docker system df రెండింటినీ చూపిస్తుంది. Build cache row నిరంతరం పెరుగుతుంది. Dangling images కోసం docker image prune, cached layers కోసం docker builder prune ఉపయోగించి reclaim చేయండి. Disk పూర్తిగా నిండితే build మాత్రమే ఆగదు. Database కూడా రాయడం ఆపుతుంది. ఆ వైఫల్యంతో కలిగే నష్టం slow deploy కంటే చాలా ఎక్కువ.
Reproducibility. Serverపై build చేసిన image ఆ serverలో మాత్రమే ఉంటుంది. Rollback చేయాలంటే పాత commit ను checkout చేసి మళ్లీ build చేయాలి. ఆ build మీరు ముందుగా పొందినదానినే ఇస్తుందని హామీ లేదు. కారణం, base tag మారి ఉండవచ్చు, అలాగే package mirrors కూడా మారి ఉండవచ్చు. వేరే చోట build చేసి tag push చేస్తే rollback ఒక editగా మారుతుంది: image: ను మునుపటి tag కు point చేసి docker compose up -d అమలు చేయండి.
స్థిరంగా పనిచేసే విధానం సులభంగా ఉంటుంది. మీ continuous integration build ను నడిపి registry.example.com/acme/web:<git-sha> ను push చేస్తుంది. VPSలోని Compose file image: ను కలిగి ఉంటుంది; అందులో build: key ఉండదు. అప్పుడు deployment కు దాదాపు ఎలాంటి memory అవసరం లేని రెండు commands మాత్రమే అవసరం.
docker compose pull
docker compose up -dServerపై ఒకసారి docker login registry.example.com అమలు చేయండి. ఆ తరువాత Compose private tags ను pull చేయగలదు.
Build section ను development కోసం ఉంచండి. దాన్ని తొలగించవద్దు. మీకు నచ్చిన పేరుతో ఒక fileలో ఉంచండి.
# compose.dev.yaml
services:
web:
build:
context: .
pull_policy: builddocker compose -f compose.yaml -f compose.dev.yaml up -d --buildఆ fileకు compose.dev.yaml అని పేరు పెట్టండి, compose.override.yaml అని కాదు. Override file అందుబాటులో ఉన్నప్పుడల్లా Compose దాన్ని స్వయంచాలకంగా load చేస్తుంది. అందువల్ల serverకు అనుకోకుండా copy చేసిన override మళ్లీ అక్కడ build ను ప్రారంభించవచ్చు. అనేక Compose files ను పొరలుగా ఉపయోగించడం ప్రతి key merge ఎలా పరిష్కరించబడుతుందో వివరిస్తుంది.
మీరు వేరే చోట build చేసినప్పుడు ఎదురయ్యే architecture సమస్య
ఒక image అది build చేసిన CPU architecture వివరాలను కలిగి ఉంటుంది. Apple Silicon laptop పై build చేసి, దాన్ని push చేసి, ఆ tag ను x86_64 VPS లోకి pull చేస్తే, అభ్యర్థించిన image platform మరియు గుర్తించిన host platform సరిపోలడం లేదని Docker హెచ్చరిస్తుంది. తరువాత process exec format error తో ఆగిపోతుంది. ఆ సందేశం corrupt binary ను సూచిస్తున్నట్లు కనిపిస్తుంది, కానీ కారణం అది కాదు. Target కోసం స్పష్టంగా build చేయండి:
docker buildx build --platform linux/amd64 \
-t registry.example.com/acme/web:1.4.2 --push .మీ laptop x86 అయి, x86 VPS బదులు ARM VPS పై run చేసినప్పుడు కూడా ఇదే mismatch జరుగుతుంది. మీరు deploy చేసే architecture పైనే CI ద్వారా build చేయిస్తే ఈ సమస్య ఉండదు.
deploy తర్వాత తనిఖీ చేయాల్సినవి
docker compose imagesనడుస్తున్న ప్రతి container వెనుక ఉన్న image మరియు tag ను చూపిస్తుంది. image ID మారితే, కొత్త build సేవలోకి వచ్చినట్లు నిర్ధారించవచ్చు.docker compose configvariable substitution తర్వాత merge అయిన file ను చూపిస్తుంది. ఏదైనా run చేయడానికి ముందు Compose ఉపయోగించే తుది image పేరు ఏమిటో చదవవచ్చు.- swap చేసిన తర్వాత మొదటి 30 seconds పాటు
docker compose logs -f webను అమలు చేయండి. ప్రారంభమై వెంటనే ముగిసే container నిరంతరం restart loop లోకి వెళ్తుంది. మీరు పరిశీలించకపోతే ఈ loop కనిపించకుండా కొనసాగుతుంది. docker image lsCREATED column ను చూపిస్తుంది. మీ చివరి commit కంటే పాత image మళ్లీ build కాలేదు.
ఈ తనిఖీలు పనిచేసే file ను మీరు ఇంకా సిద్ధం చేస్తుంటే, VPSలో Compose file ప్రాథమిక అంశాలు సంబంధిత keys ను వివరిస్తుంది. Compose command cheat sheet మిగిలిన subcommands జాబితాను అందిస్తుంది.
FAQ
build మరియు image ను ఒకే service లో ఉపయోగించవచ్చా?
అవును. మీరు స్వయంగా build చేసే project కు ఇది సాధారణ setup. Compose, build: section ఆధారంగా build చేసి, ఫలితానికి image: విలువతో tag ఇస్తుంది. ఆ tag ను docker compose push registry కి పంపుతుంది; మరో machine అదే tag ను pull చేస్తుంది. image: key లేకపోయినా Compose build చేస్తుంది. అయితే image కు project మరియు service పేర్ల ఆధారంగా పేరు ఇస్తుంది. అలాగే ఆ attribute లేకపోవడం వల్ల image push చేయలేమని హెచ్చరిస్తుంది.
Dockerfile లో చేసిన మార్పును docker compose up ఎందుకు గుర్తించదు?
ఎందుకంటే up ఆ పేరుతో image ఉందా లేదా అనే విషయాన్ని మాత్రమే పరిశీలిస్తుంది. Image ఉంటే Compose దానినే ప్రారంభిస్తుంది. మీ Dockerfile లేదా source files తో దాన్ని పోల్చదు. docker compose up -d --build ను run చేయండి. లేదా ఒక service ను భర్తీ చేయడానికి docker compose build web తరువాత docker compose up --no-deps -d web ను run చేయండి. Service పై pull_policy: build సెట్ చేస్తే ప్రతి up సమయంలో rebuild జరుగుతుంది. ఇది development machine కు అనుకూలంగా ఉంటుంది.
--build మరియు --force-recreate మధ్య తేడా ఏమిటి?
--build image ను మళ్లీ build చేస్తుంది. తరువాత image మారిన containers ను మళ్లీ సృష్టిస్తుంది. --force-recreate ఇప్పటికే ఉన్న image నుంచే containers ను మళ్లీ సృష్టిస్తుంది. అందువల్ల code మార్పును ఇది ఎప్పటికీ స్వీకరించదు. మీ మార్పు source లేదా Dockerfile లో ఉంటే --build flag ఉపయోగించాలి. Container ను మాత్రమే reset చేయడానికి --force-recreate ఉపయోగించాలి. ఉదాహరణకు, అదే image ను ఉంచి container లోని writable layer ను తొలగించడానికి దీన్ని ఉపయోగించవచ్చు.
నా Docker images ను VPS పై build చేయాలా, లేక వేరే చోట build చేయాలా?
VPS పై traffic కూడా అందిస్తున్నప్పుడు build ను వేరే చోట చేసి, తరువాత tag ను pull చేయండి. Build మీ application తో memory కోసం పోటీ పడుతుంది. చిన్న VPS లో kernel పెద్ద process ను terminate చేయడం ద్వారా ఈ సమస్యను పరిష్కరించవచ్చు. ఆ process build కావచ్చు, లేదా మీ database కావచ్చు. Build లు disk పై cache ను కూడా వదిలిపెడతాయి. దాన్ని మీ తరఫున ఏ ప్రక్రియ కూడా తొలగించదు. Users లేని చిన్న project కు server పై build చేయడం సరిపోతుంది. అయితే build: section ను development-only Compose file లో ఉంచితే తరువాత మారడం సులభం మరియు ఖర్చు తక్కువగా ఉంటుంది.
Docker build cache నా disk నిండకుండా ఎలా ఆపాలి?
మీ images మరియు build cache ఒక్కొక్కటి ఎంత space ఉపయోగిస్తున్నాయో చూడటానికి docker system df ను run చేయండి. docker builder prune cached layers ను తొలగిస్తుంది. docker image prune గత build ల తర్వాత మిగిలిన dangling images ను తొలగిస్తుంది. వీటిలో ఏదైనా command కు -a జోడిస్తే మరింత తీవ్రంగా cleanup జరుగుతుంది. తదుపరి build cache లేకుండా మొదలవుతుంది. Server పై docker system prune -af --volumes ను schedule చేయవద్దు. ఎందుకంటే --volumes ప్రస్తుతం ఏ container కూడా ఉపయోగించని volume ను తొలగిస్తుంది. Maintenance కోసం ఆపిన stack లో database సరిగ్గా అలాంటి volume లోనే ఉండవచ్చు.