111 lines
3.7 KiB
Python
111 lines
3.7 KiB
Python
#!/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 remove_conflicting_containers(images):
|
|
print("Usuwanie kolidujących kontenerów (jeśli istnieją)...")
|
|
for image in images:
|
|
name = image.split(":")[0].split("/")[-1]
|
|
run(f"docker rm -f {name}", capture_output=True)
|
|
|
|
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)
|
|
|
|
stop_containers(compose_cmd, args.compose_file, args.project_name)
|
|
updated = check_for_updates(images)
|
|
|
|
if updated:
|
|
print("Zaktualizowane obrazy:")
|
|
for img in updated:
|
|
print(f"- {img}")
|
|
prune_images()
|
|
remove_conflicting_containers(images)
|
|
start_containers(compose_cmd, args.compose_file, args.project_name)
|
|
else:
|
|
print("Obrazy aktualne. Nie uruchamiam kontenerów.")
|
|
|
|
print("Zakończono.")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|