我租了一台服务器,想在上面托管我自己的 Docker 容器注册表。服务器使用Ubuntu 24.04,安装了docker和docker compose。
现在,我创建了这个 docker-compose.yml 来在服务器上运行注册表:
version: '3'
services:
registry:
image: registry:2
ports:
- "127.0.0.1:5000:5000"
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry
volumes:
- ./data:/var/lib/registry
我正在使用
docker compose up
运行此程序。
然后我设置了从客户端到服务器的 ssh 隧道ssh -L 5000:localhost:5000 user@server
。
现在,作为健全性检查,我在客户端上运行此命令:
$ curl -X GET http://127.0.0.1:5000/v2/_catalog
{"repositories":[]}
输出看起来很合理,是一个空的存储库列表。在服务器上,我正在运行不带
docker compose up
标志的 -d
,以查看日志输出,它显示:
registry-1 | time="2024-10-08T10:24:16.455126761Z" level=info msg="response completed" go.version=go1.20.8 http.request.host="127.0.0.1:5000" http.request.id=133d3573-9be6-48fe-9102-ffdac2706c93 http.request.method=GET http.request.remoteaddr="172.18.0.1:35336" http.request.uri="/v2/_catalog" http.request.useragent="curl/8.4.0" http.response.contenttype="application/json; charset=utf-8" http.response.duration=2.285188ms http.response.status=200 http.response.written=20
registry-1 | 172.18.0.1 - - [08/Oct/2024:10:24:16 +0000] "GET /v2/_catalog HTTP/1.1" 200 20 "" "curl/8.4.0"
现在我想标记并推送图像。我在客户端上运行以下命令:
$ docker tag hello-world 127.0.0.1:5000/test:latest
$ docker push 127.0.0.1:5000/test:latest
The push refers to repository [127.0.0.1:5000/test]
Get "http://127.0.0.1:5000/v2/": dial tcp 127.0.0.1:5000: connect: connection refused
我也尝试用
localhost
而不是 127.0.0.1
来标记它,但结果是相同的。
为了彻底检查注册表是否正常工作,我在服务器上尝试了相同的操作:
root@Ubuntu-2404-noble-amd64-base ~ # docker tag hello-world 127.0.0.1:5000/test:latest
root@Ubuntu-2404-noble-amd64-base ~ # docker push 127.0.0.1:5000/test:latest
The push refers to repository [127.0.0.1:5000/test]
ac28800ec8bb: Pushed latest: digest: sha256:d37ada95d47ad12224c205a938129df7a3e52345828b4fa27b03a98825d1e2e7 size: 524
所以这有效,注册表似乎工作正常。作为另一个健全性检查,让我们在客户端上重复curl命令:
$ curl -X GET http://127.0.0.1:5000/v2/_catalog
{"repositories":["test"]}
所以这似乎正确地指向远程服务器上的 docker 注册表。 ssh 隧道似乎可以工作。 但是,可以在服务器上标记和推送图像的完全相同的命令会因客户端上的连接错误而失败。
我在客户端上使用MacOS。我在 Docker 引擎的设置中设置了不安全的注册表:
"insecure-registries": [
"127.0.0.1:5000",
"localhost:5000"
]
此时我已不知所措。您能告诉我如何解决此问题吗?
+---------+ +---------+
| clientA | ------------> | serverB |
+---------+ +---------+
macOS-Client Ubuntu-2404-noble-amd64-base
yourServer Public IP
yourServerFQDN name
请确认以下有关您服务器的信息:
+---------+ +---------+
| clientA | -------------------------> | serverB |
+---------+ +---------+
|
| (docker-compose)
+----------------------+-----------------+
|port 443 (https) | port 5000
+------------+ +-----------------+
| Nginx | <---------------------> | Docker Registry |
+------------+ +-----------------+
| (Front-end) | (Back-end)
+----------------------------------------+
下面以我内部环境的机器为例,所以IP和服务器FQDN名称都是示例。请根据您自己的 Sercer 设置进行调整。
以我为例:
由于我没有DNS,为了简单起见,我直接修改了
/etc/hosts
的文件内容。
/etc/hosts
添加这是
/etc/hosts
192.168.56.112 demoserver.demo.local
(clientA和serverB都需要修改)
创建一个目录
my_docker_registry
作为您的项目目录。
my_docker_registry <directory>
├── docker-compose.yml
├── my-demo-registry <directory>
│ ├── auth <directory>
│ │ └── htpasswd
│ └── data <directory>
└── nginx
├── certs <directory>
├── Dockerfile
└── nginx.conf
所有指令均在
my_docker_registry
(项目根目录)中执行。
mkdir -p my-demo-registry/auth
mkdir -p my-demo-registry/data
sudo apt install -y apache2-utils
# c create file
htpasswd -Bc my-demo-registry/auth/htpasswd demo01user
# second user do not create file
htpasswd -B my-demo-registry/auth/htpasswd demo02user
创建两个用户:
所有指令均在
my_docker_registry
(项目根目录)中执行。
mkdir -p nginx/certs
以下内容根据https://goharbor.io/docs/2.5.0/install-config/configure-https/的内容进行调整,生成ssl凭证。
以下将指令执行目录切换到nginx/certs目录。
cd nginx/certs
openssl genrsa -out ca.key 4096
注意,请根据您设置的服务器的FQDN名称调整以下命令的内容(例如:
demoserver.demo.local
)。
openssl req -x509 -new -nodes -sha512 -days 3650 \
-subj "/C=CN/ST=NewYork/L=NewYork/O=example/OU=Personal/CN=demoserver.demo.local" \
-key ca.key \
-out ca.crt
openssl genrsa -out demoserver.demo.local.key 4096
openssl req -sha512 -new \
-subj "/C=CN/ST=NewYork/L=NewYork/O=example/OU=Personal/CN=demoserver.demo.local" \
-key demoserver.demo.local.key \
-out demoserver.demo.local.csr
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1=demoserver.demo.local
DNS.2=demopc
DNS.3=localhost
EOF
openssl x509 -req -sha512 -days 3650 \
-extfile v3.ext \
-CA ca.crt \
-CAkey ca.key \
-CAcreateserial \
-in demoserver.demo.local.csr \
-out demoserver.demo.local.crt
openssl x509 \
-inform PEM \
-in demoserver.demo.local.crt \
-out demoserver.demo.local.cert
sudo mkdir -p /etc/docker/certs.d/demoserver.demo.local
sudo cp demoserver.demo.local.cert /etc/docker/certs.d/demoserver.demo.local/
sudo cp demoserver.demo.local.key /etc/docker/certs.d/demoserver.demo.local/
sudo cp ca.crt /etc/docker/certs.d/demoserver.demo.local/
sudo systemctl restart docker
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
RUN mkdir -p /etc/nginx/certs
COPY certs/demoserver.demo.local.crt /etc/nginx/certs/
COPY certs/demoserver.demo.local.key /etc/nginx/certs/
events {
worker_connections 1024;
}
http {
server {
listen 443 ssl;
# Replace with your domain name
server_name demoserver.demo.local;
# SSL Certificate Path
ssl_certificate /etc/nginx/certs/demoserver.demo.local.crt;
# SSL key path
ssl_certificate_key /etc/nginx/certs/demoserver.demo.local.key;
location / {
# Reverse proxy to Docker Registry
# proxy_pass http://localhost:5000;
proxy_pass http://registry:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
version: '3.3'
services:
registry:
image: registry:2
ports:
# For internal access only
- "5000:5000"
environment:
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
volumes:
- ./my-demo-registry/auth:/auth
- ./my-demo-registry/data:/var/lib/registry
# Data Volume
# - registry_data:/var/lib/registry
nginx:
build: ./nginx
ports:
# Map to port 443 on the host
- "443:443"
depends_on:
- registry
volumes:
registry_data:
docker-compose build
docker-compose up
docker ps
您将看到两个容器正在执行。一个是
nginx
和 registry
。
docker login https://demoserver.demo.local
输入用户名和密码。 (我的例子:
demo01user
)
会回来
Login Succeeded
docker pull hello-world
docker tag hello-world demoserver.demo.local/demo01user/hello-world:0.0.1
docker push demoserver.demo.local/demo01user/hello-world:0.0.1
docker image ls
得到
REPOSITORY TAG IMAGE ID CREATED SIZE
...
demoserver.demo.local/demo01user/hello-world 0.0.1 d2c94e258dcb 17 months ago 13.3kB
hello-world latest d2c94e258dcb 17 months ago 13.3kB
现在将 serverB 上的 nginx/certs 目录复制到您的 clientA 主机(您的 macOS)
执行以下指令
注意,macOS下相关说明可能需要调整。
sudo mkdir -p /etc/docker/certs.d/demoserver.demo.local
sudo cp demoserver.demo.local.cert /etc/docker/certs.d/demoserver.demo.local/
sudo cp demoserver.demo.local.key /etc/docker/certs.d/demoserver.demo.local/
sudo cp ca.crt /etc/docker/certs.d/demoserver.demo.local/
sudo systemctl restart docker
注意:这是在 clientA(即您的 macOS)上执行的。
由于我没有DNS,为了简单起见,我直接修改了
/etc/hosts
的文件内容。
/etc/hosts
添加这是
/etc/hosts
192.168.56.112 demoserver.demo.local
现在,在 clientA 上执行:
docker run demoserver.demo.local/demo01user/hello-world:0.0.1
您应该能够看到从serveB检索到的hello-world`的执行结果。
您也可以在本地机器上查看镜像。
docker image ls