[chat gpt vs. gemini] 챗지피티 와 제미나이 한테 도커 database backup script 만들라고 하기
- 두 AI 모두 무료사양을 이용
선 결론
- chatGTP 보다 gemini 가 원하는 코딩을 해줬다.
요구된 코딩
- docker mysql db 를 찾아서, 백업을 한다. (env 에서 기본정보를 가져온다)
- docker maria db 를 찾아서, 백업을 한다. (env 에서 기본정보를 가져온다)
- docker progresql 를 찾아서, 백업을 한다. (env 에서 기본정보를 가져온다)
결과 (우분투 서버 24.04 에서 작동 확인)
#!/bin/bash
# --- Configuration ---
BACKUP_DIR="/vo2" # Base directory for all backups
DATE=$(date +%Y%m%d_%H%M%S)# --- Functions ---
# Function to extract an environment variable from a container
get_env_var() {
local container_id="$1"
local var_name="$2"
# Inspect container, format to get each env var on a new line, then grep
docker inspect "$container_id" --format='{{range .Config.Env}}{{.}}{{"\n"}}{{end}}' | \
grep "^${var_name}=" | head -n 1 | cut -d'=' -f2-
}# Function to backup MySQL/MariaDB
backup_mysql_mariadb() {
local container_id="$1"
local container_name="$2"
local db_user="$3"
local db_password="$4"
local db_name="$5"echo "--- Backing up MySQL/MariaDB container: $container_name (ID: $container_id) ---"
# Export credentials so mysqldump can pick them up
export MYSQL_USER="$db_user"
export MYSQL_PASSWORD="$db_password"if [ -z "$db_name" ]; then
echo "Warning: MYSQL_DATABASE not found for $container_name. Attempting to dump all user databases..."
if [ -z "$db_user" ]; then
echo "Error: No MYSQL_USER found. Cannot backup without a user. Skipping."
unset MYSQL_USER MYSQL_PASSWORD # Unset immediately if error
return 1
fi
echo "Dumping all databases (excluding system databases)..."
local backup_file="$BACKUP_DIR/$container_name-$DATE-all_databases.gz"
# Removed the MYSQL_DATABASE export from here as it's not needed for all-databases dump
docker exec -i "$container_id" sh -c 'exec mysqldump -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" --all-databases --ignore-database=information_schema --ignore-database=performance_schema --ignore-database=mysql --ignore-database=sys' | gzip > "$backup_file"if [ $? -eq 0 ]; then
echo "Successfully backed up all databases for $container_name to $backup_file"
else
echo "Error backing up all databases for $container_name."
fi
else
echo "Backing up database: $db_name"
local backup_file="$BACKUP_DIR/$container_name-$db_name-$DATE.gz"
# Pass MYSQL_DATABASE as an environment variable to the exec'd shell
docker exec -i "$container_id" sh -c 'export MYSQL_DATABASE="'"$db_name"'"; exec mysqldump -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE"' | gzip > "$backup_file"if [ $? -eq 0 ]; then
echo "Successfully backed up $db_name for $container_name to $backup_file"
else
echo "Error backing up $db_name for $container_name."
fi
fi
unset MYSQL_USER MYSQL_PASSWORD # Unset after use
echo ""
}# Function to backup PostgreSQL
backup_postgres() {
local container_id="$1"
local container_name="$2"
local db_user="$3"
local db_password="$4"
local db_name="$5"echo "--- Backing up PostgreSQL container: $container_name (ID: $container_id) ---"
# Export PGPASSWORD for pg_dump to pick up
export PGPASSWORD="$db_password"if [ -z "$db_name" ]; then
echo "Warning: POSTGRES_DB not found for $container_name. Attempting to dump all databases..."
if [ -z "$db_user" ]; then
echo "Error: No POSTGRES_USER found. Cannot backup without a user. Skipping."
unset PGPASSWORD # Unset immediately if error
return 1
fi
echo "Dumping all databases (excluding system databases)..."
local backup_file="$BACKUP_DIR/$container_name-$DATE-all_databases.gz"
# pg_dumpall does not take -d, it dumps all databases.
docker exec -i "$container_id" pg_dumpall -U "$db_user" | gzip > "$backup_file"if [ $? -eq 0 ]; then
echo "Successfully backed up all databases for $container_name to $backup_file"
else
echo "Error backing up all databases for $container_name."
fi
else
echo "Backing up database: $db_name"
local backup_file="$BACKUP_DIR/$container_name-$db_name-$DATE.gz"
docker exec -i "$container_id" pg_dump -U "$db_user" -d "$db_name" | gzip > "$backup_file"if [ $? -eq 0 ]; then
echo "Successfully backed up $db_name for $container_name to $backup_file"
else
echo "Error backing up $db_name for $container_name."
fi
fi
unset PGPASSWORD # Unset after use
echo ""
}# --- Main Script Logic ---
echo "Starting Docker Database Backup Script..."
echo "Backup directory: $BACKUP_DIR"
echo "Current date: $DATE"
echo ""# Create backup directory if it doesn't exist
mkdir -p "$BACKUP_DIR" || { echo "Error: Could not create backup directory $BACKUP_DIR. Exiting."; exit 1; }# Get a list of all running Docker containers
CONTAINER_IDS=$(docker ps -q)if [ -z "$CONTAINER_IDS" ]; then
echo "No running Docker containers found."
exit 0
fifor ID in $CONTAINER_IDS; do
CONTAINER_NAME=$(docker inspect -f '{{.Name}}' "$ID" | sed 's/^\///') # Remove leading slash
CONTAINER_IMAGE=$(docker inspect -f '{{.Config.Image}}' "$ID")echo "Processing container: $CONTAINER_NAME (Image: $CONTAINER_IMAGE)"
# --- Determine DB Type and Extract Credentials ---
DB_TYPE="unknown"
DB_USER=""
DB_PASSWORD=""
DB_NAME=""# Check for MySQL/MariaDB
if [[ "$CONTAINER_IMAGE" == *mysql* ]] || [[ "$CONTAINER_IMAGE" == *mariadb* ]]; then
DB_TYPE="mysql_mariadb"
# Try to get specific user and password first
DB_USER=$(get_env_var "$ID" "MYSQL_USER")
DB_PASSWORD=$(get_env_var "$ID" "MYSQL_PASSWORD")
DB_NAME=$(get_env_var "$ID" "MYSQL_DATABASE")if [ -z "$DB_USER" ]; then
# Fallback to root if MYSQL_USER is not set
DB_USER="root"
DB_PASSWORD=$(get_env_var "$ID" "MYSQL_ROOT_PASSWORD")
if [ -z "$DB_PASSWORD" ]; then
echo "Warning: No MYSQL_ROOT_PASSWORD or MYSQL_PASSWORD found for $CONTAINER_NAME. MySQL/MariaDB backup might fail."
fi
fiif [ -z "$DB_USER" ] || [ -z "$DB_PASSWORD" ]; then
echo "Error: Could not retrieve MySQL/MariaDB credentials (MYSQL_USER/PASSWORD or MYSQL_ROOT_PASSWORD) for $CONTAINER_NAME. Skipping."
continue
fi# Check for PostgreSQL
elif [[ "$CONTAINER_IMAGE" == *postgres* ]]; then
DB_TYPE="postgres"
DB_USER=$(get_env_var "$ID" "POSTGRES_USER")
DB_PASSWORD=$(get_env_var "$ID" "POSTGRES_PASSWORD")
DB_NAME=$(get_env_var "$ID" "POSTGRES_DB")if [ -z "$DB_USER" ]; then
DB_USER="postgres" # Default PostgreSQL user if not specified
fiif [ -z "$DB_PASSWORD" ]; then
echo "Error: Could not retrieve PostgreSQL password (POSTGRES_PASSWORD) for $CONTAINER_NAME. Skipping."
continue
fi
fi# --- Perform Backup based on DB Type ---
case "$DB_TYPE" in
"mysql_mariadb")
backup_mysql_mariadb "$ID" "$CONTAINER_NAME" "$DB_USER" "$DB_PASSWORD" "$DB_NAME"
;;
"postgres")
backup_postgres "$ID" "$CONTAINER_NAME" "$DB_USER" "$DB_PASSWORD" "$DB_NAME"
;;
*)
echo "Skipping unknown database type for container: $CONTAINER_NAME (Image: $CONTAINER_IMAGE)"
echo ""
;;
esacdone
sudo find "$BACKUP_DIR" -name "*.*" -mtime +1 -exec rm {} \; #하루지난 파일 삭제
echo "Docker Database Backup Script Finished."
echo "Backups are located in: $BACKUP_DIR"
$chmod +x dbbcakup.sh
백업된 데이터 형식은 다음과 같다.
wordpress-db-1-exampledb-20250609_101625.gz
잘 백업되었는지 검증해 보려면, zcat 을 하면 된다.
$zcat wordpress-db-1-exampledb-20250609_101259.gz
$zless wordpress-db-1-exampledb-20250609_101259.gz #페이지별로 끈어서 봄 'q' 중단
$gzip -d -k wordpress-db-1-exampledb-20250609_101259.gz #압축풀기, sql 확장자로 됨