From 8405d96b108fc9ef85dc05a486fe2de97a5671a4 Mon Sep 17 00:00:00 2001 From: Victor Rodrigues Date: Thu, 18 Sep 2025 23:45:47 +0200 Subject: [PATCH] Accept a custom image registry url (#3066) --- README.md | 3 +++ lib/livebook.ex | 4 ++++ lib/livebook/config.ex | 17 +++++++++++++++++ lib/livebook/hubs/dockerfile.ex | 8 ++++++-- lib/livebook/k8s/pod.ex | 5 ++++- lib/livebook/runtime/fly.ex | 6 +++++- 6 files changed, 39 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2aa13d823..b684a991f 100644 --- a/README.md +++ b/README.md @@ -255,6 +255,9 @@ The following environment variables can be used to configure Livebook on boot: By default iframes are loaded from local `LIVEBOOK_IFRAME_PORT` when accessing Livebook over http:// and from https://livebookusercontent.com when accessing over https://. + * `LIVEBOOK_IMAGE_REGISTRY_URL` - sets the container image registry used to fetch livebook images from. + By default uses `ghcr.io/livebook-dev/livebook`. + * `LIVEBOOK_IP` - sets the ip address to start the web application on. Must be a valid IPv4 or IPv6 address. diff --git a/lib/livebook.ex b/lib/livebook.ex index 0ad85c076..f5269797d 100644 --- a/lib/livebook.ex +++ b/lib/livebook.ex @@ -264,6 +264,10 @@ defmodule Livebook do config :livebook, :agent_name, agent_name end + if image_registry_url = Livebook.Config.image_registry_url!("LIVEBOOK_IMAGE_REGISTRY_URL") do + config :livebook, :image_registry_url, image_registry_url + end + if Livebook.Config.boolean!("LIVEBOOK_FIPS", false) do if :crypto.enable_fips_mode(true) do IO.puts("[Livebook] FIPS mode enabled") diff --git a/lib/livebook/config.ex b/lib/livebook/config.ex index 3314d3ff2..b348bb790 100644 --- a/lib/livebook/config.ex +++ b/lib/livebook/config.ex @@ -20,6 +20,16 @@ defmodule Livebook.Config do Application.get_env(:livebook, :priv_dir) || Application.app_dir(:livebook, "priv") end + @doc """ + Returns container image registry URL. + + This returns the usual container image registry URL, and allows users to specify a custom URL. + """ + @spec image_registry_url() :: String.t() + def image_registry_url() do + Application.get_env(:livebook, :image_registry_url) || "ghcr.io/livebook-dev/livebook" + end + @doc """ Returns docker images to be used when generating sample Dockerfiles. """ @@ -663,6 +673,13 @@ defmodule Livebook.Config do end end + @doc """ + Parses image registry from env. + """ + def image_registry_url!(env) do + System.get_env(env) + end + @doc """ Parses and validates default runtime from env. """ diff --git a/lib/livebook/hubs/dockerfile.ex b/lib/livebook/hubs/dockerfile.ex index c951bb109..6b320e99a 100644 --- a/lib/livebook/hubs/dockerfile.ex +++ b/lib/livebook/hubs/dockerfile.ex @@ -3,6 +3,7 @@ defmodule Livebook.Hubs.Dockerfile do import Ecto.Changeset + alias Livebook.Config alias Livebook.Hubs @type config :: %{ @@ -82,8 +83,10 @@ defmodule Livebook.Hubs.Dockerfile do ) do base_image = Enum.find(Livebook.Config.docker_images(), &(&1.tag == config.docker_tag)) + image_registry_url = Config.image_registry_url() + image = """ - FROM ghcr.io/livebook-dev/livebook:#{base_image.tag} + FROM #{image_registry_url}:#{base_image.tag} """ image_envs = format_envs(base_image.env) @@ -316,7 +319,8 @@ defmodule Livebook.Hubs.Dockerfile do def online_docker_info(config, %Hubs.Team{} = hub, agent_key) do base_image = Enum.find(Livebook.Config.docker_images(), &(&1.tag == config.docker_tag)) - image = "ghcr.io/livebook-dev/livebook:#{base_image.tag}" + image_registry_url = Config.image_registry_url() + image = "#{image_registry_url}:#{base_image.tag}" env = [ {"LIVEBOOK_AGENT_NAME", "default"}, diff --git a/lib/livebook/k8s/pod.ex b/lib/livebook/k8s/pod.ex index d528cef26..6a2b349b1 100644 --- a/lib/livebook/k8s/pod.ex +++ b/lib/livebook/k8s/pod.ex @@ -19,6 +19,8 @@ defmodule Livebook.K8s.Pod do memory: 1Gi\ """ + alias Livebook.Config + @doc """ Returns the default pod template. """ @@ -73,7 +75,8 @@ defmodule Livebook.K8s.Pod do """ @spec set_docker_tag(map(), String.t()) :: map() def set_docker_tag(manifest, docker_tag) do - image = "ghcr.io/livebook-dev/livebook:#{docker_tag}" + image_registry_url = Config.image_registry_url() + image = "#{image_registry_url}:#{docker_tag}" put_in(manifest, ["spec", "containers", access_main_container(), "image"], image) end diff --git a/lib/livebook/runtime/fly.ex b/lib/livebook/runtime/fly.ex index de0d86250..7d16dd3b0 100644 --- a/lib/livebook/runtime/fly.ex +++ b/lib/livebook/runtime/fly.ex @@ -51,6 +51,7 @@ defmodule Livebook.Runtime.Fly do use GenServer, restart: :temporary + alias Livebook.Config alias Livebook.Runtime.RemoteUtils @type t :: %__MODULE__{ @@ -200,7 +201,10 @@ defmodule Livebook.Runtime.Fly do defp create_machine(config, runtime_data) do base_image = Enum.find(Livebook.Config.docker_images(), &(&1.tag == config.docker_tag)) - image = "ghcr.io/livebook-dev/livebook:#{base_image.tag}" + + image_registry_url = Config.image_registry_url() + + image = "#{image_registry_url}:#{base_image.tag}" env = Map.merge(