[IMP] runbot: allow to specify a custom docker registry

This commit is contained in:
Xavier-Do 2025-01-29 11:15:08 +01:00 committed by Christophe Monniez
parent c9c31f843c
commit 56912d356f
3 changed files with 28 additions and 12 deletions

View File

@ -137,11 +137,11 @@ def _docker_build(build_dir, image_tag):
return dm.result return dm.result
def docker_push(image_tag): def docker_push(image_tag, push_url='127.0.0.1:5001'):
return _docker_push(image_tag) return _docker_push(image_tag, push_url)
def _docker_push(image_tag): def _docker_push(image_tag, push_url):
"""Push a Docker image to the localy hosted docker registry """Push a Docker image to the localy hosted docker registry
:param image_tag: the image tag (or id) to push :param image_tag: the image tag (or id) to push
:return: tuple(success, msg) where success is a boolean and msg is the error message or None :return: tuple(success, msg) where success is a boolean and msg is the error message or None
@ -149,7 +149,7 @@ def _docker_push(image_tag):
with DockerManager(image_tag) as dm: with DockerManager(image_tag) as dm:
image = dm.docker_client.images.get(image_tag) image = dm.docker_client.images.get(image_tag)
push_tag = f'127.0.0.1:5001/{image_tag}' push_tag = f'{push_url}/{image_tag}'
image.tag(push_tag) image.tag(push_tag)
for chunk in dm.consume(dm.docker_client.api.push(push_tag, stream=True)): for chunk in dm.consume(dm.docker_client.api.push(push_tag, stream=True)):
if not dm.log_progress and 'Pushing' in chunk.get('status', ''): if not dm.log_progress and 'Pushing' in chunk.get('status', ''):

View File

@ -853,10 +853,9 @@ class BuildResult(models.Model):
if 'image_tag' not in kwargs: if 'image_tag' not in kwargs:
kwargs.update({'image_tag': self.params_id.dockerfile_id.image_tag}) kwargs.update({'image_tag': self.params_id.dockerfile_id.image_tag})
self._log('Preparing', 'Using Dockerfile Tag [%s](/runbot/dockerfile/tag/%s)', kwargs['image_tag'], kwargs['image_tag'], log_type='markdown') self._log('Preparing', 'Using Dockerfile Tag [%s](/runbot/dockerfile/tag/%s)', kwargs['image_tag'], kwargs['image_tag'], log_type='markdown')
icp = self.env['ir.config_parameter'] docker_registry_url = self.host_id._get_docker_registry_url()
docker_registry_host = self.env['runbot.host'].browse(int(icp.get_param('runbot.docker_registry_host_id', default=0))) if docker_registry_url and self.host_id.use_remote_docker_registry:
if docker_registry_host and self.host_id.use_remote_docker_registry: result = docker_pull(f"{docker_registry_url}/{kwargs['image_tag']}")
result = docker_pull(f"dockerhub.{docker_registry_host.name}/{kwargs['image_tag']}")
if result['success']: if result['success']:
result['image'].tag(kwargs['image_tag']) result['image'].tag(kwargs['image_tag'])
if result.get('log_progress'): if result.get('log_progress'):

View File

@ -121,21 +121,32 @@ class Host(models.Model):
self._bootstrap_db_template() self._bootstrap_db_template()
self._bootstrap_local_logs_db() self._bootstrap_local_logs_db()
def _get_docker_registry_url(self):
if self.docker_registry_url:
return self.docker_registry_url
icp = self.env['ir.config_parameter']
docker_registry_url = icp.get_param('runbot.docker_registry_url', default=None)
if docker_registry_url:
return docker_registry_url.strip('/')
docker_registry_host = self.browse(int(icp.get_param('runbot.docker_registry_host_id', default=0)))
if docker_registry_host:
return f'dockerhub.{docker_registry_host.name}'.strip('/')
def _docker_update_images(self): def _docker_update_images(self):
""" build docker images needed by locally pending builds""" """ build docker images needed by locally pending builds"""
self.ensure_one() self.ensure_one()
icp = self.env['ir.config_parameter'] icp = self.env['ir.config_parameter']
docker_registry_host = self.browse(int(icp.get_param('runbot.docker_registry_host_id', default=0))) docker_registry_host = self.browse(int(icp.get_param('runbot.docker_registry_host_id', default=0)))
registry_url = self.docker_registry_url.strip('/') if self.docker_registry_url else f'dockerhub.{docker_registry_host.name}' docker_registry_url = self._get_docker_registry_url()
# pull all images from the runbot docker registry # pull all images from the runbot docker registry
is_registry = docker_registry_host == self is_registry = docker_registry_host == self
all_docker_files = self.env['runbot.dockerfile'].search([]) all_docker_files = self.env['runbot.dockerfile'].search([])
all_tags = set(all_docker_files.mapped('image_tag')) all_tags = set(all_docker_files.mapped('image_tag'))
if docker_registry_host and self.use_remote_docker_registry and not is_registry: if docker_registry_url and self.use_remote_docker_registry and not is_registry:
_logger.info('Pulling docker images...') _logger.info('Pulling docker images...')
total_duration = 0 total_duration = 0
for dockerfile in all_docker_files.filtered('always_pull'): for dockerfile in all_docker_files.filtered('always_pull'):
remote_tag = f'{registry_url}/{dockerfile.image_tag}' remote_tag = f'{docker_registry_url}/{dockerfile.image_tag}'
result = docker_pull(remote_tag) result = docker_pull(remote_tag)
if result['success']: if result['success']:
result['image'].tag(dockerfile.image_tag) result['image'].tag(dockerfile.image_tag)
@ -149,7 +160,13 @@ class Host(models.Model):
dockerfile._build(self) dockerfile._build(self)
if is_registry: if is_registry:
try: try:
docker_push(dockerfile.image_tag) docker_push(dockerfile.image_tag) # for now, always push locally
if self.docker_registry_url:
docker_registry_url = self.docker_registry_url
else:
docker_registry_url = icp.get_param('runbot.docker_registry_url', default='').strip('/')
if docker_registry_url:
docker_push(dockerfile.image_tag, docker_registry_url)
except ImageNotFound: except ImageNotFound:
_logger.warning("Image tag `%s` not found. Skipping push", dockerfile.image_tag) _logger.warning("Image tag `%s` not found. Skipping push", dockerfile.image_tag)