Skip to content

Commit

Permalink
Turn push and load into params for the build arg
Browse files Browse the repository at this point in the history
  • Loading branch information
yuvipanda committed Feb 28, 2025
1 parent e066ca0 commit 07e97ee
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 72 deletions.
60 changes: 7 additions & 53 deletions repo2docker/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,55 +572,6 @@ def initialize(self, *args, **kwargs):
if self.volumes and not self.run:
raise ValueError("Cannot mount volumes if container is not run")

def push_image(self):
"""Push docker image to registry"""
client = self.get_engine()
# Build a progress setup for each layer, and only emit per-layer
# info every 1.5s
progress_layers = {}
layers = {}
last_emit_time = time.time()
for chunk in client.push(self.output_image_spec):
if client.string_output:
self.log.info(chunk, extra=dict(phase=R2dState.PUSHING))
continue
# else this is Docker output

# each chunk can be one or more lines of json events
# split lines here in case multiple are delivered at once
for line in chunk.splitlines():
line = line.decode("utf-8", errors="replace")
try:
progress = json.loads(line)
except Exception as e:
self.log.warning("Not a JSON progress line: %r", line)
continue
if "error" in progress:
self.log.error(progress["error"], extra=dict(phase=R2dState.FAILED))
raise ImageLoadError(progress["error"])
if "id" not in progress:
continue
# deprecated truncated-progress data
if "progressDetail" in progress and progress["progressDetail"]:
progress_layers[progress["id"]] = progress["progressDetail"]
else:
progress_layers[progress["id"]] = progress["status"]
# include full progress data for each layer in 'layers' data
layers[progress["id"]] = progress
if time.time() - last_emit_time > 1.5:
self.log.info(
"Pushing image\n",
extra=dict(
progress=progress_layers,
layers=layers,
phase=R2dState.PUSHING,
),
)
last_emit_time = time.time()
self.log.info(
f"Successfully pushed {self.output_image_spec}",
extra=dict(phase=R2dState.PUSHING),
)

def run_image(self):
"""Run docker container from built image
Expand Down Expand Up @@ -847,14 +798,20 @@ def build(self):
extra=dict(phase=R2dState.BUILDING),
)

extra_build_kwargs = self.extra_build_kwargs.copy()
# Set "push" and "load" parameters in a backwards compat way, without
# having to change the signature of every buildpack
extra_build_kwargs["push"] = self.push
extra_build_kwargs["load"] = self.run

for l in picked_buildpack.build(
docker_client,
self.output_image_spec,
# This is deprecated, but passing it anyway to not break backwards compatibility
self.build_memory_limit,
build_args,
self.cache_from,
self.extra_build_kwargs,
extra_build_kwargs,
platform=self.platform,
):
if docker_client.string_output:
Expand Down Expand Up @@ -886,8 +843,5 @@ def build(self):
def start(self):
self.build()

if self.push:
self.push_image()

if self.run:
self.run_image()
45 changes: 26 additions & 19 deletions repo2docker/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
Docker container engine for repo2docker
"""

from argparse import ArgumentError
import json
import os
import shutil
import subprocess
import tarfile
import tempfile
from contextlib import contextmanager
from contextlib import ExitStack, contextmanager
from pathlib import Path

from iso8601 import parse_date
Expand Down Expand Up @@ -89,6 +90,8 @@ class DockerEngine(ContainerEngine):

def build(
self,
push=False,
load=False,
*,
buildargs=None,
cache_from=None,
Expand All @@ -104,7 +107,15 @@ def build(
):
if not shutil.which("docker"):
raise RuntimeError("The docker commandline client must be installed")
args = ["docker", "buildx", "build", "--progress", "plain", "--load"]
args = ["docker", "buildx", "build", "--progress", "plain"]
if load:
if push:
raise ValueError("Setting push=True and load=True is currently not supported")
args.append("--load")

if push:
args.append("--push")

if buildargs:
for k, v in buildargs.items():
args += ["--build-arg", f"{k}={v}"]
Expand All @@ -129,19 +140,22 @@ def build(
# place extra args right *before* the path
args += self.extra_buildx_build_args

if fileobj:
with tempfile.TemporaryDirectory() as d:
tarf = tarfile.open(fileobj=fileobj)
tarf.extractall(d)
with ExitStack() as stack:
if self.registry_credentials:
stack.enter_context(self.docker_login(**self.registry_credentials))
if fileobj:
with tempfile.TemporaryDirectory() as d:
tarf = tarfile.open(fileobj=fileobj)
tarf.extractall(d)

args += [d]
args += [d]

yield from execute_cmd(args, True)
else:
# Assume 'path' is passed in
args += [path]
yield from execute_cmd(args, True)
else:
# Assume 'path' is passed in
args += [path]

yield from execute_cmd(args, True)
yield from execute_cmd(args, True)

def inspect_image(self, image):
"""
Expand Down Expand Up @@ -194,13 +208,6 @@ def docker_login(self, username, password, registry):
else:
del os.environ["DOCKER_CONFIG"]

def push(self, image_spec):
if self.registry_credentials:
with self.docker_login(**self.registry_credentials):
yield from execute_cmd(["docker", "push", image_spec], capture=True)
else:
yield from execute_cmd(["docker", "push", image_spec], capture=True)

def run(
self,
image_spec,
Expand Down
6 changes: 6 additions & 0 deletions repo2docker/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ def __init__(self, *, parent):

def build(
self,
push=False,
load=False,
*,
buildargs={},
cache_from=[],
Expand All @@ -230,6 +232,10 @@ def build(
Parameters
----------
push: bool
Push the resulting image to a registry
load: bool
Load the resulting image into the container store ready to be run
buildargs : dict
Dictionary of build arguments
cache_from : list[str]
Expand Down

0 comments on commit 07e97ee

Please sign in to comment.