Merge pull request 'feat: Python on whales & embedded docker CLI' (#29) from compose into develop (resolves #23)
Reviewed-on: https://hattori.ztsh.eu/iac/karl/pulls/29
This commit is contained in:
commit
b10fcf702a
3 changed files with 12 additions and 50 deletions
|
|
@ -14,10 +14,10 @@ ADD . /app
|
||||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||||
uv sync --locked
|
uv sync --locked
|
||||||
|
|
||||||
FROM python:3.12-alpine3.22
|
FROM docker:29.1.3-cli
|
||||||
|
|
||||||
ENV USER=karl
|
ENV USER=karl
|
||||||
ENV GROUPNAME=docker
|
ENV GROUPNAME=docker-host
|
||||||
ENV UID=1000
|
ENV UID=1000
|
||||||
ENV GID=994
|
ENV GID=994
|
||||||
ENV PYTHONPATH="/app"
|
ENV PYTHONPATH="/app"
|
||||||
|
|
@ -39,7 +39,8 @@ RUN addgroup \
|
||||||
$USER
|
$USER
|
||||||
|
|
||||||
RUN apk update --no-cache \
|
RUN apk update --no-cache \
|
||||||
&& apk add --no-cache git
|
&& apk add --no-cache git python3 \
|
||||||
|
&& ln -s /usr/bin/python3 /usr/local/bin/python3
|
||||||
|
|
||||||
COPY --from=builder --chown=app:app /app/.venv /app/.venv
|
COPY --from=builder --chown=app:app /app/.venv /app/.venv
|
||||||
COPY --from=builder --chown=app:app /app/src /app/src
|
COPY --from=builder --chown=app:app /app/src /app/src
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,13 @@ dependencies = [
|
||||||
"pyyaml>=6.0.2",
|
"pyyaml>=6.0.2",
|
||||||
"gitpython>=3.1.45",
|
"gitpython>=3.1.45",
|
||||||
"pykeepass>=4.1.1.post1",
|
"pykeepass>=4.1.1.post1",
|
||||||
"docker>=7.1.0",
|
|
||||||
"injectable==4.0.1",
|
"injectable==4.0.1",
|
||||||
"py-automapper>=2.2.0",
|
"py-automapper>=2.2.0",
|
||||||
"fastapi-utils>=0.8.0",
|
"fastapi-utils>=0.8.0",
|
||||||
"keyring>=25.6.0",
|
"keyring>=25.6.0",
|
||||||
"keyring-backend>=0.1.0",
|
"keyring-backend>=0.1.0",
|
||||||
"bubus>=1.5.6",
|
"bubus>=1.5.6",
|
||||||
|
"python-on-whales>=0.79.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import docker
|
|
||||||
from docker.models.containers import Container
|
|
||||||
from injectable import injectable
|
from injectable import injectable
|
||||||
|
from python_on_whales import DockerClient
|
||||||
from karl.model.containers import Tree, Compose, SimpleContainer
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
@ -13,47 +11,10 @@ logger = logging.getLogger(__name__)
|
||||||
@injectable(singleton=True)
|
@injectable(singleton=True)
|
||||||
class DockerService:
|
class DockerService:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._client = docker.from_env()
|
self._client = DockerClient()
|
||||||
# logger.info(f"Docker client initialized. Plugins: {self._client.plugins()}")
|
|
||||||
self._tree = self._init_tree()
|
|
||||||
|
|
||||||
def _init_tree(self) -> Tree:
|
|
||||||
tree = Tree()
|
|
||||||
container: Container
|
|
||||||
for container in self._client.containers.list():
|
|
||||||
labels = container.labels
|
|
||||||
working_dir = labels.get("com.docker.compose.project.working_dir")
|
|
||||||
if working_dir:
|
|
||||||
if tree.composes.get(working_dir) is None:
|
|
||||||
tree.composes[working_dir] = Compose(working_dir)
|
|
||||||
tree.composes[working_dir].containers.append(SimpleContainer.from_container(container))
|
|
||||||
else:
|
|
||||||
tree.containers.append(SimpleContainer.from_container(container))
|
|
||||||
return tree
|
|
||||||
|
|
||||||
@property
|
|
||||||
def tree(self) -> Tree:
|
|
||||||
return self._tree
|
|
||||||
|
|
||||||
def reload(self, compose_path: Path):
|
def reload(self, compose_path: Path):
|
||||||
# TODO: Won't work in docker container
|
os.chdir(compose_path.parent)
|
||||||
cmd = ["sudo", "docker", "compose", "-f", str(compose_path), "up", "-d"]
|
self._client.compose.ps()
|
||||||
import subprocess
|
self._client.compose.down(remove_orphans=True)
|
||||||
try:
|
self._client.compose.up()
|
||||||
process = subprocess.run(
|
|
||||||
cmd,
|
|
||||||
capture_output=True,
|
|
||||||
text=True,
|
|
||||||
check=False
|
|
||||||
)
|
|
||||||
if process.returncode != 0:
|
|
||||||
logger.error(f"Docker compose failed with code {process.returncode}")
|
|
||||||
logger.error(f"stderr: {process.stderr}")
|
|
||||||
raise Exception(f"Docker compose failed: {process.stderr}")
|
|
||||||
|
|
||||||
logger.info(f"Docker compose executed successfully")
|
|
||||||
logger.debug(f"stdout: {process.stdout}")
|
|
||||||
return process.stdout, process.stderr, process.returncode
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Failed to execute docker compose command: {e}")
|
|
||||||
raise e
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue