Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to dump DB via cron inside container?

I use docker-compose which ups a stack.

Relative code:

db:
  build: ./dockerfiles/postgres
  container_name: postgres-container
  volumes:
    - ./dockerfiles/postgres/pgdata:/var/lib/postgresql/data
    - ./dockerfiles/postgres/backups:/pg_backups

Dockerfile for Postgres:

FROM postgres:latest

RUN mkdir /pg_backups && > /etc/cron.d/pg_backup-cron && echo "00 22 * * * /backup.sh" >> /etc/cron.d/pg_backup-cron
ADD ./backup.sh /
RUN chmod +x /backup.sh

backup.sh

#!/bin/sh
# Dump DBs

now=$(date +"%d-%m-%Y_%H-%M")
pg_dump -h db -U postgres -d postgres > "/pg_backups/db_dump_$now.sql"

# remove all files (type f) modified longer than 30 days ago under /pg_backups
find /pg_backups -name "*.sql" -type f -mtime +30 -delete

exit 0

Cron simply does not launch the script. How to fix that?


FINAL VERSION

Based on @Farhad Farahi answer, below is the final result:

On host I made a script:

#!/bin/bash
# Creates Cron Job which backups DB in Docker everyday at 22:00 host time
croncmd_backup="docker exec -it postgres-container bash -c '/pg_backups/backup.sh'"
cronjob_backup="00 22 * * * $croncmd_backup"

if [[ $# -eq 0 ]] ; then
    echo -e 'Please provide one of the arguments (example: ./run_after_install.sh add-cron-db-backup):
    1) add-cron-db-backup
    2) remove-cron-db-backup'

# In order to avoid task duplications in cron, the script checks, if there is already back-up job in cron
elif [[ $1 == add-cron-db-backup ]]; then
    ( crontab -l | grep -v -F "$croncmd_backup" ; echo "$cronjob_backup" ) | crontab -
    echo "==>>> Backup task added to Cron"

# Remove back-up job from cron
elif [[ $1 == remove-cron-db-backup ]]; then
    ( crontab -l | grep -v -F "$croncmd_backup" ) | crontab -
    echo "==>>> Backup task removed from Cron"

fi

This script adds cron task to host, which launches the script backup.sh (see above) in a container.

For this implementation there is no need to use Dockerfile for Postgres, so relevant part of docker-compose.yml should look like:

version: '2'
services:
  db:
    image: postgres:latest
    container_name: postgres-container
    volumes:
      - ./dockerfiles/postgres/pgdata:/var/lib/postgresql/data
      - ./dockerfiles/postgres/backups:/pg_backups
like image 469
TitanFighter Avatar asked Dec 23 '22 22:12

TitanFighter


2 Answers

Things you should know:

  1. cron service is not started by default in postgres library image.

  2. when you change cron config, you need to reload cron service.

Recommendation:

Use docker host's cron and use docker exec to launch the periodic tasks.

Advantages of this approach:

  1. Unified Configuration for all containers.

  2. Avoids running multiple cron services in multiple containers (Better usage of system resources aswell as less management overhead.

  3. Honors Microservices Philosophy.
like image 192
Farhad Farahi Avatar answered Dec 28 '22 11:12

Farhad Farahi


Based on the Farhad's answer I created a file postgres_backup.sh on the host with the next content:

#!/bin/bash
# Creates Cron Job which backups DB in Docker everyday at 22:00 host time
croncmd_backup="docker exec -it postgres-container bash -c '/db_backups/script/backup.sh'"
cronjob_backup="00 22 * * * $croncmd_backup"

if [[ $# -eq 0 ]] ; then
    echo -e 'Please provide one of the arguments (example: ./postgres_backup.sh add-cron-db-backup):
    1 > add-cron-db-backup
    2 > remove-cron-db-backup

elif [[ $1 == add-cron-db-backup ]]; then
    ( crontab -l | grep -v -F "$croncmd_backup" ; echo "$cronjob_backup" ) | crontab -
    echo "==>>> Backup task added to Local (not container) Cron"

elif [[ $1 == remove-cron-db-backup ]]; then
    ( crontab -l | grep -v -F "$croncmd_backup" ) | crontab -
    echo "==>>> Backup task removed from Cron"

fi

and I added a file /db_backups/script/backup.sh to Docker's Postgres Image with the content:

#!/bin/sh
# Dump DBs

now=$(date +"%d-%m-%Y_%H-%M")
pg_dump -h db -U postgres -d postgres > "/db_backups/backups/db_dump_$now.sql"

# remove all files (type f) modified longer than 30 days ago under /db_backups/backups
find /db_backups/backups -name "*.sql" -type f -mtime +30 -delete

exit 0
like image 21
TitanFighter Avatar answered Dec 28 '22 11:12

TitanFighter