Spaces:
Sleeping
Sleeping
File size: 5,903 Bytes
dc9e27a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# msdl/docker_manager.py
import os
import subprocess
import sys
from functools import lru_cache
import yaml
from msdl.config import PROJECT_ROOT, TEMP_DIR
from msdl.i18n import t
@lru_cache(maxsize=1)
def get_docker_command():
try:
subprocess.run(
["docker", "compose", "version"], check=True, capture_output=True
)
return ["docker", "compose"]
except subprocess.CalledProcessError:
try:
subprocess.run(
["docker-compose", "--version"], check=True, capture_output=True
)
return ["docker-compose"]
except subprocess.CalledProcessError:
print(t("DOCKER_COMPOSE_NOT_FOUND"))
sys.exit(1)
@lru_cache(maxsize=1)
def check_docker_install():
try:
subprocess.run(["docker", "--version"], check=True, capture_output=True)
docker_compose_cmd = get_docker_command()
subprocess.run(
docker_compose_cmd + ["version"], check=True, capture_output=True
)
print(t("DOCKER_INSTALLED"))
return True
except subprocess.CalledProcessError as e:
print(t("DOCKER_INSTALL_ERROR", error=str(e)))
return False
except FileNotFoundError:
print(t("DOCKER_NOT_FOUND"))
return False
def stop_and_remove_containers():
docker_compose_cmd = get_docker_command()
compose_file = os.path.join(TEMP_DIR, "docker-compose.yaml")
# Read the docker-compose.yaml file
try:
with open(compose_file, "r") as file:
compose_config = yaml.safe_load(file)
except Exception as e:
print(t("COMPOSE_FILE_READ_ERROR", error=str(e)))
return
# Get project name and service names
project_name = compose_config.get("name", "mindsearch")
service_names = list(compose_config.get("services", {}).keys())
# Use only the project name as the container prefix
container_prefix = f"{project_name}_"
try:
# 1. Try to stop containers using the current docker-compose.yaml
subprocess.run(
docker_compose_cmd + ["-f", compose_file, "down", "-v", "--remove-orphans"],
check=True,
)
except subprocess.CalledProcessError:
print(t("CURRENT_COMPOSE_STOP_FAILED"))
# 2. Attempt to clean up potentially existing containers, regardless of the success of the previous step
try:
# List all containers (including stopped ones)
result = subprocess.run(
["docker", "ps", "-a", "--format", "{{.Names}}"],
check=True,
capture_output=True,
text=True,
)
all_containers = result.stdout.splitlines()
# 3. Filter out containers belonging to our project
project_containers = [
c
for c in all_containers
if c.startswith(container_prefix)
or any(c == f"{project_name}-{service}" for service in service_names)
]
if project_containers:
# 4. Force stop and remove these containers
for container in project_containers:
try:
subprocess.run(["docker", "stop", container], check=True)
subprocess.run(["docker", "rm", "-f", container], check=True)
print(t("CONTAINER_STOPPED_AND_REMOVED", container=container))
except subprocess.CalledProcessError as e:
print(t("CONTAINER_STOP_ERROR", container=container, error=str(e)))
# 5. Clean up potentially leftover networks
try:
subprocess.run(["docker", "network", "prune", "-f"], check=True)
print(t("NETWORKS_PRUNED"))
except subprocess.CalledProcessError as e:
print(t("NETWORK_PRUNE_ERROR", error=str(e)))
except subprocess.CalledProcessError as e:
print(t("DOCKER_LIST_ERROR", error=str(e)))
print(t("CONTAINERS_STOPPED_AND_REMOVED"))
def run_docker_compose():
docker_compose_cmd = get_docker_command()
try:
print(t("STARTING_CONTAINERS_WITH_BUILD"))
subprocess.run(
docker_compose_cmd
+ [
"-f",
os.path.join(TEMP_DIR, "docker-compose.yaml"),
"--env-file",
os.path.join(TEMP_DIR, ".env"),
"up",
"-d",
"--build",
],
check=True,
)
print(t("CONTAINERS_STARTED"))
except subprocess.CalledProcessError as e:
print(t("DOCKER_ERROR", error=str(e)))
print(t("DOCKER_OUTPUT"))
print(e.output.decode() if e.output else "No output")
stop_and_remove_containers()
sys.exit(1)
def update_docker_compose_paths(project_root=PROJECT_ROOT):
docker_compose_path = os.path.join(TEMP_DIR, "docker-compose.yaml")
with open(docker_compose_path, "r") as file:
compose_data = yaml.safe_load(file)
for service in compose_data["services"].values():
if "build" in service:
if "context" in service["build"]:
if service["build"]["context"] == "..":
service["build"]["context"] = project_root
else:
service["build"]["context"] = os.path.join(
project_root, service["build"]["context"]
)
if "dockerfile" in service["build"]:
dockerfile_name = os.path.basename(service["build"]["dockerfile"])
service["build"]["dockerfile"] = os.path.join(TEMP_DIR, dockerfile_name)
with open(docker_compose_path, "w") as file:
yaml.dump(compose_data, file)
print(t("PATHS_UPDATED"))
def main():
if check_docker_install():
update_docker_compose_paths()
run_docker_compose()
else:
sys.exit(1)
if __name__ == "__main__":
main()
|