Docker Compose stack चा backup आणि upgrade कसा करावा
Docker Compose deploy मार्गदर्शक login screen वर थांबतात. नेमके काय dump करावे, कोणते volumes जतन करावे, restore सिद्ध कसा करावा आणि upgrade आधी backup कसा घ्यावा ते जाणून घ्या.
Docker Compose stack backup मध्ये काय असणे आवश्यक आहे
Docker Compose stack backup मध्ये चार स्वतंत्र गोष्टी असणे आवश्यक आहे. यांपैकी एकही गोष्ट हरवल्यास अॅप पुन्हा सुरू होणार नाही: compose file, त्याच्या शेजारी असलेली .env, प्रत्येक volume मधील सामग्री आणि database च्या स्वतःच्या client ने तयार केलेला database dump. Container चालू असताना database च्या files कॉपी करणे म्हणजे backup नाही. Upgrades साठी हीच यादी लागू होते आणि त्यासोबत एक नियम आहे: pull करण्यापूर्वी backup घ्या, कारण schema migrations पुढील आवृत्तीकडे जाण्यासाठी लिहिलेल्या असतात आणि बहुतेक projects मध्ये मागील आवृत्तीकडे परतण्याची पद्धत नसते.
खालील सर्व माहिती stack आधीच deployed आहे आणि docker compose ps मध्ये तो चालू असल्याचे दिसते, असे गृहीत धरते. उदाहरणांमध्ये /srv/myapp येथील project directory आणि app व db अशी services वापरल्या आहेत. तुमची स्वतःची नावे वापरा. Commands मुद्दाम generic ठेवले आहेत, कारण महत्त्वाचे भाग—volumes आणि database—अॅप कोणतेही असले तरी त्याच पद्धतीने कार्य करतात.
तुमच्या stack मध्ये प्रत्यक्षात काय साठवले जाते ते शोधा
cd /srv/myapp
docker compose ps
docker compose config --volumes
docker volume ls --filter label=com.docker.compose.project=myappdocker compose config --volumes तुमच्या file मध्ये घोषित केलेल्या named volumes ची संक्षिप्त नावे दाखवते. docker volume ls हे volumes disk वर प्रत्यक्षात कोणती नावे धारण करतात ती दाखवते. या दोन याद्या वेगळ्या असतात, कारण Compose project name पुढे जोडते: file मध्ये db_data असे लिहिलेले volume प्रत्यक्षात myapp_db_data या नावाने अस्तित्वात असते. Project name साठी default म्हणून directory name वापरले जाते. त्यामुळे directory चे नाव बदलल्यास stack रिकाम्या volumes च्या नव्या संचाकडे निर्देश करतो आणि तुमचा डेटा असलेले जुने volumes तिथेच राहतात. खालील प्रत्येक command साठी docker volume ls मधून मिळालेले प्रत्यक्ष नाव वापरा.
Bind mounts यापैकी कोणत्याही यादीत दिसत नाहीत. Compose file मध्ये colon च्या डाव्या बाजूला host path असलेल्या entries म्हणजे bind mounts, ./config:/app/config. त्या host वरील सामान्य directories असतात, त्यामुळे सामान्य tools वापरून त्यांच्यापर्यंत पोहोचता येते. Named volumes /var/lib/docker/volumes/ अंतर्गत साठवले जातात आणि docker volume inspect --format '{{.Mountpoint}}' myapp_db_data त्यांपैकी एका volume चा अचूक path दाखवते. तुमचा stack कोणता प्रकार वापरतो यावर त्याची प्रत कशी तयार करायची हे ठरते. bind mounts आणि named volumes मधील फरक या विषयातील trade-off चे संपूर्ण स्पष्टीकरण देते.
आता तुम्हाला सापडलेल्या गोष्टी दोन गटांत विभागा. काही volumes मध्ये असे state असते जे काहीही पुन्हा तयार करू शकत नाही: upload केलेल्या files, generated keys, database स्वतः आणि वापरकर्त्याने app मध्ये टाइप केलेली कोणतीही माहिती. इतर volumes मध्ये thumbnails आणि search indexes सारखा derived data असतो, जो app स्वतः पुन्हा तयार करते. दुसऱ्या गटाचा backup घेतल्याने disk space आणि restore time खर्च होतो, पण कोणताही फायदा मिळत नाही. Redis cache volume हे याचे सर्वात स्पष्ट उदाहरण आहे: ते गमावल्यास पहिली request फक्त धीमी होते.
compose फाइल आणि .env फाइलचा बॅकअप घ्या
दोन्ही फाइल्स host वर एकमेकींच्या शेजारी असतात आणि त्यांपैकी कोणतीही volume मध्ये नसते. .env मध्ये database password, application secret आणि API tokens असतात. त्यामुळे volumes चा संच पुन्हा कार्यरत अॅपमध्ये रूपांतरित करणारी हीच फाइल असते. ती सहसा .gitignore मध्येही सूचीबद्ध असते. त्यामुळे "माझे configuration git मध्ये आहे" या योजनेत सर्वात महत्त्वाची एकमेव फाइल वगळली जाते. env फाइलमध्ये secrets ठेवणे ही योग्य पद्धत आहे आणि त्यामुळे तुमच्या backup वरही त्यानुसार जबाबदारी येते.
sudo install -d -m 700 -o "$USER" -g "$(id -gn)" /srv/backups/myapp
cp -a compose.yaml .env /srv/backups/myapp/
chmod 600 /srv/backups/myapp/.envStack वापरत असलेल्या प्रत्येक compose फाइलची प्रत घ्या; फक्त पहिल्या फाइलची नाही. -f compose.yaml -f compose.prod.yaml ने सुरू केलेला stack त्याच प्रकारे पुन्हा सुरू करण्यासाठी दोन्ही फाइल्स आवश्यक असतात. तसेच अनेक compose फाइल्स कशा merge होतात यावर कोणती values container पर्यंत पोहोचतात हे ठरते.
एक सूचना .env ला volumes शी जोडते. अधिकृत Postgres image रिकामी data directory initialise करताना फक्त POSTGRES_PASSWORD वाचते. नंतर ती value बदलल्याने database मधील password बदलत नाही. मागील महिन्याची volume आजच्या .env सोबत restore केली, तर दोन्ही फाइल्स तपासल्यावर योग्य दिसत असूनही app FATAL: password authentication failed for user "appuser" सह connect होण्यात अपयशी ठरतो. .env आणि volumes एकाच वेळचे असतील, तर ते एकाच backup मध्ये एकत्र ठेवा.
डेटाबेसच्या स्वतःच्या client ने dump घ्या
डेटाबेस सर्व्हर त्याच्या files मध्ये सतत लिहित असतो. सर्व्हर सुरू असताना घेतलेली tar ची /var/lib/postgresql/data काही pages write होण्यापूर्वीची आणि काही write झाल्यानंतरची कॉपी करू शकते. त्यामुळे archive मध्ये वेगवेगळ्या क्षणांचे मिश्रण असते आणि ते पुन्हा लागू करता येईलच असे नाही. Dump tool एका transaction मध्ये वाचतो. त्यामुळे file मध्ये एका सुसंगत क्षणाची स्थिती असते. या फरकामुळे backup आणि copy यांच्यात फरक पडतो.
docker compose exec -T db sh -c \
'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' \
> /srv/backups/myapp/db-$(date +%F).dump-T कायम ठेवा. यामुळे TTY allocation बंद होते. TTY जोडलेले असताना Docker output stream ला तुमच्या shell कडे पाठवताना त्याचे रूपांतर करते. त्यामुळे binary dump खराब होतो. Restore अयशस्वी झाल्यावरच हे लक्षात येते. Single quotes देखील महत्त्वाचे आहेत. ते तुमच्या host shell ला $POSTGRES_USER expand करण्यापासून थांबवतात. त्यामुळे container मधील shell ते expand करते आणि compose file मध्ये आधीच सेट केलेली values वापरते. -Fc custom format लिहिते. या format मध्ये dump तयार होताना compression होते आणि नंतर pg_restore वापरून त्यातील objects निवडता येतात.
Roles आणि त्यांचे passwords कोणत्याही एका database बाहेर साठवलेले असतात. त्यामुळे त्यांचाही dump घ्या:
docker compose exec -T db sh -c 'pg_dumpall -U "$POSTGRES_USER" --globals-only' \
> /srv/backups/myapp/globals.sqlत्यानंतर file मध्ये dump आहे, error message नाही, हे तपासा:
ls -lh /srv/backups/myapp/
head -c 5 /srv/backups/myapp/db-$(date +%F).dumpCustom-format dump ची सुरुवात पाच bytes PGDMP ने होते. Zero bytes ची file किंवा pg_dump: ने सुरू होणारी file म्हणजे command अयशस्वी झाली आहे. Command सुरू होण्यापूर्वीच shell output file तयार करते. त्यामुळे dump अयशस्वी झाला तरी योग्य नाव आणि योग्य timestamp असलेली file मागे राहते. ही सर्वात सामान्य silent backup failure आहे.
MariaDB किंवा MySQL साठी client बदलतो, पण पद्धत तीच राहते:
docker compose exec -T db sh -c \
'mariadb-dump -u root -p"$MARIADB_ROOT_PASSWORD" --single-transaction --databases "$MARIADB_DATABASE"' \
> /srv/backups/myapp/db-$(date +%F).sql--single-transaction writers ना block न करता InnoDB tables चा सुसंगत dump देते. MySQL image मध्ये command mysqldump आहे आणि variables MYSQL_ROOT_PASSWORD आणि MYSQL_DATABASE आहेत. सध्याच्या MariaDB images मध्ये mysqldump हे mariadb-dump साठी compatibility name म्हणून अजूनही कार्य करते. Command line वर दिलेला password dump सुरू असेपर्यंत container च्या process list मध्ये दिसतो, हे लक्षात ठेवा.
SQLite साठी स्वतंत्र काळजी घ्यावी लागते. Database एकाच file मध्ये असतो. परंतु अलीकडील transactions त्याच्या बाजूला असलेल्या स्वतंत्र -wal file मध्ये असू शकतात. त्यामुळे फक्त .db कॉपी केल्यास नवीनतम writes नसलेला database मिळतो. Image मध्ये client उपलब्ध असल्यास app सुरू असतानाच sqlite3 /data/app.db ".backup '/data/app-backup.db'" सुसंगत copy लिहिते. तो उपलब्ध नसल्यास container थांबवा आणि .db file तिच्या -wal आणि -shm companions सोबत कॉपी करा.
तुमचा database stack च्या आत नसून host वर चालत असल्यास docker compose exec prefix शिवाय हीच commands लागू होतात. पुढील rebuild करण्यापूर्वी Docker मध्ये किंवा host वर database चालवणे हा भाग वाचणे उपयुक्त ठरेल.
व्हॉल्यूमचा संग्रह तयार करा
Named volume साठी हाताने संपादित करता येईल असा host path नसतो. त्यामुळे तो तात्पुरत्या container मध्ये mount करा आणि तेथून त्याचा archive तयार करा.
docker run --rm \
-v myapp_uploads:/data:ro \
-v /srv/backups/myapp:/backup \
alpine:3 tar czf /backup/uploads.tar.gz -C /data .Helper container volume ला /data येथे read-only पद्धतीने आणि backup directory ला /backup येथे mount करतो. त्यानंतर तो archive host side वर लिहितो. --rm, tar संपताच helper काढून टाकतो. :ro महत्त्वाचे आहे, कारण चुकीची tar command source मध्ये बदल करू शकत नाही. Restore योग्य ठिकाणी होण्यासाठी -C /data . आवश्यक आहे. यामुळे प्रत्येक path volume root च्या तुलनेत साठवला जातो. त्याऐवजी tar czf /backup/uploads.tar.gz /data लिहिल्यास प्रत्येक path ला सुरुवातीला data/ जोडले जाते. त्यामुळे restore करताना volume मध्ये /data/data तयार होते आणि अॅपला रिकामी directory दिसते. Container मध्ये tar root म्हणून चालल्यामुळे archive चा मालक root असतो. यामुळे अडचण येत असल्यास sudo chown "$USER" /srv/backups/myapp/uploads.tar.gz चालवा. Restore केलेल्या files अॅपला वाचता येत नसतील, तर PUID आणि PGID file ownership कसे ठरवतात हे वाचा.
प्रत्येक named volume साठी ही command एकदा चालवा. Bind mounts साठी container ची गरज नाही: tar czf /srv/backups/myapp/config.tar.gz -C /srv/myapp/config . host वर तेच काम करते.
प्रत्येक volume साठी अॅप थांबवणे आवश्यक आहे का ते ठरवा. अॅप ज्या volume मध्ये files जागेवरच पुन्हा लिहितो, त्या volume वर चालू स्थितीत tar केल्यास एखादी file लिहिताना अर्धवट साठवली जाऊ शकते. Uploads directory साठी हा धोका कमी असतो, कारण files एकदा लिहिल्यानंतर फक्त वाचल्या जातात. इतर कोणत्याही बाबतीत copy चालू असेपर्यंत ती service docker compose stop app ने थांबवा आणि त्यानंतर docker compose start app चालवा. stop containers आणि volumes जसेच्या तसे ठेवतो. या परिस्थितीत तुम्हाला नेमके हेच हवे आहे. त्यामुळे यापैकी कोणतीही command देण्यापूर्वी down आणि stop मधील फरक नीट समजून घ्या.
Database volume च्या tar archive ला database backup समजू नका. Dump हाच backup आहे. थांबवलेल्या database चा volume archive जलद पुनर्बांधणीसाठी उपयुक्त मार्ग आहे; त्यापेक्षा अधिक काही नाही.
कार्यपद्धतीचा क्रम
- Compose files आणि
.envbackup directory मध्ये कॉपी करा. - Database अजून चालू असतानाच त्याचा dump घ्या.
- App container च्या volumes मध्ये थेट बदल होत असल्यास तो थांबवा.
- प्रत्येक named volume आणि प्रत्येक bind-mount directory चे archive तयार करा.
- तुम्ही थांबवलेल्या गोष्टी पुन्हा सुरू करा आणि नंतर
docker compose psने पडताळणी करा. - Stack कोणते image tags आणि digests वापरून चालत आहे ते नोंदवून ठेवा.
- संपूर्ण backup directory या server च्या बाहेर कॉपी करा.
Step 7 हेच काम लोक नंतर करण्यासाठी ठेवतात.
सर्व्हरबाहेर प्रत काढा
Stack ज्या disk वर आहे त्याच disk वर असलेला backup तुम्हाला फक्त स्वतःच्या चुकांपासून संरक्षण देतो. इतर कोणत्याही धोक्यापासून तो संरक्षण देत नाही. एक volume निकामी होणे, एक server delete होणे किंवा एक account गमावणे यामुळे दोन्ही प्रती एकाच वेळी नष्ट होऊ शकतात. Directory या VPS व्यतिरिक्त इतर storage वर ठरावीक वेळापत्रकानुसार पाठवा आणि retention policy लागू करा. VPS वरील restic backups मध्ये repository setup, retention flags आणि check command यांचा समावेश आहे. त्यामुळे ते येथे पुन्हा सांगण्याची गरज नाही.
restic dump थेट pipe मधूनही वाचू शकते. त्यामुळे plaintext database पूर्णपणे disk वर न लिहिता ठेवता येतो:
docker compose exec -T db sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' \
| restic backup --stdin --stdin-filename db.dumpतुम्ही कोणतेही tool वापरत असलात तरी schedule systemd timer किंवा cron job मध्ये ठेवा. तसेच job अयशस्वी झाल्यास त्याचा अहवाल तुम्हाला दिसेल अशा ठिकाणी पाठवा. ज्याचे output कुठेही जात नाही अशी backup script सहा महिने कार्य करणे थांबवू शकते आणि कोणाच्याही लक्षात येणार नाही.
बॅकअप restore drill करून तो कार्यरत असल्याचे सिद्ध करा
ज्या बॅकअपमधून अद्याप कोणीही restore केलेले नाही, तो केवळ एक अंदाज आहे. खालील drill पहिल्या stack च्या बाजूला चालणाऱ्या दुसऱ्या stack मध्ये restore करतो. त्यामुळे production सेवा देत राहते आणि तुम्ही टाइप केलेली कोणतीही गोष्ट production पर्यंत पोहोचत नाही.
यासाठी project name वापरले जाते. Compose हे नाव directory name मधून घेतो आणि त्याने तयार केलेल्या प्रत्येक container आणि volume वर ते नोंदवतो. बॅकअप नवीन directory मध्ये copy केल्यावर restore केलेल्या stack ला त्याचे स्वतःचे volumes आपोआप मिळतात.
sudo install -d -m 700 -o "$USER" -g "$(id -gn)" /srv/myapp-restore
cd /srv/myapp-restore
cp /srv/backups/myapp/compose.yaml /srv/backups/myapp/.env .कॉपी केलेली compose file edit करा, जेणेकरून प्रकाशित host port चालू stack शी conflict होणार नाही. 8080:8080 च्या जागी 18080:8080 ठेवा किंवा कॉपी केलेल्या .env मध्ये तो port सेट करणारा variable बदला. त्यानंतर काहीही सुरू न करता containers आणि त्यांचे रिकामे volumes तयार करा:
docker compose create
docker volume ls --filter label=com.docker.compose.project=myapp-restoreदुसऱ्या command ने production मधील त्याच volume names ची यादी करावी आणि त्यांच्या सुरुवातीला myapp-restore_ असावे. त्यात डेटा भरा, database स्वतंत्रपणे सुरू करा आणि dump load करा:
docker run --rm -v myapp-restore_uploads:/data -v /srv/backups/myapp:/backup \
alpine:3 tar xzf /backup/uploads.tar.gz -C /data
docker compose up -d db
docker compose exec -T db sh -c \
'pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean --if-exists' \
< /srv/backups/myapp/db-2026-08-16.dump--clean --if-exists प्रत्येक object पुन्हा तयार करण्यापूर्वी तो delete करतो. त्यामुळे restore पुन्हा चालवता येतो. हा flag नसल्यास, आधीच ते tables असलेल्या database मध्ये दुसऱ्यांदा चालवल्यावर प्रक्रिया pg_restore: error: could not execute query: ERROR: relation "users" already exists मुळे थांबते.
त्यानंतर उर्वरित सेवा सुरू करा आणि वापरकर्ता ज्या पद्धतीने तपासेल त्या पद्धतीने तपासा:
docker compose up -d --wait
docker compose exec -T db sh -c 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt"'
docker compose logs --tail=50docker compose up -d --wait प्रत्येक service running किंवा healthy असल्याचे कळेपर्यंत थांबतो. एखादी service कधीही त्या स्थितीत पोहोचली नाही, तर तो non-zero exit करतो. त्यामुळे हा टप्पा script मध्ये वापरता येतो. एखादी service healthy होत नसेल, तर docker compose ps तिची स्थिती दाखवतो. Compose healthchecks मध्ये त्या column मधील माहितीचा अर्थ स्पष्ट केला आहे. त्यानंतर alternate port वर app उघडा आणि प्रत्यक्ष account ने log in करा. एक record लिहा आणि volume मध्ये असलेली एक file उघडा. हाच पुरावा आहे: dump restore झाला, volume restore झाला आणि दोन्ही एकमेकांशी सुसंगत आहेत. Login page दिसते एवढेच सिद्ध करणाऱ्या drill ने तुमच्या डेटाबद्दल काहीही सिद्ध केलेले नाही.
Drill यशस्वी झाल्यावर तो हटवा:
docker compose down -v-v हा flag वापरण्याचे योग्य ठिकाण हेच आहे. Production directory मध्ये हीच command तुम्ही जतन करू इच्छित असलेले volumes delete करते.
Compose stack चे upgrade कसे करावे
तुम्ही सध्या चालवत असलेल्या आवृत्तीपासून तुम्हाला हवी असलेली आवृत्तीपर्यंतच्या प्रत्येक आवृत्तीच्या release notes वाचा आणि त्यात breaking आणि migration हे शब्द शोधा. अनेक major versions वगळून थेट upgrade करण्याचे समर्थन नसलेल्या projects मध्ये हे स्पष्टपणे नमूद केलेले असते. Migration अयशस्वी होण्यापूर्वी schema चा काही भाग बदललेला असू शकतो.
काहीही बदलण्यापूर्वी सध्या काय चालू आहे ते नोंदवा:
docker compose images
docker image inspect --format '{{index .RepoDigests 0}}' postgres:16.4docker compose images प्रत्येक service सध्या वापरत असलेली image आणि tag दाखवते. Image चे अचूक नाव दर्शवणारी एकमेव value म्हणजे digest. कारण tag कोणत्याही वेळी दुसऱ्या image कडे हलवता येतो.
वरील sections मधून घेतलेला backup box बाहेरच्या सुरक्षित ठिकाणी copy करा. Patch release साठीही हे करा. लोक ज्या upgrades साठी तयारी करणे थांबवतात, तेच upgrades सहसा सोपे असतात.
त्यानंतर compose file मध्ये version pin करा, कारण latest ही version नाही:
services:
db:
image: postgres:16.4image: postgres:latest वापरल्यावर docker compose pull आज त्या tag ने दर्शवलेल्या कोणत्याही image ला fetch करते. त्यामुळे काल तुम्ही नेमके काय चालवत होतात, हे सांगण्याचा कोणताही मार्ग राहत नाही. Pinned tag मुळे upgrade एकाच ओळीतील बदल बनतो. तो बदल तुम्ही git diff मध्ये वाचू शकता आणि आणखी एक बदल करून पूर्वस्थितीत आणू शकता. Application image साठीही हीच पद्धत वापरा आणि project's release page वरून अचूक version घ्या.
Pull करून containers पुन्हा तयार करा:
docker compose pull
docker compose up -d --waitdocker compose up -d ही file चालू containers शी तुलना करते आणि ज्या services ची image किंवा configuration बदलली आहे, त्याच पुन्हा तयार करते. Named volumes वर त्याचा परिणाम होत नाही. त्यामुळे नवीन container विद्यमान data वर सुरू होतो. याचाच उद्देश आहे आणि हाच धोका देखील आहे, कारण नवीन version सुरू होण्याच्या वेळीच त्याचे schema migration सहसा चालते.
काय घडते आहे ते monitor करा:
docker compose ps
docker compose logs -f --tail=100 appअयशस्वी झालेल्या container साठी docker compose ps मधील STATUS column मध्ये Exited (1) दिसते. त्याचे कारण log च्या शेवटच्या ओळींमध्ये असते. Migration errors तिथे स्पष्टपणे दिसतात आणि इतरत्र दिसत नाहीत. Logs स्थिर झाल्यावर login करा आणि app एक मिनिट वापरून पाहा.
जर docker compose pull हे no space left on device सह थांबले, तर जुने image layers हे सहसा कारण असते. वापरात नसलेल्या Docker images काढून टाकल्याने जागा मोकळी होते. Pruning upgrade यशस्वी असल्याची खात्री झाल्यानंतर करा, आधी करू नका. कारण जलद rollback साठी ते जुने layers आवश्यक असतात.
अपग्रेड अयशस्वी झाल्यावर rollback कसे करावे
यामध्ये दोन परिस्थिती असतात आणि त्यांचा खर्च वेगवेगळा असतो. नवीन आवृत्तीने schema मध्ये बदल केलेला नसेल, तर rollback एका ओळीचा असतो: compose file मध्ये जुना tag पुन्हा ठेवा आणि docker compose up -d चालवा. Container बदलला जातो, volumes त्यांच्या ठिकाणीच राहतात आणि जुन्या code ला त्याने लिहिलेला data वाचता येतो.
नवीन आवृत्तीने schema migrate केला असेल, तर जुना code तो वाचू शकत नाही. Migrations पुढील दिशेने चालण्यासाठी लिहिलेल्या असतात आणि बहुतेक projects कोणतीही downgrade script release करत नाहीत. त्यामुळे जुनी आवृत्ती सुरू होते आणि rename किंवा drop केलेल्या column वरच्या पहिल्याच query वेळी ERROR: column "avatar_url" does not exist स्वरूपाच्या errors मुळे अयशस्वी होते. परत जाण्याचा मार्ग म्हणजे pull करण्यापूर्वी घेतलेला dump: जुना tag पुन्हा ठेवा, database volume बाजूला काढा, तो रिकामा पुन्हा तयार करा, dump त्यात restore करा आणि सुरू करा. तो dump नसेल, तर परत जाण्याचा कोणताही मार्ग उरत नाही. म्हणूनच pull करण्यापूर्वी backup घेणे आवश्यक आहे.
Postgres major versions मध्ये ही समस्या सर्वाधिक गंभीर असते. Upgrade ऐवजी rollback वेळी failure दिसतो, त्यामुळे लोकांना आश्चर्य वाटते. प्रत्येक major release सोबत on-disk format बदलतो. postgres:16.4 बदलून postgres:17.2 करा, docker compose up -d चालवा आणि नवीन server सुरू होण्यास नकार देतो:
FATAL: database files are incompatible with server
DETAIL: The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17.2.Image तुमच्यासाठी pg_upgrade चालवत नाही. Compose stack मध्ये समर्थित पद्धत म्हणजे dump, replace, restore: जुनी आवृत्ती अद्याप सुरू असताना dump घ्या, docker compose down, database volume काढा, नवीन tag सेट करा, नवीन रिकाम्या data directory साठी docker compose create करा, database सुरू करा, dump restore करा आणि उर्वरित सेवा सुरू करा. नवीन major ने एक दिवस प्रत्यक्ष network traffic हाताळेपर्यंत जुना dump जतन ठेवा. एकाच major मधील minor upgrades, जसे 16.4 ते 16.9, यापैकी काहीही आवश्यक करत नाहीत, कारण त्यांच्यामध्ये format स्थिर असतो आणि container सरळ सुरू होतो.
VPS snapshots हा backup आहे का?
ते backup ला पूरक असतात, आणि दोन्ही वेगवेगळ्या प्रकारे अपयशी ठरतात. Snapshot hypervisor वर संपूर्ण disk ची प्रत तयार करतो. त्यामुळे तुम्ही backup मध्ये समाविष्ट करायला विसरलेले भागही येतात आणि संपूर्ण machine काही मिनिटांत पूर्ववत करता येते. त्यामुळे एका विशिष्ट कामासाठी हे योग्य साधन आहे: upgrade मुळे server बिघडला आणि तो वीस मिनिटांपूर्वी जसा होता तसा परत हवा.
इतर सर्व कामांसाठी हे साधन मर्यादित आहे. याची granularity संपूर्ण machine इतकी असते. त्यामुळे एखादा deleted table परत मिळवण्यासाठी संपूर्ण server कुठेतरी restore करून त्यातून तो table शोधावा लागतो. Retention कालावधी सहसा कमी असतो. Copies सामान्यतः server ज्या provider account मध्ये असतो त्याच account मध्ये राहतात. त्यामुळे account गमावल्यास server आणि त्याचे snapshots दोन्ही एकाच वेळी गमावले जातात. तसेच चालू machine चा snapshot घेतल्यास database मधील write प्रक्रियेच्या मध्यावस्थेची प्रत नोंदवली जाते. त्यामुळे database पहिल्यांदा सुरू होताना crash recovery करते आणि त्या वेळी सुरू असलेला कोणताही transaction गमावला जातो.
दोन्ही वापरा. Snapshot म्हणजे upgrade window साठीचे undo button आहे. Dump म्हणजे deleted account नंतरही उपलब्ध राहणारी प्रत आहे. snapshots आणि backups मधील फरक प्रत्येक साधन नेमक्या कोणत्या अपयशांपासून संरक्षण देते हे स्पष्ट करते. हाच backup directory stack नवीन VPS वर हलवणे हे आठवणीवरून पुन्हा उभारणी करण्याऐवजी नियमित काम बनवते.
काय बिघडते आणि तुम्हाला काय दिसेल
down वरील volumes flag. docker compose down -v फाइलमध्ये घोषित केलेले named volumes काढून टाकते आणि Compose Volume myapp_db_data Removed अशी ओळ दाखवून याची पुष्टी करते. हे पूर्ववत करता येत नाही. साधे docker compose down volumes तसेच ठेवते. docker compose down --volumes हा long form वापरा, जेणेकरून destructive flag पूर्ण शब्द म्हणून लिहावा लागेल.
magic string नसलेला dump. pg_restore: error: did not find magic string in file header याचा अर्थ फाइल archive नाही. नेहमीचे कारण म्हणजे docker compose exec वर -T नसणे. TTY जोडलेला असल्यास stream shell कडे जाताना रूपांतरित होतो आणि binary dump खराब होतो. -T वापरून dump पुन्हा घ्या आणि head -c 5 वापरून पहिल्या पाच bytes तपासा.
बदलता न येणारा password. Restore नंतर FATAL: password authentication failed for user "appuser" दिसत असल्यास .env आणि data directory वेगवेगळ्या वेळेचे आहेत. Image हा password फक्त रिक्त data directory तयार करताना सेट करते. त्यामुळे नंतर .env संपादित केल्याने database मध्ये कोणताही बदल होत नाही. जुळणारा .env restore करा किंवा ALTER USER वापरून database मध्ये password बदला.
दुसरा, रिक्त volume. Docker मागणीनुसार volume तयार करते. त्यामुळे s नसताना docker run -v myapp_upload:/data चालवल्यास नवीन रिक्त volume मध्ये डेटा लिहिला जातो आणि यशस्वी झाल्याचे दाखवले जाते. त्यानंतर docker volume ls दोन्ही नावे दाखवते; त्यापैकी एका volume मध्ये काहीही नसते. नावे आठवणीने टाइप करण्याऐवजी docker volume ls मधून volume names कॉपी करा.
production कडे केलेला restore. /srv/myapp-restore ऐवजी /srv/myapp मध्ये restore commands चालवल्यास backup वापरून live data overwrite होतो. दोन्ही ठिकाणी commands सारखेच दिसतात. प्रत्येक restore command आधी pwd तपासा आणि drill स्वतःच्या directory मध्ये ठेवा.
FAQ
docker compose down माझा डेटा हटवते का?
नाही. docker compose down containers आणि default network हटवते, पण named volumes आणि bind mounts मध्ये बदल करत नाही. docker compose down -v तुमच्या file मध्ये घोषित केलेले named volumes हटवते आणि ही कृती कायमस्वरूपी असते. Bind mounts हे host directories असल्यामुळे Compose ते कधीही हटवत नाही. Backup घेताना सेवा थांबवायच्या असतील आणि इतर सर्व गोष्टी तशाच ठेवायच्या असतील, तर त्याऐवजी docker compose stop वापरा.
pg_dump चालवण्याऐवजी Postgres data directory ची प्रत काढू शकतो का?
फक्त container थांबवलेला असताना. Server चालू असताना त्यातील files बदलत राहतात. त्यामुळे तयार झालेल्या copy मध्ये वेगवेगळ्या क्षणांतील स्थिती मिसळलेली असू शकते आणि ती पुन्हा वापरता येत नाही. File-level copy ही एका Postgres major version शीही बांधलेली असते. त्यामुळे ती वेगळ्या major version अंतर्गत सुरू होणार नाही. Container थांबवा, volume चे archive तयार करा, तो पुन्हा सुरू करा आणि या पद्धतीला जलद rebuild path समजा; एकमेव backup म्हणून तिच्यावर अवलंबून राहू नका. Dump ही portable copy आहे आणि restore करण्यासाठी तीच वापरली जाते.
Compose मध्ये Postgres ला नवीन major version वर कसे upgrade करावे?
Tag बदलणे पुरेसे नाही. नवीन server जुन्या data directory वर सुरू होण्यास नकार देतो आणि The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17.2 log करतो. जुनी version अजून चालू असताना pg_dump चालवा. त्यानंतर docker compose down चालवा, database volume हटवा, नवीन tag सेट करा, नवीन रिकाम्या volume साठी docker compose create चालवा, database सुरू करा आणि dump त्यात restore करा. नवीन version ने प्रत्यक्ष network traffic हाताळेपर्यंत जुना dump जतन करून ठेवा.
Backup किती वेळाने घ्यावे आणि ते किती काळ जतन करावे?
तुम्ही पुन्हा करायला तयार असलेल्या कामाच्या प्रमाणानुसार interval ठरवा. Personal किंवा small-team stack साठी nightly backup योग्य आहे. प्रत्येक upgrade च्या लगेच आधी एक अतिरिक्त manual backup घ्या. Retention साठी, लगेच लक्षात न आलेल्या नुकसानीचा समावेश होईल इतका इतिहास जतन करा. उदाहरणार्थ, Friday ला आढळलेल्या corrupted table साठी Thursday night ची copy उपयोगी ठरणार नाही. restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune हे सुरुवातीसाठी योग्य धोरण आहे. Schedule कोणतेही असो, प्रत्येक तिमाहीत एकदा त्यातून restore करा. हे करून पाहेपर्यंत तुमच्याकडे backups नसतात; फक्त files असतात.
Backup घेण्यासाठी संपूर्ण stack थांबवावी लागते का?
सहसा नाही. Server चालू असतानाही database dump consistent असतो, त्यामुळे database साठी downtime आवश्यक नाही. खरा प्रश्न volumes बाबत असतो. App फक्त files जोडत असेल, उदाहरणार्थ uploads directory मध्ये, तर live archive पुरेसे सुरक्षित असते. App files जागेवरच पुन्हा लिहित असेल, तर copy घेईपर्यंत ती एक service docker compose stop app ने थांबवा आणि त्यानंतर पुन्हा सुरू करा. Database चालू ठेवून app थांबवणे हा सहसा उपलब्ध करून देता येणारा सर्वात कमी कालावधीचा सुरक्षित पर्याय असतो.