kopia lustrzana https://github.com/jupyterhub/repo2docker
Turn push and load into params for the build arg
rodzic
e066ca04a1
commit
07e97ee5ce
|
@ -572,55 +572,6 @@ class Repo2Docker(Application):
|
||||||
if self.volumes and not self.run:
|
if self.volumes and not self.run:
|
||||||
raise ValueError("Cannot mount volumes if container is not 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):
|
def run_image(self):
|
||||||
"""Run docker container from built image
|
"""Run docker container from built image
|
||||||
|
@ -847,6 +798,12 @@ class Repo2Docker(Application):
|
||||||
extra=dict(phase=R2dState.BUILDING),
|
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(
|
for l in picked_buildpack.build(
|
||||||
docker_client,
|
docker_client,
|
||||||
self.output_image_spec,
|
self.output_image_spec,
|
||||||
|
@ -854,7 +811,7 @@ class Repo2Docker(Application):
|
||||||
self.build_memory_limit,
|
self.build_memory_limit,
|
||||||
build_args,
|
build_args,
|
||||||
self.cache_from,
|
self.cache_from,
|
||||||
self.extra_build_kwargs,
|
extra_build_kwargs,
|
||||||
platform=self.platform,
|
platform=self.platform,
|
||||||
):
|
):
|
||||||
if docker_client.string_output:
|
if docker_client.string_output:
|
||||||
|
@ -886,8 +843,5 @@ class Repo2Docker(Application):
|
||||||
def start(self):
|
def start(self):
|
||||||
self.build()
|
self.build()
|
||||||
|
|
||||||
if self.push:
|
|
||||||
self.push_image()
|
|
||||||
|
|
||||||
if self.run:
|
if self.run:
|
||||||
self.run_image()
|
self.run_image()
|
||||||
|
|
|
@ -2,13 +2,14 @@
|
||||||
Docker container engine for repo2docker
|
Docker container engine for repo2docker
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from argparse import ArgumentError
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import tarfile
|
import tarfile
|
||||||
import tempfile
|
import tempfile
|
||||||
from contextlib import contextmanager
|
from contextlib import ExitStack, contextmanager
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from iso8601 import parse_date
|
from iso8601 import parse_date
|
||||||
|
@ -89,6 +90,8 @@ class DockerEngine(ContainerEngine):
|
||||||
|
|
||||||
def build(
|
def build(
|
||||||
self,
|
self,
|
||||||
|
push=False,
|
||||||
|
load=False,
|
||||||
*,
|
*,
|
||||||
buildargs=None,
|
buildargs=None,
|
||||||
cache_from=None,
|
cache_from=None,
|
||||||
|
@ -104,7 +107,15 @@ class DockerEngine(ContainerEngine):
|
||||||
):
|
):
|
||||||
if not shutil.which("docker"):
|
if not shutil.which("docker"):
|
||||||
raise RuntimeError("The docker commandline client must be installed")
|
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:
|
if buildargs:
|
||||||
for k, v in buildargs.items():
|
for k, v in buildargs.items():
|
||||||
args += ["--build-arg", f"{k}={v}"]
|
args += ["--build-arg", f"{k}={v}"]
|
||||||
|
@ -129,19 +140,22 @@ class DockerEngine(ContainerEngine):
|
||||||
# place extra args right *before* the path
|
# place extra args right *before* the path
|
||||||
args += self.extra_buildx_build_args
|
args += self.extra_buildx_build_args
|
||||||
|
|
||||||
if fileobj:
|
with ExitStack() as stack:
|
||||||
with tempfile.TemporaryDirectory() as d:
|
if self.registry_credentials:
|
||||||
tarf = tarfile.open(fileobj=fileobj)
|
stack.enter_context(self.docker_login(**self.registry_credentials))
|
||||||
tarf.extractall(d)
|
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)
|
yield from execute_cmd(args, True)
|
||||||
else:
|
|
||||||
# Assume 'path' is passed in
|
|
||||||
args += [path]
|
|
||||||
|
|
||||||
yield from execute_cmd(args, True)
|
|
||||||
|
|
||||||
def inspect_image(self, image):
|
def inspect_image(self, image):
|
||||||
"""
|
"""
|
||||||
|
@ -194,13 +208,6 @@ class DockerEngine(ContainerEngine):
|
||||||
else:
|
else:
|
||||||
del os.environ["DOCKER_CONFIG"]
|
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(
|
def run(
|
||||||
self,
|
self,
|
||||||
image_spec,
|
image_spec,
|
||||||
|
|
|
@ -212,6 +212,8 @@ class ContainerEngine(LoggingConfigurable):
|
||||||
|
|
||||||
def build(
|
def build(
|
||||||
self,
|
self,
|
||||||
|
push=False,
|
||||||
|
load=False,
|
||||||
*,
|
*,
|
||||||
buildargs={},
|
buildargs={},
|
||||||
cache_from=[],
|
cache_from=[],
|
||||||
|
@ -230,6 +232,10 @@ class ContainerEngine(LoggingConfigurable):
|
||||||
|
|
||||||
Parameters
|
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
|
buildargs : dict
|
||||||
Dictionary of build arguments
|
Dictionary of build arguments
|
||||||
cache_from : list[str]
|
cache_from : list[str]
|
||||||
|
|
Ładowanie…
Reference in New Issue