From fb47728ddc4e31a390417c8364614ca6dc934255 Mon Sep 17 00:00:00 2001 From: Alvaro Saurin Date: Fri, 13 Mar 2020 11:09:18 +0100 Subject: [PATCH] Option for using the local k3d registry as a proxy for the Docker Hub Signed-off-by: Alvaro Saurin --- cli/commands.go | 33 +++++++++++++++++---------------- cli/registry.go | 38 ++++++++++++++++++++++++++++++-------- cli/types.go | 33 +++++++++++++++++---------------- docs/registries.md | 16 ++++++++++++++++ main.go | 4 ++++ 5 files changed, 84 insertions(+), 40 deletions(-) diff --git a/cli/commands.go b/cli/commands.go index b8e7344c..36314083 100644 --- a/cli/commands.go +++ b/cli/commands.go @@ -236,22 +236,23 @@ func CreateCluster(c *cli.Context) error { * Defines, with which specifications, the cluster and the nodes inside should be created */ clusterSpec := &ClusterSpec{ - AgentArgs: k3AgentArgs, - APIPort: *apiPort, - AutoRestart: c.Bool("auto-restart"), - ClusterName: c.String("name"), - Env: env, - NodeToLabelSpecMap: labelmap, - Image: image, - NodeToPortSpecMap: portmap, - PortAutoOffset: c.Int("port-auto-offset"), - RegistriesFile: registriesFile, - RegistryEnabled: c.Bool("enable-registry"), - RegistryName: c.String("registry-name"), - RegistryPort: c.Int("registry-port"), - RegistryVolume: c.String("registry-volume"), - ServerArgs: k3sServerArgs, - Volumes: volumesSpec, + AgentArgs: k3AgentArgs, + APIPort: *apiPort, + AutoRestart: c.Bool("auto-restart"), + ClusterName: c.String("name"), + Env: env, + NodeToLabelSpecMap: labelmap, + Image: image, + NodeToPortSpecMap: portmap, + PortAutoOffset: c.Int("port-auto-offset"), + RegistriesFile: registriesFile, + RegistryEnabled: c.Bool("enable-registry"), + RegistryCacheEnabled: c.Bool("enable-registry-cache"), + RegistryName: c.String("registry-name"), + RegistryPort: c.Int("registry-port"), + RegistryVolume: c.String("registry-volume"), + ServerArgs: k3sServerArgs, + Volumes: volumesSpec, } /****************** diff --git a/cli/registry.go b/cli/registry.go index c6ac56db..efc96564 100644 --- a/cli/registry.go +++ b/cli/registry.go @@ -18,17 +18,23 @@ import ( "gopkg.in/yaml.v2" ) -const defaultRegistryContainerName = "k3d-registry" +const ( + defaultRegistryContainerName = "k3d-registry" -const defaultRegistryImage = "registry:2" + defaultRegistryImage = "registry:2" -// Default registry port, both for the external and the internal ports -// Note well, that the internal port is never changed. -const defaultRegistryPort = 5000 + // Default registry port, both for the external and the internal ports + // Note well, that the internal port is never changed. + defaultRegistryPort = 5000 -const defaultFullRegistriesPath = "/etc/rancher/k3s/registries.yaml" + defaultFullRegistriesPath = "/etc/rancher/k3s/registries.yaml" -const defaultRegistryMountPath = "/var/lib/registry" + defaultRegistryMountPath = "/var/lib/registry" + + defaultDockerHubAddress = "docker.io" + + defaultDockerRegistryHubAddress = "registry-1.docker.io" +) // default labels assigned to the registry container var defaultRegistryContainerLabels = map[string]string{ @@ -105,10 +111,17 @@ func writeRegistriesConfigInContainer(spec *ClusterSpec, ID string) error { privRegistries.Mirrors = map[string]Mirror{} } - // the add the private registry + // then add the private registry privRegistries.Mirrors[registryExternalAddress] = Mirror{ Endpoints: []string{fmt.Sprintf("http://%s", registryInternalAddress)}, } + + // with the cache, redirect all the PULLs to the Docker Hub to the local registry + if spec.RegistryCacheEnabled { + privRegistries.Mirrors[defaultDockerHubAddress] = Mirror{ + Endpoints: []string{fmt.Sprintf("http://%s", registryInternalAddress)}, + } + } } d, err := yaml.Marshal(&privRegistries) @@ -214,6 +227,15 @@ func createRegistry(spec ClusterSpec) (string, error) { Labels: containerLabels, } + // we can enable the cache in the Registry by just adding a new env variable + // (see https://docs.docker.com/registry/configuration/#override-specific-configuration-options) + if spec.RegistryCacheEnabled { + log.Printf("Activating pull-through cache to Docker Hub\n") + cacheConfigKey := "REGISTRY_PROXY_REMOTEURL" + cacheConfigValues := fmt.Sprintf("https://%s", defaultDockerRegistryHubAddress) + config.Env = []string{fmt.Sprintf("%s=%s", cacheConfigKey, cacheConfigValues)} + } + id, err := createContainer(config, hostConfig, networkingConfig, defaultRegistryContainerName) if err != nil { return "", fmt.Errorf(" Couldn't create registry container %s\n%w", defaultRegistryContainerName, err) diff --git a/cli/types.go b/cli/types.go index dac7e1c9..d3cb3c6e 100644 --- a/cli/types.go +++ b/cli/types.go @@ -35,22 +35,23 @@ type Cluster struct { // ClusterSpec defines the specs for a cluster that's up for creation type ClusterSpec struct { - AgentArgs []string - APIPort apiPort - AutoRestart bool - ClusterName string - Env []string - NodeToLabelSpecMap map[string][]string - Image string - NodeToPortSpecMap map[string][]string - PortAutoOffset int - RegistriesFile string - RegistryEnabled bool - RegistryName string - RegistryPort int - RegistryVolume string - ServerArgs []string - Volumes *Volumes + AgentArgs []string + APIPort apiPort + AutoRestart bool + ClusterName string + Env []string + NodeToLabelSpecMap map[string][]string + Image string + NodeToPortSpecMap map[string][]string + PortAutoOffset int + RegistriesFile string + RegistryEnabled bool + RegistryCacheEnabled bool + RegistryName string + RegistryPort int + RegistryVolume string + ServerArgs []string + Volumes *Volumes } // PublishedPorts is a struct used for exposing container ports on the host system diff --git a/docs/registries.md b/docs/registries.md index d6a1f957..e53a665b 100644 --- a/docs/registries.md +++ b/docs/registries.md @@ -129,6 +129,22 @@ The easiest solution for this is to add an entry in your `/etc/hosts` file like Once again, this will only work with k3s >= v0.10.0 (see the [section below](#k3s-old) when using k3s <= v0.9.1) +### Local registry volume + +The local k3d registry uses a volume for storying the images. This volume will be destroyed +when the k3d registry is released. In order to persist this volume and make these images survive +the removal of the registry, you can specify a volume with the `--registry-volume` and use the +`--keep-registry-volume` flag when deleting the cluster. This will create a volume with the given +name the first time the registry is used, while successive invocations will just mount this +existing volume in the k3d registry container. + +### Docker Hub cache + +The local k3d registry can also be used for caching images from the Docker Hub. You can start the +registry as a pull-through cache when the cluster is created with `--enable-registry-cache`. Used +in conjuction with `--registry-volume`/`--keep-registry-volume` can speed up all the downloads +from the Hub by keeping a persistent cache of images in your local machine. + ## Testing your registry You should test that you can diff --git a/main.go b/main.go index a8c59f97..52ba0239 100644 --- a/main.go +++ b/main.go @@ -144,6 +144,10 @@ func main() { Name: "registries-file", Usage: "registries.yaml config file", }, + cli.BoolFlag{ + Name: "enable-registry-cache", + Usage: "Use the local registry as a cache for the Docker Hub", + }, }, Action: run.CreateCluster, },