provision and use a docker registry repository

This commit is contained in:
Rui Lopes 2020-03-28 16:23:00 +00:00
parent 457cb7f752
commit 54e3872442
5 changed files with 279 additions and 2 deletions

2
Vagrantfile vendored
View File

@ -27,7 +27,9 @@ Vagrant.configure(2) do |config|
config.vm.synced_folder '.', '/vagrant', type: 'nfs' config.vm.synced_folder '.', '/vagrant', type: 'nfs'
end end
config.vm.provision :shell, path: 'provision/provision-base.sh' config.vm.provision :shell, path: 'provision/provision-base.sh'
config.vm.provision :shell, path: 'provision/provision-docker.sh'
config.vm.provision :shell, path: 'provision/provision-nexus.sh' config.vm.provision :shell, path: 'provision/provision-nexus.sh'
config.vm.provision :shell, path: 'provision/use-docker-repository.sh'
config.vm.provision :shell, path: 'provision/use-raw-repository.sh' config.vm.provision :shell, path: 'provision/use-raw-repository.sh'
config.vm.provision :shell, path: 'provision/use-maven-repository-from-mvn.sh' config.vm.provision :shell, path: 'provision/use-maven-repository-from-mvn.sh'
config.vm.provision :shell, path: 'provision/use-maven-repository-from-gradle.sh' config.vm.provision :shell, path: 'provision/use-maven-repository-from-gradle.sh'

View File

@ -129,6 +129,96 @@ server {
proxy_pass http://127.0.0.1:8081; proxy_pass http://127.0.0.1:8081;
} }
} }
# docker-group repository.
server {
listen 5001 ssl http2;
server_name $config_fqdn;
access_log /var/log/nginx/$config_fqdn-docker-group.access.log;
ssl_certificate /etc/ssl/private/$config_fqdn-crt.pem;
ssl_certificate_key /etc/ssl/private/$config_fqdn-keypair.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# see https://github.com/cloudflare/sslconfig/blob/master/conf
# see https://blog.cloudflare.com/it-takes-two-to-chacha-poly/
# see https://blog.cloudflare.com/do-the-chacha-better-mobile-performance-with-cryptography/
# NB even though we have CHACHA20 here, the OpenSSL library that ships with Ubuntu 16.04 does not have it. so this is a nop. no problema.
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!aNULL:!MD5;
tcp_nodelay on;
client_max_body_size 10G;
proxy_send_timeout 120;
proxy_read_timeout 300;
proxy_buffering off;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_set_header Host \$host;
proxy_set_header X-Forwarded-Host \$host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
location / {
proxy_pass http://127.0.0.1:6001;
}
}
# docker-hub-proxy repository.
server {
listen 5002 ssl http2;
server_name $config_fqdn;
access_log /var/log/nginx/$config_fqdn-docker-hub-proxy.access.log;
ssl_certificate /etc/ssl/private/$config_fqdn-crt.pem;
ssl_certificate_key /etc/ssl/private/$config_fqdn-keypair.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# see https://github.com/cloudflare/sslconfig/blob/master/conf
# see https://blog.cloudflare.com/it-takes-two-to-chacha-poly/
# see https://blog.cloudflare.com/do-the-chacha-better-mobile-performance-with-cryptography/
# NB even though we have CHACHA20 here, the OpenSSL library that ships with Ubuntu 16.04 does not have it. so this is a nop. no problema.
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!aNULL:!MD5;
tcp_nodelay on;
client_max_body_size 10G;
proxy_send_timeout 120;
proxy_read_timeout 300;
proxy_buffering off;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_set_header Host \$host;
proxy_set_header X-Forwarded-Host \$host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
location / {
proxy_pass http://127.0.0.1:6002;
}
}
# docker-hosted repository.
server {
listen 5003 ssl http2;
server_name $config_fqdn;
access_log /var/log/nginx/$config_fqdn-docker-hosted.access.log;
ssl_certificate /etc/ssl/private/$config_fqdn-crt.pem;
ssl_certificate_key /etc/ssl/private/$config_fqdn-keypair.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# see https://github.com/cloudflare/sslconfig/blob/master/conf
# see https://blog.cloudflare.com/it-takes-two-to-chacha-poly/
# see https://blog.cloudflare.com/do-the-chacha-better-mobile-performance-with-cryptography/
# NB even though we have CHACHA20 here, the OpenSSL library that ships with Ubuntu 16.04 does not have it. so this is a nop. no problema.
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!aNULL:!MD5;
tcp_nodelay on;
client_max_body_size 10G;
proxy_send_timeout 120;
proxy_read_timeout 300;
proxy_buffering off;
proxy_set_header X-Forwarded-Proto \$scheme;
proxy_set_header Host \$host;
proxy_set_header X-Forwarded-Host \$host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
location / {
proxy_pass http://127.0.0.1:6003;
}
}
EOF EOF
ln -s ../sites-available/$config_fqdn.conf /etc/nginx/sites-enabled/ ln -s ../sites-available/$config_fqdn.conf /etc/nginx/sites-enabled/
systemctl restart nginx systemctl restart nginx

View File

@ -0,0 +1,59 @@
#!/bin/bash
set -eux
# NB execute apt-cache madison docker-ce to known the available versions.
docker_version="${1:-5:19.03.8~3-0~ubuntu-bionic}"; shift || true
registry_proxy_domain="${1:-$(hostname --fqdn)}"; shift || true
# NB as-of docker 19.03.8, there is still no way to specify a registry mirror credentials,
# as such, we cannot use our docker-group registry, instead we must use the docker-proxy
# registry and allow anonymous access to it.
# see https://github.com/moby/moby/issues/30880
registry_proxy_host="$registry_proxy_domain:5002"
registry_proxy_url="https://$registry_proxy_host"
# prevent apt-get et al from asking questions.
# NB even with this, you'll still get some warnings that you can ignore:
# dpkg-preconfigure: unable to re-open stdin: No such file or directory
export DEBIAN_FRONTEND=noninteractive
# install docker.
# see https://docs.docker.com/install/linux/docker-ce/ubuntu/
apt-get install -y apt-transport-https software-properties-common gnupg2
wget -qO- https://download.docker.com/linux/ubuntu/gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt-get update
apt-get install -y "docker-ce=$docker_version" "docker-ce-cli=$docker_version" containerd.io
# configure it.
cat >/etc/docker/daemon.json <<EOF
{
"experimental": false,
"debug": false,
"log-driver": "journald",
"labels": [
"os=linux"
],
"hosts": [
"fd://"
],
"containerd": "/run/containerd/containerd.sock",
"registry-mirror": "$registry_proxy_url"
}
EOF
# start docker without any command line flags as its entirely configured from daemon.json.
install -d /etc/systemd/system/docker.service.d
cat >/etc/systemd/system/docker.service.d/override.conf <<'EOF'
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd
EOF
systemctl daemon-reload
systemctl restart docker
# let the vagrant user manage docker.
usermod -aG docker vagrant
# kick the tires.
ctr version
docker version
docker info

View File

@ -66,6 +66,23 @@ repository.createNugetProxy("chocolatey.org-proxy", "https://chocolatey.org/api/
repository.createNugetGroup("chocolatey-group", ["chocolatey-hosted", "chocolatey.org-proxy"], "default") repository.createNugetGroup("chocolatey-group", ["chocolatey-hosted", "chocolatey.org-proxy"], "default")
// create a docker registry repository backed by the default blob store.
repository.createDockerHosted("docker-hosted", 6003, null, "default", true, true, WritePolicy.ALLOW, true)
// create a docker proxy repository backed by the default blob store.
// see https://help.sonatype.com/repomanager3/formats/docker-registry
// TODO set Allow Nexus Repository Manager to download and cache foreign layers.
// NB as-of docker 19.03.5, there is still no way to specify a registry mirror credentials...
// as such, we cannot use our docker-group registry, instead we must use the docker-proxy
// registry, enable the Docker Bearer Token Realm and allow anonymous access to it.
// see https://github.com/moby/moby/issues/30880
// NB this will make https://nexus.example.com:5002/v2/library/debian/manifests/buster-slim proxy
// to https://registry-1.docker.io/v2/library/debian/manifests/buster-slim
// https://registry-1.docker.io/v2/library/golang/tags/list
repository.createDockerProxy("docker-hub-proxy", "https://registry-1.docker.io", "HUB", null, 6002, null, "default", true, true, false)
// create a docker group repository that merges the docker-hosted and docker-hub-proxy together.
repository.createDockerGroup("docker-group", 6001, null, ["docker-hosted", "docker-hub-proxy"], true, "default", true)
// see http://stackoverflow.com/questions/8138164/groovy-generate-random-string-from-given-character-set // see http://stackoverflow.com/questions/8138164/groovy-generate-random-string-from-given-character-set
def random(String alphabet, int n) { def random(String alphabet, int n) {
new Random().with { new Random().with {
@ -94,12 +111,19 @@ taskConfiguration.setString("snapshotRetentionDays", "30")
taskScheduler.scheduleTask(taskConfiguration, new Daily(new Date().clearTime().next())) taskScheduler.scheduleTask(taskConfiguration, new Daily(new Date().clearTime().next()))
// enable the NuGet API-Key Realm. // NB you can list the available realms with realmManager.availableRealms.
realmManager = container.lookup(RealmManager.class.name) realmManager = container.lookup(RealmManager.class.name)
// enable the NuGet API-Key Realm.
realmManager.enableRealm("NuGetApiKey") realmManager.enableRealm("NuGetApiKey")
// enable the npm Bearer Token Realm. // enable the npm Bearer Token Realm.
realmManager.enableRealm("NpmToken") realmManager.enableRealm("NpmToken")
// enable the Docker Bearer Token Realm.
realmManager.enableRealm("DockerToken")
// allow Anonymous access to nexus to be able to use the docker-hub-proxy repository.
// NB this might be worked around by creating an docker-anonymous user and force its
// credentials in the nginx reverse-proxy configuration.
// see https://github.com/moby/moby/issues/30880#issuecomment-601513505
security.anonymousAccess = true
// set the admin password. // set the admin password.
// NB we set it to something different than the default (admin123) to get // NB we set it to something different than the default (admin123) to get

View File

@ -0,0 +1,102 @@
#!/bin/bash
set -eux
nexus_domain=$(hostname --fqdn)
docker_group_registry_host="$nexus_domain:5001"
docker_hosted_registry_host="$nexus_domain:5003"
registry_username='alice.doe'
registry_password='password'
# login into the registry.
echo "logging in the registry $docker_group_registry_host..."
docker login $docker_group_registry_host --username "$registry_username" --password-stdin <<EOF
$registry_password
EOF
echo "logging in the registry $docker_hosted_registry_host..."
docker login $docker_hosted_registry_host --username "$registry_username" --password-stdin <<EOF
$registry_password
EOF
mkdir -p tmp/use-docker-repository && cd tmp/use-docker-repository
#
# test the docker repository.
cat >main.go <<'EOF'
package main
import (
"fmt"
"flag"
"log"
"net/http"
)
func main() {
log.SetFlags(0)
var listenAddress = flag.String("listen", ":8000", "Listen address.")
flag.Parse()
if flag.NArg() != 0 {
flag.Usage()
log.Fatalf("\nERROR You MUST NOT pass any positional arguments")
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Printf("%s %s%s\n", r.Method, r.Host, r.URL)
fmt.Fprintf(w, "%s %s%s\n", r.Method, r.Host, r.URL)
})
fmt.Printf("Listening at http://%s\n", *listenAddress)
err := http.ListenAndServe(*listenAddress, nil)
if err != nil {
log.Fatalf("Failed to ListenAndServe: %v", err)
}
}
EOF
cat >Dockerfile <<'EOF'
FROM golang:1.14.1-buster as builder
WORKDIR /app
COPY main.go .
RUN CGO_ENABLED=0 go build -ldflags="-s" -o=go-hello
# NB we use the buster-slim (instead of scratch) image so we
# can enter the container to execute bash etc.
FROM debian:buster-slim
COPY --from=builder /app/go-hello .
WORKDIR /
EXPOSE 8000
ENTRYPOINT ["/go-hello"]
EOF
# build the image.
docker build -t go-hello:1.0.0 .
docker image ls go-hello:1.0.0
# push the image to the docker-hosted registry.
docker tag go-hello:1.0.0 $docker_hosted_registry_host/go-hello:1.0.0
docker push $docker_hosted_registry_host/go-hello:1.0.0
# show the repository (image) details directly from the docker-hosted registry.
# see https://docs.docker.com/registry/spec/api/
# see https://docs.docker.com/registry/spec/manifest-v2-2/
wget -qO- --user "$registry_username" --password "$registry_password" \
"https://$docker_hosted_registry_host/v2/go-hello/tags/list" | jq .
manifest=$(wget -qO- --user "$registry_username" --password "$registry_password" \
'--header=Accept: application/vnd.docker.distribution.manifest.v2+json' \
"https://$docker_hosted_registry_host/v2/go-hello/manifests/1.0.0")
config_digest=$(echo "$manifest" | jq -r .config.digest)
echo "$manifest" | jq .
wget -qO- --user "$registry_username" --password "$registry_password" \
"https://$docker_hosted_registry_host/v2/go-hello/blobs/$config_digest" | jq .
# remove it from local cache.
docker image remove go-hello:1.0.0
docker image remove $docker_hosted_registry_host/go-hello:1.0.0
# pull it from the docker-group registry.
docker pull $docker_group_registry_host/go-hello:1.0.0