provision and use a docker registry repository
This commit is contained in:
parent
457cb7f752
commit
54e3872442
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue