diff --git a/update_docker_project.py b/update_docker_project.py new file mode 100644 index 0000000..bc544e4 --- /dev/null +++ b/update_docker_project.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 + +import subprocess +import argparse +import os +import shutil +import sys +import re + +# Sprawdzenie PyYAML +try: + import yaml +except ImportError: + print("Błąd: brak modułu 'pyyaml'.") + print("Zainstaluj go komendą: pip install pyyaml / zypper in python312-pyaml / apt install python3-yaml") + sys.exit(1) + +def detect_compose_command(): + if shutil.which("docker-compose"): + return "docker-compose" + elif shutil.which("docker"): + result = subprocess.run("docker compose version", shell=True, stdout=subprocess.DEVNULL) + if result.returncode == 0: + return "docker compose" + print("Nie znaleziono docker compose ani docker-compose.") + sys.exit(1) + +def run(cmd, capture_output=False): + result = subprocess.run(cmd, shell=True, capture_output=capture_output, text=True) + if result.returncode != 0: + print(f"Błąd: {cmd}") + if result.stderr: + print(result.stderr) + return result.stdout.strip() if capture_output else None + +def stop_containers(compose_cmd, compose_file, project_name): + print("Zatrzymywanie kontenerów...") + run(f"{compose_cmd} -p {project_name} -f {compose_file} down") + +def resolve_env_var(value: str) -> str: + pattern = re.compile(r'\$\{([^}:\-]+)(?::-([^}]+))?\}') + def replacer(match): + var, default = match.groups() + return os.environ.get(var, default or "") + return pattern.sub(replacer, value) + +def get_images_from_compose(compose_path): + with open(compose_path, "r") as f: + data = yaml.safe_load(f) + services = data.get("services", {}) + resolved_images = [] + for svc in services.values(): + image = svc.get("image") + if image: + resolved_images.append(resolve_env_var(image)) + return resolved_images + +def check_for_updates(images): + print("Sprawdzanie aktualizacji...") + updates = {} + for image in images: + print(f"- Sprawdzanie obrazu: {image}") + pull_result = run(f"docker pull {image}", capture_output=True) + if pull_result and "Downloaded newer image" in pull_result: + updates[image] = image + return updates + +def prune_images(): + print("Czyszczenie nieużywanych obrazów...") + run("docker image prune -f") + +def start_containers(compose_cmd, compose_file, project_name): + print("Uruchamianie kontenerów...") + run(f"{compose_cmd} -p {project_name} -f {compose_file} up -d") + +def main(): + parser = argparse.ArgumentParser(description="Aktualizacja i restart docker-compose projektu.") + parser.add_argument('--project-folder', required=True, help='Ścieżka do folderu projektu') + parser.add_argument('--compose-file', required=True, help='Ścieżka do pliku docker-compose.yml') + parser.add_argument('--project-name', required=True, help='Nazwa projektu docker-compose') + + args = parser.parse_args() + os.chdir(args.project_folder) + + compose_cmd = detect_compose_command() + images = get_images_from_compose(args.compose_file) + + updated = check_for_updates(images) + + if updated: + stop_containers(compose_cmd, args.compose_file, args.project_name) + print("Zaktualizowane obrazy:") + for img in updated: + print(f"- {img}") + prune_images() + start_containers(compose_cmd, args.compose_file, args.project_name) + else: + print("Obrazy aktualne. Nie zatrzymuję i nie uruchamiam kontenerów.") + + print("Zakończono.") + +if __name__ == "__main__": + main()