SSD Nodes Learn 🎉 VPS $5.50/மாதம் முதல்

Docker Compose stack-ஐ பாதுகாப்பாக பேக்கப் செய்வது எப்படி?

Docker Compose stack-ஐ அப்டேட் செய்வதற்கு முன் கவனிக்க வேண்டியவை. Database dump, volumes மற்றும் configuration கோப்புகளை எவ்வாறு முறையாக பேக்கப் எடுப்பது என்பதற்கான முழுமையான வழிகாட்டி.

Docker Compose stack backup-ல் என்னென்ன இருக்க வேண்டும்

ஒரு Docker Compose stack backup-ல் நான்கு தனித்தனி விஷயங்கள் இருக்க வேண்டும். இதில் எதை இழந்தாலும் application-ஐ மீண்டும் கொண்டு வர முடியாது: compose file, அதன் அருகில் உள்ள .env, ஒவ்வொரு volume-ன் உள்ளடக்கங்கள், மற்றும் database-ன் சொந்த client மூலம் எடுக்கப்பட்ட database dump. container இயங்கிக்கொண்டிருக்கும்போது database-ன் கோப்புகளை நகலெடுப்பது backup ஆகாது. Upgrades-க்கு இதே பட்டியலைப் பயன்படுத்த வேண்டும், ஆனால் ஒரு கூடுதல் விதி உள்ளது: pull செய்வதற்கு முன்பே backup எடுக்கவும். ஏனெனில், schema migrations முன்னோக்கிச் செல்லும் வகையில் எழுதப்படுகின்றன, பெரும்பாலான திட்டங்களில் பின்னோக்கிச் செல்வதற்கான வழிமுறை இருப்பதில்லை.

கீழே உள்ள அனைத்தும் stack ஏற்கனவே deploy செய்யப்பட்டு, docker compose ps மூலம் அது இயங்குவதை உறுதிப்படுத்தியதாகக் கொள்கிறது. உதாரணங்கள் /srv/myapp-ல் உள்ள project directory-ஐயும், app மற்றும் db எனப் பெயரிடப்பட்ட services-ஐயும் பயன்படுத்துகின்றன. உங்கள் சொந்தப் பெயர்களைப் பயன்படுத்தவும். கட்டளைகள் பொதுவானதாகவே வைக்கப்பட்டுள்ளன, ஏனெனில் முக்கியமான பகுதிகளான volumes மற்றும் database ஆகியவை எந்த application-ஆக இருந்தாலும் ஒரே மாதிரியாகவே செயல்படும்.

உங்கள் stack உண்மையில் எதைச் சேமிக்கிறது என்பதைக் கண்டறியவும்

cd /srv/myapp
docker compose ps
docker compose config --volumes
docker volume ls --filter label=com.docker.compose.project=myapp

docker compose config --volumes உங்கள் கோப்பில் அறிவிக்கப்பட்டுள்ள named volumes-ன் சுருக்கமான பெயர்களை அச்சிடுகிறது. docker volume ls அந்த volumes வட்டில் (disk) உண்மையில் கொண்டுள்ள பெயர்களை அச்சிடுகிறது. இந்த இரண்டு பட்டியல்களும் மாறுபடும், ஏனெனில் Compose project பெயரை முன்னொட்டாகச் சேர்க்கிறது: கோப்பில் db_data என்று எழுதப்பட்ட ஒரு volume, வட்டில் myapp_db_data என்ற பெயரில் இருக்கும். Project பெயர் இயல்பாகவே directory பெயராக இருக்கும், எனவே directory-ஐ மறுபெயரிடுவது, அந்த stack-ஐ புதிய காலி volumes-க்குச் சுட்டிக்காட்டும் மற்றும் பழைய volumes-ஐ உங்கள் தரவுகளுடன் அப்படியே விட்டுவிடும். கீழே உள்ள ஒவ்வொரு கட்டளைக்கும் docker volume ls-லிருந்து கிடைக்கும் உண்மையான பெயர் தேவை.

Bind mounts இந்த இரண்டு பட்டியல்களிலும் இடம்பெறாது. Compose கோப்பில், இவை colon-க்கு இடதுபுறம் host path-ஐக் கொண்ட பதிவுகளாகும், ./config:/app/config. இவை host-ல் உள்ள சாதாரண directory-கள் என்பதால், சாதாரண கருவிகள் மூலம் இவற்றை அணுகலாம். Named volumes /var/lib/docker/volumes/-க்கு கீழ் இருக்கும், மேலும் docker volume inspect --format '{{.Mountpoint}}' myapp_db_data அவற்றின் சரியான பாதையை அச்சிடும். உங்கள் stack எந்த வகையைப் பயன்படுத்துகிறது என்பது நீங்கள் அதை எவ்வாறு நகலெடுக்கிறீர்கள் என்பதை மாற்றும், மேலும் bind mounts against named volumes இதற்கான சாதக பாதகங்களை முழுமையாக விளக்குகிறது.

இப்போது நீங்கள் கண்டறிந்தவற்றை இரண்டு குழுக்களாகப் பிரிக்கவும். சில volumes எவராலும் மீண்டும் உருவாக்க முடியாத நிலையை (state) வைத்திருக்கும்: பதிவேற்றப்பட்ட கோப்புகள், உருவாக்கப்பட்ட keys, database மற்றும் பயனர் பயன்பாட்டில் உள்ளிட்டவை. மற்றவை thumbnails மற்றும் search indexes போன்ற பெறப்பட்ட தரவுகளை (derived data) வைத்திருக்கும், இவற்றை application தானாகவே மீண்டும் உருவாக்கிக்கொள்ளும். இரண்டாவது குழுவை backup செய்வது disk இடத்தையும், மீட்பு நேரத்தையும் வீணாக்குமே தவிர எந்தப் பயனும் தராது. Redis cache volume இதற்கு மிகத்தெளிவான உதாரணம்: அதை இழப்பதால் ஒரு மெதுவான முதல் கோரிக்கை (request) மட்டுமே ஏற்படும்.

compose file மற்றும் .env file-ஐ காப்புப்பிரதி (backup) எடுத்தல்

இந்த இரண்டு கோப்புகளும் host-ல் அருகருகே உள்ளன, இவை எந்த volume-க்குள்ளும் இல்லை. .env-ல் database password, application secret மற்றும் API tokens ஆகியவை உள்ளன; எனவே, சிதறிக்கிடக்கும் volumes-ஐ மீண்டும் ஒரு முழுமையான செயலியாக மாற்றும் முக்கிய கோப்பு இதுவே. இது பொதுவாக .gitignore-ல் சேர்க்கப்படுவதில்லை; எனவே, "எனது configuration அனைத்தும் git-ல் உள்ளது" என்று நீங்கள் நினைத்தால், மிக முக்கியமான இந்த ஒரு கோப்பு விடுபட்டுவிடும். env file-ல் ரகசியங்களை வைத்திருப்பது சரியான முறையாகும், ஆனால் இது உங்கள் காப்புப்பிரதி திட்டத்தில் கூடுதல் பொறுப்பை உருவாக்குகிறது.

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/.env

stack-ல் பயன்படுத்தப்படும் அனைத்து compose file-களையும் நகலெடுக்கவும், முதல் கோப்பை மட்டும் எடுக்க வேண்டாம். -f compose.yaml -f compose.prod.yaml மூலம் தொடங்கப்பட்ட stack மீண்டும் அதே முறையில் இயங்க இரண்டு கோப்புகளும் தேவை. பல compose file-கள் எவ்வாறு இணைகின்றன என்பது எந்த மதிப்புகள் container-ஐச் சென்றடையும் என்பதைத் தீர்மானிக்கிறது.

ஒரு எச்சரிக்கை: .env-ஐ volumes-உடன் இணைக்க வேண்டும். அதிகாரப்பூர்வமான Postgres image, ஒரு காலி data directory-ஐ உருவாக்கும்போது மட்டுமே POSTGRES_PASSWORD-ஐ வாசிக்கும். அந்த மதிப்பை பிற்காலத்தில் மாற்றினால், database-க்குள் இருக்கும் password மாறாது. கடந்த மாதத்தின் volume-ஐ இன்றைய .env-உடன் சேர்த்து restore செய்தால், இரண்டு கோப்புகளும் சரியாகத் தெரிந்தாலும், FATAL: password authentication failed for user "appuser" பிழையுடன் செயலி இணைக்கத் தவறிவிடும். எனவே, .env மற்றும் volumes ஆகியவற்றை ஒரே காலகட்டத்தைச் சேர்ந்தவையாக, ஒன்றாகவே காப்புப்பிரதி எடுக்கவும்.

அதன் சொந்த client-ஐப் பயன்படுத்தி database-ஐ dump செய்தல்

Database server தொடர்ந்து அதன் கோப்புகளில் எழுதிக்கொண்டே இருக்கும். Server இயங்கிக்கொண்டிருக்கும்போது எடுக்கப்படும் ஒரு tar, /var/lib/postgresql/data-ன் சில பக்கங்களை எழுதும் முன்பும், சில பக்கங்களை எழுதிய பின்பும் நகலெடுக்கும். இதனால், அந்த archive-ல் முரண்பட்ட காலக்கட்டங்களின் தரவுகள் கலந்திருக்கும், அவற்றை மீண்டும் இயக்க முடியாது. ஒரு dump கருவி ஒரே transaction-க்குள் தரவுகளை வாசிப்பதால், அந்த கோப்பு ஒரு சீரான காலக்கட்டத்தின் தரவுகளைக் கொண்டிருக்கும். இந்த வேறுபாடே ஒரு 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-ஐ விரிவுபடுத்துவதிலிருந்து தடுக்கின்றன. இதனால், compose கோப்பில் ஏற்கனவே அமைக்கப்பட்டுள்ள மதிப்புகளைப் பயன்படுத்தி, container-க்குள் இருக்கும் shell அதை விரிவுபடுத்துகிறது. -Fc தனிப்பயன் வடிவத்தில் (custom format) எழுதுகிறது, இது தரவுகளைச் சுருக்கி (compress) சேமிப்பதோடு, பிற்காலத்தில் pg_restore மூலம் குறிப்பிட்ட பொருட்களை மட்டும் பிரித்தெடுக்க அனுமதிக்கிறது.

Roles மற்றும் அவற்றின் கடவுச்சொற்கள் எந்தவொரு தனிப்பட்ட database-க்குள்ளும் இருப்பதில்லை, எனவே அவற்றையும் சேர்த்து எடுத்துக்கொள்ளுங்கள்:

docker compose exec -T db sh -c 'pg_dumpall -U "$POSTGRES_USER" --globals-only' \
  > /srv/backups/myapp/globals.sql

பின்பு, அந்த கோப்பு ஒரு dump தானா அல்லது பிழைச் செய்தியா என்பதைச் சரிபார்க்கவும்:

ls -lh /srv/backups/myapp/
head -c 5 /srv/backups/myapp/db-$(date +%F).dump

தனிப்பயன் வடிவ dump கோப்பு PGDMP என்ற ஐந்து bytes-உடன் தொடங்கும். பூஜ்ஜியம் bytes கொண்ட கோப்பு அல்லது pg_dump:-உடன் தொடங்கும் கோப்பு, கட்டளை தோல்வியடைந்ததைக் குறிக்கிறது. கட்டளை இயங்குவதற்கு முன்பே shell வெளியீட்டு கோப்பை உருவாக்கிவிடுவதால், தோல்வியடைந்த dump-ம் சரியான பெயர் மற்றும் நேரத்துடன் ஒரு கோப்பை விட்டுச் செல்லும். இதுவே அமைதியாக நடக்கும் மிகவும் பொதுவான backup தோல்வியாகும்.

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, InnoDB அட்டவணைகளைத் தடுக்காமல் (blocking) சீரான dump-ஐ வழங்குகிறது. MySQL image-ல் இந்த கட்டளை mysqldump ஆகும், மேலும் மாறிகள் (variables) MYSQL_ROOT_PASSWORD மற்றும் MYSQL_DATABASE ஆகும். தற்போதைய MariaDB image-களில் mariadb-dump-க்கான இணக்கத்தன்மை பெயராக mysqldump இன்னும் செயல்படுகிறது. கட்டளை வரியில் (command line) கொடுக்கப்படும் கடவுச்சொல், dump இயங்கும் வரை container-ன் process பட்டியலில் தெரியும் என்பதை நினைவில் கொள்க.

SQLite-க்கு கூடுதல் கவனம் தேவை. Database ஒரே கோப்பாக இருந்தாலும், சமீபத்திய பரிவர்த்தனைகள் (transactions) அதற்கு அருகிலுள்ள ஒரு தனி -wal கோப்பில் இருக்கலாம். எனவே, .db-ஐ மட்டும் நகலெடுப்பது சமீபத்திய தரவுகள் இல்லாத database-ஐத் தரும். image-ல் client இருந்தால், sqlite3 /data/app.db ".backup '/data/app-backup.db'" பயன்பாட்டில் இருக்கும்போதே சீரான நகலை உருவாக்கும். இல்லையெனில், container-ஐ நிறுத்திவிட்டு, .db கோப்பை அதன் -wal மற்றும் -shm துணைக்கோப்புகளுடன் சேர்த்து நகலெடுக்கவும்.

உங்கள் database stack-க்குள் இல்லாமல் host-ல் இயங்கினால், docker compose exec முன்னொட்டு (prefix) இல்லாமல் இதே கட்டளைகளைப் பயன்படுத்தலாம். உங்கள் அடுத்த rebuild-க்கு முன் database-ஐ Docker-ல் அல்லது host-ல் இயக்குவது குறித்த கட்டுரையை வாசிப்பது பயனுள்ளதாக இருக்கும்.

Volumes-ஐப் பாதுகாத்தல்

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 பக்கத்தில் உருவாக்குகிறது. --rm கட்டளை, tar முடிந்தவுடன் helper container-ஐ நீக்கிவிடும். :ro முக்கியமானது, ஏனெனில் தவறான tar கட்டளை source-ஐப் பாதிக்காமல் தடுக்க இது உதவுகிறது. -C /data . தான் restore சரியாக நடப்பதை உறுதி செய்கிறது: இது ஒவ்வொரு path-ஐயும் volume root-க்கு சார்பாகச் சேமிக்கிறது. இதற்குப் பதிலாக tar czf /backup/uploads.tar.gz /data என்று எழுதினால், ஒவ்வொரு path-லும் ஒரு data/ முன்னொட்டாகச் சேர்ந்துவிடும். இதனால் restore செய்யும்போது volume-க்குள் /data/data என்ற directory உருவாகும், app-க்கு அது காலியாகவே தெரியும். Container-க்குள் tar root பயனர் மூலம் இயங்குவதால், அந்த archive-ன் உரிமையாளர் root ஆக இருப்பார். இது உங்களுக்கு இடையூறாக இருந்தால் sudo chown "$USER" /srv/backups/myapp/uploads.tar.gz கட்டளையை இயக்கவும். restored கோப்புகளை app-ஆல் படிக்க முடியவில்லை என்றால், PUID மற்றும் PGID கோப்பு உரிமையை எவ்வாறு தீர்மானிக்கின்றன என்பதைப் படிக்கவும்.

ஒவ்வொரு named volume-க்கும் இதை ஒருமுறை இயக்கவும். Bind mounts-க்கு container தேவையில்லை: tar czf /srv/backups/myapp/config.tar.gz -C /srv/myapp/config . கட்டளையே host-ல் அதே வேலையைச் செய்யும்.

App-ஐ நிறுத்த வேண்டுமா என்பதை ஒவ்வொரு volume-க்கும் ஏற்ப முடிவு செய்யவும். App தொடர்ந்து எழுதும் ஒரு volume-ஐ live tar எடுக்கும்போது, கோப்பு பாதியில் இருக்கும்போதே நகலெடுக்கப்படலாம். கோப்புகள் ஒருமுறை எழுதப்பட்டு பின் படிக்க மட்டுமே பயன்படும் uploads directory-க்கு இந்த ஆபத்து குறைவு. மற்றவற்றுக்கு, நகலெடுக்கும் நேரம் வரை docker compose stop app மூலம் அந்த service-ஐ நிறுத்திவிட்டு, பின் docker compose start app செய்யவும். stop கட்டளை container-களையும் volume-களையும் அப்படியே வைத்திருக்கும், இதுவே நமக்குத் தேவை. down மற்றும் stop ஆகியவற்றுக்கு இடையேயான வேறுபாடு என்ன என்பதைத் தட்டச்சு செய்வதற்கு முன்பே உறுதிப்படுத்திக் கொள்வது நல்லது.

Database volume-ன் tar-ஐ உங்கள் database backup-ஆகக் கருத வேண்டாம். Dump எடுப்பதே முறையான backup ஆகும். நிறுத்தப்பட்ட database-ன் volume archive என்பது விரைவான rebuild-க்கு மட்டுமே உதவும், அதைத் தாண்டி எதற்கும் பயன்படாது.

செயல்பாடுகளின் வரிசைமுறை

  1. Compose கோப்புகளையும் .env-ஐயும் backup கோப்பகத்திற்கு நகலெடுக்கவும்.
  2. Database இயங்கிக்கொண்டிருக்கும்போதே அதன் தரவுகளை dump செய்யவும்.
  3. Volumes-ல் மாற்றம் ஏற்பட்டால், app container-ஐ நிறுத்தவும்.
  4. ஒவ்வொரு named volume மற்றும் bind-mount கோப்பகத்தையும் archive செய்யவும்.
  5. நிறுத்திய அனைத்தையும் மீண்டும் தொடங்கி, docker compose ps மூலம் உறுதிப்படுத்தவும்.
  6. stack-ல் இயங்கும் image tags மற்றும் digests-ஐ குறித்து வைத்துக்கொள்ளவும்.
  7. முழு backup கோப்பகத்தையும் இந்த server-லிருந்து வெளியே நகலெடுக்கவும்.

படி 7-ஐத்தான் பலரும் பிறகு பார்த்துக்கொள்ளலாம் என்று விட்டுவிடுகிறார்கள்.

சேவையகத்திலிருந்து நகலை வெளியேற்றுதல்

நீங்கள் பயன்படுத்தும் அதே வட்டில் (disk) சேமிக்கப்படும் backup, உங்கள் சொந்தத் தவறுகளிலிருந்து மட்டுமே பாதுகாக்கும். வட்டு பழுதடைந்தாலோ, server நீக்கப்பட்டாலோ அல்லது கணக்கு முடக்கப்பட்டாலோ, இரண்டு நகல்களும் ஒரே நேரத்தில் அழிந்துவிடும். எனவே, இந்த VPS-ல் இல்லாத வேறொரு சேமிப்பகத்திற்கு, ஒரு குறிப்பிட்ட கால அட்டவணையின்படி மற்றும் retention policy-யுடன் கோப்புகளை அனுப்ப வேண்டும். VPS-லிருந்து restic backups என்ற பகுதியில் repository அமைப்பு, retention flags மற்றும் check command ஆகியவை விளக்கப்பட்டுள்ளன, எனவே அவற்றை இங்கே மீண்டும் குறிப்பிடத் தேவையில்லை.

restic கருவியானது dump-ஐ நேரடியாக ஒரு pipe மூலமாகவும் படிக்க முடியும். இது plaintext database-ஐ வட்டில் சேமிக்காமல் தவிர்க்க உதவுகிறது:

docker compose exec -T db sh -c 'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' \
  | restic backup --stdin --stdin-filename db.dump

நீங்கள் எந்தக் கருவியைப் பயன்படுத்தினாலும், அதன் கால அட்டவணையை systemd timer அல்லது cron job-ல் அமைக்கவும். அந்தப் பணி தோல்வியுற்றால், நீங்கள் அறியும் வகையில் அறிவிப்பு வரும்படி செய்யவும். வெளியீடு எங்கும் சேமிக்கப்படாத ஒரு backup script, ஆறு மாதங்கள் வேலை செய்யாமல் இருந்தாலும் யாரும் கவனிக்க முடியாத நிலையை உருவாக்கும்.

Restore drill மூலம் backup சரியாகச் செயல்படுவதை உறுதிப்படுத்துதல்

நீங்கள் ஒருமுறை கூட restore செய்து பார்க்காத backup என்பது வெறும் அனுமானம் மட்டுமே. கீழே கொடுக்கப்பட்டுள்ள drill, ஏற்கனவே இயங்கிக்கொண்டிருக்கும் stack-க்கு இணையாக இரண்டாவது stack-ஐ உருவாக்கி அதில் restore செய்கிறது. இதனால் production service பாதிக்கப்படாது, நீங்கள் செய்யும் எந்த மாற்றமும் production-ஐச் சென்றடையாது.

இதற்கான முக்கிய அம்சம் project name ஆகும். Compose, directory பெயரிலிருந்து project name-ஐ எடுத்து, தான் உருவாக்கும் ஒவ்வொரு container மற்றும் volume-உடன் அதை இணைக்கும். எனவே, backup-ஐ ஒரு புதிய directory-க்கு நகலெடுத்தால், restored 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-ஐத் திருத்தி, host port மோதல் ஏற்படாமல் பார்த்துக்கொள்ளவும். 18080:8080-க்கு பதிலாக 8080:8080-ஐப் பயன்படுத்தவும் அல்லது அந்த port-ஐக் குறிக்கும் variable-ஐ நகலெடுக்கப்பட்ட .env-ல் மாற்றவும். பின், எதையும் தொடங்காமல் container-களையும் அவற்றின் காலியான volume-களையும் உருவாக்கவும்:

docker compose create
docker volume ls --filter label=com.docker.compose.project=myapp-restore

இரண்டாவது கட்டளை, production-ல் உள்ள அதே volume பெயர்களை myapp-restore_ முன்னொட்டுடன் காட்ட வேண்டும். அவற்றை நிரப்பி, database-ஐ மட்டும் தனியாகத் தொடங்கி, dump-ஐ ஏற்றவும்:

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-ஐயும் நீக்கிவிட்டு மீண்டும் உருவாக்குவதால், இந்த restore செயல்முறையை மீண்டும் மீண்டும் செய்ய முடியும். இது இல்லையெனில், ஏற்கனவே தரவுகள் உள்ள database-ல் மீண்டும் restore செய்ய முயலும்போது 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=50

docker compose up -d --wait அனைத்து service-களும் இயங்கும் அல்லது healthy நிலையில் இருக்கும் வரை காத்திருக்கும். ஏதேனும் ஒன்று தோல்வியடைந்தால், இது non-zero exit code-ஐத் தரும், இதுவே இந்த நிலையை script செய்ய உதவுகிறது. ஒரு service healthy நிலையை அடையவில்லை என்றால், docker compose ps அதன் நிலையைத் தெளிவாகக் காட்டும். Compose healthchecks அந்த column எதைக் குறிக்கிறது என்பதை விளக்குகிறது. பின், மாற்று port-ல் app-ஐத் திறந்து, உண்மையான account மூலம் login செய்யவும். ஒரு பதிவை எழுதி, volume-ல் உள்ள ஒரு கோப்பைத் திறக்கவும். இந்த இரண்டு செயல்களும் dump மற்றும் volume ஆகிய இரண்டும் சரியாக restore செய்யப்பட்டுள்ளதையும், அவை ஒன்றுடன் ஒன்று ஒத்துப்போவதையும் உறுதிப்படுத்தும். login பக்கம் மட்டும் சரியாகத் தெரிகிறது என்பது உங்கள் தரவுகள் பாதுகாப்பாக உள்ளது என்பதற்கான சான்று அல்ல.

சோதனை முடிந்ததும் drill-ஐ நீக்கவும்:

docker compose down -v

இங்கே மட்டுமே -v flag-ஐப் பயன்படுத்துவது சரியானது. Production directory-ல் இதே கட்டளையைப் பயன்படுத்தினால், நீங்கள் பாதுகாக்க நினைக்கும் volumes நீக்கப்பட்டுவிடும்.

Compose stack-ஐ upgrade செய்வது எப்படி

நீங்கள் தற்போது பயன்படுத்தும் பதிப்பிற்கும், நீங்கள் மாற்ற விரும்பும் பதிப்பிற்கும் இடைப்பட்ட அனைத்து பதிப்புகளின் release notes-ஐயும் வாசிக்கவும். அதில் breaking மற்றும் migration ஆகிய சொற்களைத் தேடவும். பல major பதிப்புகளைத் தாண்டி நேரடியாக upgrade செய்வதை ஆதரிக்காத திட்டங்கள், அதைத் தெளிவாகக் குறிப்பிட்டிருக்கும். ஒரு migration தோல்வியடைந்தால், அது ஏற்கனவே schema-வின் ஒரு பகுதியை மாற்றிய பிறகுதான் உங்களுக்குத் தெரிவிக்கும்.

எந்த மாற்றத்தையும் செய்வதற்கு முன், தற்போது நீங்கள் எதை இயக்குகிறீர்கள் என்பதைப் பதிவு செய்யவும்:

docker compose images
docker image inspect --format '{{index .RepoDigests 0}}' postgres:16.4

docker compose images, ஒவ்வொரு service-ம் தற்போது பயன்படுத்தும் image மற்றும் tag-ஐப் பட்டியலிடுகிறது. ஒரு tag எந்த நேரத்திலும் வேறொரு இடத்திற்கு மாற்றப்படலாம் என்பதால், image-ஐத் துல்லியமாகக் குறிக்கும் ஒரே மதிப்பு digest மட்டுமே.

மேலே உள்ள பிரிவுகளில் உள்ள backup-ஐ எடுத்து, அதை server-க்கு வெளியே நகலெடுக்கவும். patch release-களுக்கும் இதையே செய்யவும். மக்கள் எப்போது தயாரிப்பை நிறுத்துகிறார்களோ, அப்போதுதான் upgrade-கள் சிக்கலாகின்றன.

பிறகு, compose file-ல் பதிப்பைப் பூட்டவும் (pin), ஏனெனில் latest என்பது ஒரு பதிப்பு அல்ல:

services:
  db:
    image: postgres:16.4

image: postgres:latest பயன்படுத்தும்போது, docker compose pull அந்த tag இன்று எதைக் குறிக்கிறதோ அதை மட்டுமே பதிவிறக்கும். நேற்று நீங்கள் எதை இயக்கினீர்கள் என்பதை அறிய வழி இருக்காது. ஒரு குறிப்பிட்ட tag-ஐப் பூட்டுவது, upgrade-ஐ ஒரே வரியில் மாற்றக்கூடியதாக மாற்றுகிறது. இதை நீங்கள் git diff மூலம் சரிபார்க்கலாம், மேலும் ஒரு திருத்தம் மூலம் பழைய நிலைக்குத் திரும்பலாம். திட்டத்தின் release பக்கத்திலிருந்து சரியான பதிப்பை எடுத்து, application image-ஐயும் இதேபோல் பூட்டவும்.

Pull செய்து மீண்டும் உருவாக்கவும்:

docker compose pull
docker compose up -d --wait

docker compose up -d, கோப்பையும் தற்போது இயங்கும் container-களையும் ஒப்பிட்டு, image அல்லது configuration மாறிய service-களை மட்டும் மீண்டும் உருவாக்கும். இது named volumes-ஐப் பாதிக்காது, எனவே புதிய container ஏற்கனவே உள்ள தரவுகளுடன் தொடங்கும். இதுவே இந்தச் செயல்பாட்டின் நோக்கம், அதே சமயம் இதுவே ஆபத்தும் கூட; ஏனெனில் புதிய பதிப்பின் முதல் தொடக்கத்தில்தான் பொதுவாக அதன் schema migration நடக்கும்.

அது நடப்பதைக் கவனிக்கவும்:

docker compose ps
docker compose logs -f --tail=100 app

தோல்வியடைந்த container, docker compose ps-ன் STATUS column-ல் Exited (1) என்று காட்டும். அதன் log-ன் கடைசி வரிகளில் அதற்கான காரணம் இருக்கும். Migration பிழைகள் அங்கே தெளிவாகத் தெரியும், மற்ற இடங்களில் அவை தெரியாது. Logs சீரான பிறகு, உள்ளே நுழைந்து ஒரு நிமிடம் app-ஐப் பயன்படுத்தவும்.

docker compose pull, no space left on device பிழையுடன் நின்றால், பழைய image layers-தான் பொதுவாகக் காரணமாக இருக்கும். பயன்படுத்தப்படாத Docker image-களை நீக்குதல் மூலம் இடத்தைச் சேமிக்கலாம். Upgrade வெற்றிகரமாக முடிந்த பிறகு நீக்குதலைச் செய்யவும்; அதற்கு முன் செய்ய வேண்டாம். ஏனெனில், விரைவாக rollback செய்ய அந்தப் பழைய layers தேவைப்படும்.

மேம்படுத்தல் தோல்வியடையும் போது எவ்வாறு பழைய நிலைக்குத் திரும்புவது (Roll back)

இதில் இரண்டு சூழல்கள் உள்ளன, ஒவ்வொன்றிற்கும் ஆகும் செலவு மற்றும் உழைப்பு மாறுபடும். புதிய பதிப்பு database schema-வை மாற்றவில்லை என்றால், பழைய நிலைக்குத் திரும்புவது எளிது: compose கோப்பில் பழைய tag-ஐ மீண்டும் இட்டு, docker compose up -d கட்டளையை இயக்கவும். container மாற்றப்படும், volumes அப்படியே இருக்கும், பழைய code தான் எழுதிய தரவுகளை மீண்டும் வாசிக்கும்.

புதிய பதிப்பு schema-வை மாற்றியிருந்தால், பழைய code-ஆல் அதை வாசிக்க முடியாது. Migrations முன்னோக்கிச் செல்லும் வகையில் மட்டுமே எழுதப்படுகின்றன; பெரும்பாலான திட்டங்களில் downgrade script வழங்கப்படுவதில்லை. எனவே, பழைய பதிப்பு தொடங்கினாலும், பெயர் மாற்றப்பட்ட அல்லது நீக்கப்பட்ட column-ஐ அணுகும் முதல் query-லேயே தோல்வியடையும். அப்போது ERROR: column "avatar_url" does not exist போன்ற பிழைகள் தோன்றும். இதற்கு ஒரே வழி, மேம்படுத்தலுக்கு முன் நீங்கள் எடுத்த database dump ஆகும்: பழைய tag-ஐ இட்டு, database volume-ஐ நீக்கி, அதை காலியாக உருவாக்கி, dump-ஐ restore செய்து, பின் தொடங்க வேண்டும். அந்த dump இல்லையென்றால் பழைய நிலைக்குத் திரும்ப வழியே இல்லை; இதனால்தான் மேம்படுத்தலுக்கு முன் backup எடுப்பது கட்டாயமானது.

Postgres major பதிப்பு மாற்றங்கள் இதில் மிகவும் சிக்கலானவை. இவை மேம்படுத்தலின் போதே தோல்வியடையாமல், rollback செய்யும் போதுதான் சிக்கலை ஏற்படுத்தும். ஒவ்வொரு 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-ஐ அமைக்கவும், docker compose create மூலம் புதிய காலி data directory-ஐ உருவாக்கவும், database-ஐத் தொடங்கி, dump-ஐ restore செய்யவும், பின் மற்ற சேவைகளைத் தொடங்கவும். புதிய major பதிப்பு ஒரு நாள் முழுவதும் முழுமையான traffic-ஐக் கையாளும் வரை பழைய dump-ஐ வைத்திருக்கவும். 16.4 முதல் 16.9 வரையிலான minor மேம்படுத்தல்களுக்கு இவை தேவையில்லை, ஏனெனில் அவற்றுக்கிடையே format மாறாது, container நேரடியாகத் தொடங்கும்.

VPS snapshots ஒரு backup-ஆ?

இவை backup-க்கு ஒரு துணை மட்டுமே; இவை இரண்டும் வெவ்வேறு சூழல்களில் தோல்வியடையக்கூடும். ஒரு snapshot என்பது hypervisor மட்டத்தில் முழு வட்டு (disk)-ஐயும் நகலெடுக்கும். எனவே, நீங்கள் backup செய்ய மறந்த கோப்புகள் உட்பட, முழு இயந்திரத்தையும் சில நிமிடங்களில் பழைய நிலைக்குக் கொண்டுவர இது உதவும். ஒரு குறிப்பிட்ட பணிக்கு இதுவே சரியான கருவி: ஒரு upgrade-ஆல் server பழுதடைந்துவிட்டால், 20 நிமிடங்களுக்கு முன்பு இருந்த நிலைக்கு அதை மீண்டும் கொண்டுவர இது பயன்படுகிறது.

மற்ற அனைத்து தேவைகளுக்கும் இது ஒரு பலவீனமான கருவியாகும். இதில் முழு இயந்திரமும் ஒரு அலகாகவே கையாளப்படுகிறது. எனவே, நீக்கப்பட்ட ஒரு database table-ஐ மீட்க வேண்டுமென்றால், முழு server-ஐயும் வேறொரு இடத்தில் restore செய்து, அதிலிருந்து அந்த table-ஐத் தேடி எடுக்க வேண்டும். இவற்றின் சேமிப்பு காலம் (retention) பொதுவாகக் குறைவாகவே இருக்கும். இந்த நகல்கள் பெரும்பாலும் server இருக்கும் அதே provider account-ல் சேமிக்கப்படும்; எனவே, உங்கள் account-ஐ நீங்கள் இழந்தால், server மற்றும் அதன் snapshots ஆகிய இரண்டையுமே இழக்க நேரிடும். மேலும், இயங்கிக்கொண்டிருக்கும் ஒரு இயந்திரத்தின் snapshot எடுக்கும்போது, database-ன் எழுதும் பணி பாதியில் இருக்கலாம். இதனால், மீண்டும் தொடங்கும் போது database crash recovery-க்கு உள்ளாகும், மேலும் அந்த நேரத்தில் நடந்துகொண்டிருந்த பரிவர்த்தனைகள் (transactions) அழிந்துவிடும்.

இவை இரண்டையும் பயன்படுத்துங்கள். ஒரு upgrade-ன் போது ஏற்படும் சிக்கல்களைச் சரிசெய்ய 'undo' பொத்தானாக snapshot-ஐப் பயன்படுத்துங்கள். account நீக்கப்பட்டாலும் அழியாமல் இருக்க, database dump-ஐப் பயன்படுத்துங்கள். snapshots மற்றும் backups-க்கு இடையிலான வேறுபாடுகள் எந்தெந்த தோல்விகளை இவை ஒவ்வொன்றும் எதிர்கொள்கின்றன என்பதை விளக்குகிறது. அதே backup directory-ஐப் பயன்படுத்தி, ஒரு stack-ஐ புதிய VPS-க்கு மாற்றுவது என்பது நினைவாற்றலை நம்பி மீண்டும் கட்டமைப்பதற்குப் பதிலாக, ஒரு வழக்கமான பணியாக மாற்றப்படுகிறது.

என்ன தவறாக நடக்கும், நீங்கள் எதைக் காண்பீர்கள்

down கட்டளையில் volumes flag. docker compose down -v என்பது கோப்பில் அறிவிக்கப்பட்ட பெயரிடப்பட்ட volumes-ஐ நீக்கிவிடும், மேலும் Volume myapp_db_data Removed என்ற வரியின் மூலம் Compose இதை உறுதிப்படுத்தும். இதைத் திரும்பப் பெற முடியாது. சாதாரண docker compose down கட்டளை அவற்றை அப்படியே விட்டுவிடும். எனவே, நீண்ட வடிவமான docker compose down --volumes என்பதைப் பயன்படுத்தவும், அப்போதுதான் அழிக்கும் தன்மையுள்ள அந்த 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-ஐச் சரிபார்க்கவும்.

மாறாத கடவுச்சொல். restore செய்த பிறகு FATAL: password authentication failed for user "appuser" என்பது, .env மற்றும் தரவு அடைவு (data directory) ஆகியவை வெவ்வேறு நேரங்களில் எடுக்கப்பட்டவை என்பதைக் குறிக்கிறது. ஒரு காலி தரவு அடைவை உருவாக்கும்போது மட்டுமே image அந்த கடவுச்சொல்லை அமைக்கும், எனவே பின்னர் .env-ஐத் திருத்துவது தரவுத்தளத்திற்குள் எதையும் மாற்றாது. பொருந்தக்கூடிய .env-ஐ restore செய்யவும், அல்லது ALTER USER மூலம் தரவுத்தளத்திற்குள் கடவுச்சொல்லை மாற்றவும்.

இரண்டாவது, காலியான volume. Docker தேவைப்படும்போது ஒரு volume-ஐ உருவாக்கும், எனவே s விடுபட்ட நிலையில் docker run -v myapp_upload:/data கட்டளையை இயக்கினால், அது புதிய காலியான volume-ல் எழுதி வெற்றிகரமாக முடிந்ததாகக் காட்டும். அப்போது docker volume ls இரண்டு பெயர்களையும் காட்டும், அதில் ஒன்று எதையும் கொண்டிருக்காது. நினைவிலிருந்து தட்டச்சு செய்வதற்குப் பதிலாக, docker volume ls-லிருந்து volume பெயர்களை நகலெடுக்கவும்.

தயாரிப்பு சூழலை (production) நோக்கிய restore. /srv/myapp-restore-க்கு பதிலாக /srv/myapp-ல் restore கட்டளைகளை இயக்குவது, நேரடித் தரவுகளை (live data) backup மூலம் மேலெழுதிவிடும் (overwrite), மேலும் இரண்டு இடங்களிலும் கட்டளைகள் ஒரே மாதிரியாகவே இருக்கும். ஒவ்வொரு restore கட்டளைக்கு முன்பும் pwd-ஐச் சரிபார்க்கவும், மேலும் பயிற்சி (drill) கோப்புகளை அதன் சொந்த அடைவிலேயே வைத்திருக்கவும்.

FAQ

docker compose down எனது தரவுகளை நீக்கிவிடுமா?

இல்லை. docker compose down என்பது containers மற்றும் default network-ஐ மட்டுமே நீக்கும்; named volumes மற்றும் bind mounts-ஐ அது பாதிக்காது. docker compose down -v என்பது உங்கள் கோப்பில் குறிப்பிடப்பட்டுள்ள named volumes-ஐ நீக்கும், இது நிரந்தரமானது. Bind mounts என்பவை host directories என்பதால், Compose அவற்றை ஒருபோதும் நீக்காது. மற்ற எதையும் மாற்றாமல், backup எடுக்கும்போது மட்டும் services-ஐ நிறுத்த விரும்பினால், அதற்குப் பதிலாக docker compose stop-ஐப் பயன்படுத்தவும்.

pg_dump-ஐ இயக்குவதற்குப் பதிலாக Postgres தரவு அடைவை (data directory) நகலெடுக்கலாமா?

container நிறுத்தப்பட்ட நிலையில் மட்டுமே இது சாத்தியம். server இயங்கிக்கொண்டிருக்கும்போது, அதன் கோப்புகள் தொடர்ந்து மாறிக்கொண்டே இருக்கும், எனவே நகலெடுக்கப்படும் கோப்புகள் முரண்பட்ட தரவுகளைக் கொண்டிருக்கலாம். மேலும், கோப்பு அளவிலான நகல் (file-level copy) ஒரு குறிப்பிட்ட Postgres major version-க்கு மட்டுமே பொருந்தும்; எனவே, வேறொரு version-ல் அதைத் தொடங்க முடியாது. container-ஐ நிறுத்தி, volume-ஐ archive செய்து, மீண்டும் தொடங்கவும். இதை ஒரு முழுமையான backup-ஆகக் கருதாமல், விரைவான மீள் உருவாக்கும் (rebuild) வழியாகக் கருதவும். dump கோப்பே எடுத்துச் செல்லக்கூடிய (portable) நகலாகும், அதிலிருந்துதான் நீங்கள் restore செய்ய வேண்டும்.

Compose-ல் Postgres-ஐ புதிய major version-க்கு எப்படி upgrade செய்வது?

tag-ஐ மட்டும் மாற்றுவது போதாது. புதிய server பழைய தரவு அடைவில் தொடங்க மறுத்து, The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17.2 என்ற பிழையைக் காட்டும். பழைய version இயங்கிக்கொண்டிருக்கும்போதே pg_dump-ஐ இயக்கவும், பிறகு docker compose down-ஐப் பயன்படுத்தவும். database volume-ஐ நீக்கிவிட்டு, புதிய tag-ஐ அமைத்து, புதிய காலி volume-க்காக docker compose create-ஐ இயக்கவும். பிறகு database-ஐத் தொடங்கி, dump-ஐ அதில் restore செய்யவும். புதிய version சரியாகச் செயல்படும் வரை பழைய dump-ஐ வைத்திருக்கவும்.

எவ்வளவு அடிக்கடி backup எடுக்க வேண்டும், அவற்றை எவ்வளவு காலம் வைத்திருக்க வேண்டும்?

மீண்டும் செய்ய வேண்டிய வேலை எவ்வளவு என்பதைப் பொறுத்து கால இடைவெளியைத் தீர்மானிக்கவும். தனிப்பட்ட அல்லது சிறிய குழுக்களின் பயன்பாட்டிற்கு இரவு நேர backup போதுமானது, அத்துடன் ஏதேனும் upgrade செய்வதற்கு முன்பு ஒருமுறை manual backup எடுக்கவும். தரவுச் சிதைவு போன்றவற்றைச் சமாளிக்க, போதுமான காலத்திற்குப் பழைய நகல்களை வைத்திருக்கவும்; வெள்ளிக்கிழமை கண்டறியப்படும் ஒரு சிதைந்த table-க்கு, வியாழக்கிழமை இரவு எடுத்த நகல் உதவாது. restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune என்பது ஒரு நியாயமான தொடக்கக் கொள்கையாகும். கால அட்டவணை எதுவாக இருந்தாலும், காலாண்டுக்கு ஒருமுறை restore செய்து பார்க்கவும். அவ்வாறு செய்யாதவரை, உங்களிடம் backup இல்லை, வெறும் கோப்புகள் மட்டுமே உள்ளன.

backup எடுப்பதற்காக முழு stack-ஐயும் நிறுத்த வேண்டுமா?

பொதுவாகத் தேவையில்லை. server இயங்கிக்கொண்டிருக்கும்போதே database dump சீராக இருக்கும் என்பதால், database-க்கு downtime தேவையில்லை. volumes-தான் முக்கியமானது. uploads directory போன்ற கோப்புகளை மட்டுமே app சேர்க்கிறது என்றால், இயங்கிக்கொண்டிருக்கும்போதே archive செய்வது பாதுகாப்பானது. கோப்புகளை அதே இடத்தில் மாற்றியமைக்கிறது (rewrite) என்றால், நகலெடுக்கும் நேரம் வரை அந்த ஒரு service-ஐ மட்டும் docker compose stop app மூலம் நிறுத்திவிட்டு, பிறகு தொடங்கவும். database இயங்கிக்கொண்டிருக்கும்போது app-ஐ மட்டும் நிறுத்துவது, பாதுகாப்பான மற்றும் குறுகிய கால இடைவெளியாகும்.